@@ -68,22 +68,51 @@ def _set_adu_size(self):
68
68
69
69
def _calculate_response_length (self , expected_pdu_size ):
70
70
if self .base_adu_size == - 1 :
71
- return 1024
71
+ return None
72
72
else :
73
73
return self .base_adu_size + expected_pdu_size
74
74
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
+
75
103
def execute (self , request ):
76
104
''' Starts the producer to send the next request to
77
105
consumer.write(Frame(request))
78
106
'''
79
107
retries = self .retries
80
108
request .transaction_id = self .getNextTID ()
81
109
_logger .debug ("Running transaction %d" % request .transaction_id )
110
+
111
+ expected_response_length = None
82
112
if hasattr (request , "get_response_pdu_size" ):
83
113
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 )
87
116
88
117
while retries > 0 :
89
118
try :
@@ -92,11 +121,20 @@ def execute(self, request):
92
121
if _logger .isEnabledFor (logging .DEBUG ):
93
122
_logger .debug ("send: " + " " .join ([hex (byte2int (x )) for x in packet ]))
94
123
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 ))
96
133
97
134
if not result and self .retry_on_empty :
98
135
retries -= 1
99
136
continue
137
+
100
138
if _logger .isEnabledFor (logging .DEBUG ):
101
139
_logger .debug ("recv: " + " " .join ([hex (byte2int (x )) for x in result ]))
102
140
self .client .framer .processIncomingPacket (result , self .addTransaction )
0 commit comments