diff --git a/.gitignore b/.gitignore index 5ba77b1e9..b6695b6b1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ build/ dist/ pymodbus.egg-info/ .coverage +*env/ +.idea/ +RIPTIDE.md diff --git a/pymodbus/bit_read_message.py b/pymodbus/bit_read_message.py index f0dd6e312..72cb988df 100644 --- a/pymodbus/bit_read_message.py +++ b/pymodbus/bit_read_message.py @@ -14,6 +14,7 @@ class ReadBitsRequestBase(ModbusRequest): ''' Base class for Messages Requesting bit values ''' _rtu_frame_size = 8 + _pdu_length = 2 # func + bytcodeLen def __init__(self, address, count, **kwargs): ''' Initializes the read request data @@ -23,7 +24,8 @@ def __init__(self, address, count, **kwargs): ''' ModbusRequest.__init__(self, **kwargs) self.address = address - self.count = count + self.count = count + self._pdu_length += count def encode(self): ''' Encodes a request pdu diff --git a/pymodbus/bit_write_message.py b/pymodbus/bit_write_message.py index 64f291daf..4c62b48e0 100644 --- a/pymodbus/bit_write_message.py +++ b/pymodbus/bit_write_message.py @@ -39,6 +39,7 @@ class WriteSingleCoilRequest(ModbusRequest): ''' function_code = 5 _rtu_frame_size = 8 + _pdu_length = 5 # func + adress1 + adress2 + value1+value2 def __init__(self, address=None, value=None, **kwargs): ''' Initializes a new instance @@ -148,7 +149,7 @@ class WriteMultipleCoilsRequest(ModbusRequest): ''' function_code = 15 _rtu_byte_count_pos = 6 - + _pdu_length = 5 # func + adress1 + adress2 + outputQuant1 + outputQuant2 def __init__(self, address=None, values=None, **kwargs): ''' Initializes a new instance diff --git a/pymodbus/file_message.py b/pymodbus/file_message.py index 366517cef..85edb7d89 100644 --- a/pymodbus/file_message.py +++ b/pymodbus/file_message.py @@ -31,8 +31,10 @@ def __init__(self, **kwargs): self.file_number = kwargs.get('file_number', 0x00) self.record_number = kwargs.get('record_number', 0x00) self.record_data = kwargs.get('record_data', '') - self.record_length = kwargs.get('record_length', len(self.record_data) / 2) - self.response_length = kwargs.get('response_length', len(self.record_data) + 1) + self.record_length = kwargs.get('record_length', + len(self.record_data) / 2) + self.response_length = kwargs.get('response_length', + len(self.record_data) + 1) def __eq__(self, relf): ''' Compares the left object to the right @@ -286,6 +288,7 @@ class MaskWriteRegisterRequest(ModbusRequest): ''' function_code = 0x16 _rtu_frame_size = 10 + _pdu_length = 7 # func + adress1 + adress2 + andMaskHi + andMaskLo + orMaskHi + orMaskLo def __init__(self, address=0x0000, and_mask=0xffff, or_mask=0x0000, **kwargs): ''' Initializes a new instance diff --git a/pymodbus/register_read_message.py b/pymodbus/register_read_message.py index 06d82925f..fa27a86d9 100644 --- a/pymodbus/register_read_message.py +++ b/pymodbus/register_read_message.py @@ -13,6 +13,7 @@ class ReadRegistersRequestBase(ModbusRequest): Base class for reading a modbus register ''' _rtu_frame_size = 8 + _pdu_length = 2 #func + bytcodeLen def __init__(self, address, count, **kwargs): ''' Initializes a new instance @@ -23,7 +24,7 @@ def __init__(self, address, count, **kwargs): ModbusRequest.__init__(self, **kwargs) self.address = address self.count = count - + self._pdu_length += 2*count def encode(self): ''' Encodes the request packet @@ -213,7 +214,7 @@ class ReadWriteMultipleRegistersRequest(ModbusRequest): ''' function_code = 23 _rtu_byte_count_pos = 10 - + _pdu_length = 2 #func + bytcodeLen def __init__(self, **kwargs): ''' Initializes a new request message @@ -231,6 +232,7 @@ def __init__(self, **kwargs): self.write_registers = [self.write_registers] self.write_count = len(self.write_registers) self.write_byte_count = self.write_count * 2 + self._pdu_length+=2*count #slave + func + bytcodeLen + bytecode x 2 + crc1 + crc2 def encode(self): ''' Encodes the request packet diff --git a/pymodbus/register_write_message.py b/pymodbus/register_write_message.py index b49db4901..bc13c4a56 100644 --- a/pymodbus/register_write_message.py +++ b/pymodbus/register_write_message.py @@ -19,6 +19,7 @@ class WriteSingleRegisterRequest(ModbusRequest): ''' function_code = 6 _rtu_frame_size = 8 + _pdu_length = 5 # func + adress1 + adress2 + outputQuant1 + outputQuant2 def __init__(self, address=None, value=None, **kwargs): ''' Initializes a new instance @@ -123,6 +124,7 @@ class WriteMultipleRegistersRequest(ModbusRequest): ''' function_code = 16 _rtu_byte_count_pos = 6 + _pdu_length = 5 #func + adress1 + adress2 + outputQuant1 + outputQuant2 def __init__(self, address=None, values=None, **kwargs): ''' Initializes a new instance diff --git a/pymodbus/transaction.py b/pymodbus/transaction.py index 71cc79b3d..b2a6bfa4b 100644 --- a/pymodbus/transaction.py +++ b/pymodbus/transaction.py @@ -49,6 +49,26 @@ def __init__(self, client, **kwargs): self.client = client self.retry_on_empty = kwargs.get('retry_on_empty', Defaults.RetryOnEmpty) self.retries = kwargs.get('retries', Defaults.Retries) + self._set_adu_size() + + def _set_adu_size(self): + # base ADU size of modbus frame in bytes + if isinstance(self.client.framer, ModbusSocketFramer): + self.base_adu_size = 7 # tid(2), pid(2), length(2), uid(1) + elif isinstance(self.client.framer, ModbusRtuFramer): + self.base_adu_size = 3 # address(1), CRC(2) + elif isinstance(self.client.framer, ModbusAsciiFramer): + self.base_adu_size = 4 # Address(2), LRC(2) + elif isinstance(self.client.framer, ModbusBinaryFramer): + self.base_adu_size = 3 #, Address(1), CRC(2) + else: + self.base_adu_size = -1 + + def _calculate_response_length(self, expected_pdu_size): + if self.base_adu_size == -1: + return 1024 + else: + return self.base_adu_size + expected_pdu_size def execute(self, request): ''' Starts the producer to send the next request to @@ -57,7 +77,7 @@ def execute(self, request): retries = self.retries request.transaction_id = self.getNextTID() _logger.debug("Running transaction %d" % request.transaction_id) - + expected_response_length = self._calculate_response_length(request._pdu_length) while retries > 0: try: self.client.connect() @@ -65,7 +85,9 @@ def execute(self, 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) + + result = self.client._recv(expected_response_length) + # result = self.client._recv(1024) if not result and self.retry_on_empty: retries -= 1 continue @@ -79,6 +101,7 @@ def execute(self, request): retries -= 1 return self.getTransaction(request.transaction_id) + def addTransaction(self, request, tid=None): ''' Adds a transaction to the handler diff --git a/pymodbus/version.py b/pymodbus/version.py index c002097b4..873672bd0 100644 --- a/pymodbus/version.py +++ b/pymodbus/version.py @@ -9,7 +9,7 @@ class Version(object): - def __init__(self, package, major, minor, micro): + def __init__(self, package, major, minor, micro, pre=""): ''' :param package: Name of the package that this is a version of. @@ -21,12 +21,13 @@ def __init__(self, package, major, minor, micro): self.major = major self.minor = minor self.micro = micro + self.pre = pre def short(self): ''' Return a string in canonical short version format .. ''' - return '%d.%d.%d' % (self.major, self.minor, self.micro) + return '%d.%d.%d%s' % (self.major, self.minor, self.micro, self.pre) def __str__(self): ''' Returns a string representation of the object @@ -35,7 +36,7 @@ def __str__(self): ''' return '[%s, version %s]' % (self.package, self.short()) -version = Version('pymodbus', 1, 3, 0) +version = Version('pymodbus', 1, 3, 0, "rc93104") version.__name__ = 'pymodbus' # fix epydoc error #---------------------------------------------------------------------------# diff --git a/requirements.txt b/requirements.txt index 39d95377b..5eb9b6bcf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,17 +5,18 @@ # ------------------------------------------------------------------- # if you want to run the tests and code coverage, uncomment these # ------------------------------------------------------------------- -#coverage==3.5.3 -#mock==1.0b1 -#nose==1.2.1 -#pep8==1.3.3 +coverage>=3.5.3 +mock>=1.0b1 +nose>=1.2.1 +pep8>=1.3.3 +-e . # ------------------------------------------------------------------- # if you want to use the asynchronous version, uncomment these # ------------------------------------------------------------------- -#Twisted==12.2.0 -#zope.interface==4.0.1 -#pyasn1==0.1.4 -#pycrypto==2.6 +Twisted==15.2.1 +zope.interface==4.1.2 +pyasn1==0.1.7 +pycrypto==2.6.1 #wsgiref==0.1.2 # ------------------------------------------------------------------- # if you want to build the documentation, uncomment these