Skip to content

Commit

Permalink
Implement getResponseSize()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Cougar committed Aug 15, 2014
1 parent 9044524 commit c5a9eae
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 5 deletions.
7 changes: 7 additions & 0 deletions pymodbus/pdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ def doException(self, exception):
(self.function_code, exception))
return ExceptionResponse(self.function_code, exception)

def getResponseSize(self):
''' Returns expected packet size of response for this request
:raises: A not implemented exception
'''
raise NotImplementedException()


class ModbusResponse(ModbusPDU):
''' Base class for a modbus response PDU
Expand Down
7 changes: 7 additions & 0 deletions pymodbus/register_read_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ def decode(self, data):
'''
self.address, self.count = struct.unpack('>HH', data)

def getResponseSize(self):
''' Returns expected packet size of response for this request
:returns: The expected packet size
'''
return 1 + 2 * self.count

def __str__(self):
''' Returns a string representation of the instance
Expand Down
7 changes: 7 additions & 0 deletions pymodbus/register_write_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ def execute(self, context):
values = context.getValues(self.function_code, self.address, 1)
return WriteSingleRegisterResponse(self.address, values[0])

def getResponseSize(self):
''' Returns expected packet size of response for this request
:returns: The expected packet size
'''
return 2 + 2

def __str__(self):
''' Returns a string representation of the instance
Expand Down
27 changes: 22 additions & 5 deletions pymodbus/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import socket
from binascii import b2a_hex, a2b_hex

from pymodbus.exceptions import ModbusIOException
from pymodbus.exceptions import ModbusIOException, NotImplementedException
from pymodbus.constants import Defaults
from pymodbus.interfaces import IModbusFramer
from pymodbus.utilities import checkCRC, computeCRC
Expand Down Expand Up @@ -62,10 +62,19 @@ def execute(self, request):
try:
self.client.connect()
self.client._send(self.client.framer.buildPacket(request))
# I need to fix this to read the header and the result size,
# as this may not read the full result set, but right now
# it should be fine...
result = self.client._recv(1024)
try:
recvsize = self.client.framer.getResponseSize(request)
except NotImplementedException:
recvsize = 0;

# TODO: read first only as much as needed to check Modbus
# exception and then all remaining bytes. Otherwise
# exception always takes _timeout_ seconds.
if recvsize:
result = self.client._recv(recvsize)
else:
result = self.client._recv(1024)

if not result and self.retry_on_empty:
retries -= 1
continue
Expand Down Expand Up @@ -553,6 +562,14 @@ def buildPacket(self, message):
packet += struct.pack(">H", computeCRC(packet))
return packet

def getResponseSize(self, message):
''' Returns expected packet size of response for request
:param message: Request message
:returns: The expected packet size
'''
return 1 + 1 + message.getResponseSize() + 2


#---------------------------------------------------------------------------#
# Modbus ASCII Message
Expand Down

0 comments on commit c5a9eae

Please sign in to comment.