@@ -68,22 +68,51 @@ def _set_adu_size(self):
6868
6969 def _calculate_response_length (self , expected_pdu_size ):
7070 if self .base_adu_size == - 1 :
71- return 1024
71+ return None
7272 else :
7373 return self .base_adu_size + expected_pdu_size
7474
75+ def _calculate_exception_length (self ):
76+ ''' Returns the length of the Modbus Exception Response according to
77+ the type of Framer.
78+ '''
79+ if isinstance (self .client .framer , ModbusSocketFramer ):
80+ return self .base_adu_size + 2 # Fcode(1), ExcecptionCode(1)
81+ elif isinstance (self .client .framer , ModbusAsciiFramer ):
82+ return self .base_adu_size + 4 # Fcode(2), ExcecptionCode(2)
83+ elif isinstance (self .client .framer , (ModbusRtuFramer , ModbusBinaryFramer )):
84+ return self .base_adu_size + 2 # Fcode(1), ExcecptionCode(1)
85+
86+ return None
87+
88+ def _check_response (self , response ):
89+ ''' Checks if the response is a Modbus Exception.
90+ '''
91+ if isinstance (self .client .framer , ModbusSocketFramer ):
92+ if len (response ) >= 8 and byte2int (response [7 ]) > 128 :
93+ return False
94+ elif isinstance (self .client .framer , ModbusAsciiFramer ):
95+ if len (response ) >= 5 and int (response [3 :5 ], 16 ) > 128 :
96+ return False
97+ elif isinstance (self .client .framer , (ModbusRtuFramer , ModbusBinaryFramer )):
98+ if len (response ) >= 2 and byte2int (response [1 ]) > 128 :
99+ return False
100+
101+ return True
102+
75103 def execute (self , request ):
76104 ''' Starts the producer to send the next request to
77105 consumer.write(Frame(request))
78106 '''
79107 retries = self .retries
80108 request .transaction_id = self .getNextTID ()
81109 _logger .debug ("Running transaction %d" % request .transaction_id )
110+
111+ expected_response_length = None
82112 if hasattr (request , "get_response_pdu_size" ):
83113 response_pdu_size = request .get_response_pdu_size ()
84- expected_response_length = self ._calculate_response_length (response_pdu_size )
85- else :
86- expected_response_length = 1024
114+ if response_pdu_size :
115+ expected_response_length = self ._calculate_response_length (response_pdu_size )
87116
88117 while retries > 0 :
89118 try :
@@ -92,11 +121,20 @@ def execute(self, request):
92121 if _logger .isEnabledFor (logging .DEBUG ):
93122 _logger .debug ("send: " + " " .join ([hex (byte2int (x )) for x in packet ]))
94123 self .client ._send (packet )
95- result = self .client ._recv (expected_response_length )
124+
125+ exception = False
126+ result = self .client ._recv (expected_response_length or 1024 )
127+ while result and expected_response_length and len (result ) < expected_response_length :
128+ if not exception and not self ._check_response (result ):
129+ exception = True
130+ expected_response_length = self ._calculate_exception_length ()
131+ continue
132+ result += self .client ._recv (expected_response_length - len (result ))
96133
97134 if not result and self .retry_on_empty :
98135 retries -= 1
99136 continue
137+
100138 if _logger .isEnabledFor (logging .DEBUG ):
101139 _logger .debug ("recv: " + " " .join ([hex (byte2int (x )) for x in result ]))
102140 self .client .framer .processIncomingPacket (result , self .addTransaction )
0 commit comments