Skip to content

Commit c5a9eae

Browse files
committed
Implement getResponseSize()
getResponseSize() can be used to know in advance how many bytes needs to be read after request. Using this information it is not needed to wait for serial port timeout during receive.
1 parent 9044524 commit c5a9eae

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

pymodbus/pdu.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ def doException(self, exception):
106106
(self.function_code, exception))
107107
return ExceptionResponse(self.function_code, exception)
108108

109+
def getResponseSize(self):
110+
''' Returns expected packet size of response for this request
111+
112+
:raises: A not implemented exception
113+
'''
114+
raise NotImplementedException()
115+
109116

110117
class ModbusResponse(ModbusPDU):
111118
''' Base class for a modbus response PDU

pymodbus/register_read_message.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ def decode(self, data):
3838
'''
3939
self.address, self.count = struct.unpack('>HH', data)
4040

41+
def getResponseSize(self):
42+
''' Returns expected packet size of response for this request
43+
44+
:returns: The expected packet size
45+
'''
46+
return 1 + 2 * self.count
47+
4148
def __str__(self):
4249
''' Returns a string representation of the instance
4350

pymodbus/register_write_message.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ def execute(self, context):
6161
values = context.getValues(self.function_code, self.address, 1)
6262
return WriteSingleRegisterResponse(self.address, values[0])
6363

64+
def getResponseSize(self):
65+
''' Returns expected packet size of response for this request
66+
67+
:returns: The expected packet size
68+
'''
69+
return 2 + 2
70+
6471
def __str__(self):
6572
''' Returns a string representation of the instance
6673

pymodbus/transaction.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import socket
77
from binascii import b2a_hex, a2b_hex
88

9-
from pymodbus.exceptions import ModbusIOException
9+
from pymodbus.exceptions import ModbusIOException, NotImplementedException
1010
from pymodbus.constants import Defaults
1111
from pymodbus.interfaces import IModbusFramer
1212
from pymodbus.utilities import checkCRC, computeCRC
@@ -62,10 +62,19 @@ def execute(self, request):
6262
try:
6363
self.client.connect()
6464
self.client._send(self.client.framer.buildPacket(request))
65-
# I need to fix this to read the header and the result size,
66-
# as this may not read the full result set, but right now
67-
# it should be fine...
68-
result = self.client._recv(1024)
65+
try:
66+
recvsize = self.client.framer.getResponseSize(request)
67+
except NotImplementedException:
68+
recvsize = 0;
69+
70+
# TODO: read first only as much as needed to check Modbus
71+
# exception and then all remaining bytes. Otherwise
72+
# exception always takes _timeout_ seconds.
73+
if recvsize:
74+
result = self.client._recv(recvsize)
75+
else:
76+
result = self.client._recv(1024)
77+
6978
if not result and self.retry_on_empty:
7079
retries -= 1
7180
continue
@@ -553,6 +562,14 @@ def buildPacket(self, message):
553562
packet += struct.pack(">H", computeCRC(packet))
554563
return packet
555564

565+
def getResponseSize(self, message):
566+
''' Returns expected packet size of response for request
567+
568+
:param message: Request message
569+
:returns: The expected packet size
570+
'''
571+
return 1 + 1 + message.getResponseSize() + 2
572+
556573

557574
#---------------------------------------------------------------------------#
558575
# Modbus ASCII Message

0 commit comments

Comments
 (0)