From 765042155c8a0baf57f0a356fda171ac7cd22d53 Mon Sep 17 00:00:00 2001 From: dhoomakethu Date: Sat, 16 Feb 2019 13:46:55 +0530 Subject: [PATCH] Fix #387 Transactions failing on 2.2.0rc2. --- CHANGELOG.rst | 1 + pymodbus/server/sync.py | 13 +++++++++--- pymodbus/transaction.py | 45 +++++++++++++++++++++++------------------ pymodbus/version.py | 2 +- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e76039699..ccdeb179b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,7 @@ from pymodbus.client.asynchronous import ModbusTcpClient * Support broadcasting in Modbus Client and Servers (sync). * Fix asyncio examples. * Improved logging in Modbus Server . +* Fix regression introduced in 2.2.0rc2 (Modbus sync client transaction failing) * Minor update in factory.py, now server logs prints received request instead of only function code ``` diff --git a/pymodbus/server/sync.py b/pymodbus/server/sync.py index d51d4cdc4..9492265f7 100644 --- a/pymodbus/server/sync.py +++ b/pymodbus/server/sync.py @@ -181,14 +181,21 @@ def handle(self): reset_frame = False while self.running: try: + units = self.server.context.slaves() data = self.request.recv(1024) if not data: self.running = False + else: + if not isinstance(units, (list, tuple)): + units = [units] + # if broadcast is enabled make sure to + # process requests to address 0 + if self.server.broadcast_enable: + if 0 not in units: + units.append(0) + if _logger.isEnabledFor(logging.DEBUG): _logger.debug('Handling data: ' + hexlify_packets(data)) - # if not self.server.control.ListenOnly: - - units = self.server.context.slaves() single = self.server.context.single self.framer.processIncomingPacket(data, self.execute, units, single=single) diff --git a/pymodbus/transaction.py b/pymodbus/transaction.py index 17be1507b..579fcd86d 100644 --- a/pymodbus/transaction.py +++ b/pymodbus/transaction.py @@ -112,14 +112,17 @@ def execute(self, request): ) retries = self.retries request.transaction_id = self.getNextTID() - _logger.debug("Running transaction %d" % request.transaction_id) + _logger.debug("Running transaction " + "{}".format(request.transaction_id)) _buffer = hexlify_packets(self.client.framer._buffer) if _buffer: - _logger.debug("Clearing current Frame : - {}".format(_buffer)) + _logger.debug("Clearing current Frame " + ": - {}".format(_buffer)) self.client.framer.resetFrame() - - if request.unit_id == 0 and self.client.broadcast_enable: - response, last_exception = self._transact(request, None) + broadcast = (self.client.broadcast_enable + and request.unit_id == 0) + if broadcast: + self._transact(request, None, broadcast=True) response = b'Broadcast write sent - no response expected' else: expected_response_length = None @@ -139,10 +142,12 @@ def execute(self, request): full = True if not expected_response_length: expected_response_length = Defaults.ReadSize - response, last_exception = self._transact(request, - expected_response_length, - full=full - ) + response, last_exception = self._transact( + request, + expected_response_length, + full=full, + broadcast=broadcast + ) if not response and ( request.unit_id not in self._no_response_devices): self._no_response_devices.append(request.unit_id) @@ -193,7 +198,7 @@ def execute(self, request): self.client.state = ModbusTransactionState.TRANSACTION_COMPLETE return ex - def _transact(self, packet, response_length, full=False): + def _transact(self, packet, response_length, full=False, broadcast=False): """ Does a Write and Read transaction :param packet: packet to be sent @@ -209,20 +214,20 @@ def _transact(self, packet, response_length, full=False): if _logger.isEnabledFor(logging.DEBUG): _logger.debug("SEND: " + hexlify_packets(packet)) size = self._send(packet) - if response_length is not None: - if size: - _logger.debug("Changing transaction state from 'SENDING' " - "to 'WAITING FOR REPLY'") - self.client.state = ModbusTransactionState.WAITING_FOR_REPLY - result = self._recv(response_length, full) - if _logger.isEnabledFor(logging.DEBUG): - _logger.debug("RECV: " + hexlify_packets(result)) - else: + if broadcast: if size: _logger.debug("Changing transaction state from 'SENDING' " "to 'TRANSACTION_COMPLETE'") self.client.state = ModbusTransactionState.TRANSACTION_COMPLETE - result = b'' + return b'', None + if size: + _logger.debug("Changing transaction state from 'SENDING' " + "to 'WAITING FOR REPLY'") + self.client.state = ModbusTransactionState.WAITING_FOR_REPLY + result = self._recv(response_length, full) + if _logger.isEnabledFor(logging.DEBUG): + _logger.debug("RECV: " + hexlify_packets(result)) + except (socket.error, ModbusIOException, InvalidMessageReceivedException) as msg: self.client.close() diff --git a/pymodbus/version.py b/pymodbus/version.py index 3e81d7af5..13a4dff55 100644 --- a/pymodbus/version.py +++ b/pymodbus/version.py @@ -41,7 +41,7 @@ def __str__(self): return '[%s, version %s]' % (self.package, self.short()) -version = Version('pymodbus', 2, 2, 0, "rc2") +version = Version('pymodbus', 2, 2, 0, "rc3") version.__name__ = 'pymodbus' # fix epydoc error