def testExecute(self): client = MagicMock() client.framer = self._ascii client.framer._buffer = b'deadbeef' client.framer.processIncomingPacket = MagicMock() client.framer.processIncomingPacket.return_value = None client.framer.buildPacket = MagicMock() client.framer.buildPacket.return_value = b'deadbeef' client.framer.sendPacket = MagicMock() client.framer.sendPacket.return_value = len(b'deadbeef') request = MagicMock() request.get_response_pdu_size.return_value = 10 request.unit_id = 1 tm = ModbusTransactionManager(client) tm._recv = MagicMock(return_value=b'abcdef') self.assertEqual(tm.retries, 3) self.assertEqual(tm.retry_on_empty, False) # tm._transact = MagicMock() # some response # tm._transact.return_value = (b'abcdef', None) tm.getTransaction = MagicMock() tm.getTransaction.return_value = 'response' response = tm.execute(request) self.assertEqual(response, 'response') # No response tm._recv = MagicMock(return_value=b'abcdef') # tm._transact.return_value = (b'', None) tm.transactions = [] tm.getTransaction = MagicMock() tm.getTransaction.return_value = None response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # No response with retries tm.retry_on_empty = True tm._recv = MagicMock(side_effect=iter([b'', b'abcdef'])) # tm._transact.side_effect = [(b'', None), (b'abcdef', None)] response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # retry on invalid response tm.retry_on_invalid = True tm._recv = MagicMock(side_effect=iter([b'', b'abcdef', b'deadbe', b'123456'])) # tm._transact.side_effect = [(b'', None), (b'abcdef', None)] response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # Unable to decode response tm._recv = MagicMock(side_effect=ModbusIOException()) # tm._transact.side_effect = [(b'abcdef', None)] client.framer.processIncomingPacket.side_effect = MagicMock(side_effect=ModbusIOException()) self.assertIsInstance(tm.execute(request), ModbusIOException)
def testExecute(self): client = MagicMock() client.framer = self._ascii client.framer._buffer = b'deadbeef' client.framer.processIncomingPacket = MagicMock() client.framer.processIncomingPacket.return_value = None client.framer.buildPacket = MagicMock() client.framer.buildPacket.return_value = b'deadbeef' client.framer.sendPacket = MagicMock() client.framer.sendPacket.return_value = len(b'deadbeef') request = MagicMock() request.get_response_pdu_size.return_value = 10 request.unit_id = 1 tm = ModbusTransactionManager(client) tm._recv = MagicMock(return_value=b'abcdef') self.assertEqual(tm.retries, 3) self.assertEqual(tm.retry_on_empty, False) # tm._transact = MagicMock() # some response # tm._transact.return_value = (b'abcdef', None) tm.getTransaction = MagicMock() tm.getTransaction.return_value = 'response' response = tm.execute(request) self.assertEqual(response, 'response') # No response tm._recv = MagicMock(return_value=b'abcdef') # tm._transact.return_value = (b'', None) tm.transactions = [] tm.getTransaction = MagicMock() tm.getTransaction.return_value = None response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # No response with retries tm.retry_on_empty = True tm._recv = MagicMock(side_effect=iter([b'', b'abcdef'])) # tm._transact.side_effect = [(b'', None), (b'abcdef', None)] response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # Unable to decode response tm._recv = MagicMock(side_effect=ModbusIOException()) # tm._transact.side_effect = [(b'abcdef', None)] client.framer.processIncomingPacket.side_effect = MagicMock(side_effect=ModbusIOException()) self.assertIsInstance(tm.execute(request), ModbusIOException)
class ModbusClientProtocol(protocol.Protocol, ModbusClientMixin): ''' This represents the base modbus client protocol. All the application layer code is deferred to a higher level wrapper. ''' def __init__(self, framer=None): ''' Initializes the framer module :param framer: The framer to use for the protocol ''' self.framer = framer or ModbusSocketFramer(ClientDecoder()) serial = not isinstance(framer, ModbusSocketFramer) self.transaction = ModbusTransactionManager(self, serial) self._connected = False def connectionMade(self): ''' Called upon a successful client connection. ''' _logger.debug("Client connected to modbus server") self._connected = True def connectionLost(self, reason): ''' Called upon a client disconnect :param reason: The reason for the disconnect ''' _logger.debug("Client disconnected from modbus server: %s" % reason) self._connected = False for tid in self.transaction: self.transaction.getTransaction(tid).errback(Failure( ConnectionException('Connection lost during request'))) def dataReceived(self, data): ''' Get response, check for valid message, decode result :param data: The data returned from the server ''' self.framer.processIncomingPacket(data, self._handleResponse) def execute(self, request): ''' Starts the producer to send the next request to consumer.write(Frame(request)) ''' request.transaction_id = _manager.getNextTID() packet = self.framer.buildPacket(request) self.transport.write(packet) return self._buildResponse(request.transaction_id) def _handleResponse(self, reply): ''' Handle the processed response and link to correct deferred :param reply: The reply to process ''' if reply is not None: tid = reply.transaction_id handler = self.transaction.getTransaction(tid) if handler: handler.callback(reply) else: _logger.debug("Unrequested message: " + str(reply)) def _buildResponse(self, tid): ''' Helper method to return a deferred response for the current request. :param tid: The transaction identifier for this response :returns: A defer linked to the latest request ''' if not self._connected: return defer.fail(Failure( ConnectionException('Client is not connected'))) d = defer.Deferred() self.transaction.addTransaction(d, tid) return d
def testExecute(self, mock_time): mock_time.time.side_effect = count() client = MagicMock() client.framer = self._ascii client.framer._buffer = b'deadbeef' client.framer.processIncomingPacket = MagicMock() client.framer.processIncomingPacket.return_value = None client.framer.buildPacket = MagicMock() client.framer.buildPacket.return_value = b'deadbeef' client.framer.sendPacket = MagicMock() client.framer.sendPacket.return_value = len(b'deadbeef') client.framer.decode_data = MagicMock() client.framer.decode_data.return_value = { "unit": 1, "fcode": 222, "length": 27 } request = MagicMock() request.get_response_pdu_size.return_value = 10 request.unit_id = 1 request.function_code = 222 tm = ModbusTransactionManager(client) tm._recv = MagicMock(return_value=b'abcdef') self.assertEqual(tm.retries, 3) self.assertEqual(tm.retry_on_empty, False) # tm._transact = MagicMock() # some response # tm._transact.return_value = (b'abcdef', None) tm.getTransaction = MagicMock() tm.getTransaction.return_value = 'response' response = tm.execute(request) self.assertEqual(response, 'response') # No response tm._recv = MagicMock(return_value=b'abcdef') # tm._transact.return_value = (b'', None) tm.transactions = [] tm.getTransaction = MagicMock() tm.getTransaction.return_value = None response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # No response with retries tm.retry_on_empty = True tm._recv = MagicMock(side_effect=iter([b'', b'abcdef'])) # tm._transact.side_effect = [(b'', None), (b'abcdef', None)] response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # wrong handle_local_echo tm._recv = MagicMock( side_effect=iter([b'abcdef', b'deadbe', b'123456'])) client.handle_local_echo = True tm.retry_on_empty = False tm.retry_on_invalid = False self.assertEqual( tm.execute(request).message, '[Input/Output] Wrong local echo') client.handle_local_echo = False # retry on invalid response tm.retry_on_invalid = True tm._recv = MagicMock( side_effect=iter([b'', b'abcdef', b'deadbe', b'123456'])) # tm._transact.side_effect = [(b'', None), (b'abcdef', None)] response = tm.execute(request) self.assertIsInstance(response, ModbusIOException) # Unable to decode response tm._recv = MagicMock(side_effect=ModbusIOException()) # tm._transact.side_effect = [(b'abcdef', None)] client.framer.processIncomingPacket.side_effect = MagicMock( side_effect=ModbusIOException()) self.assertIsInstance(tm.execute(request), ModbusIOException) # Broadcast client.broadcast_enable = True request.unit_id = 0 response = tm.execute(request) self.assertEqual(response, b'Broadcast write sent - ' b'no response expected')