29
29
ModbusTlsFramer ,
30
30
)
31
31
from pymodbus .logging import Log
32
- from pymodbus .pdu import ModbusRequest
32
+ from pymodbus .pdu import ModbusRequest , ModbusResponse
33
33
from pymodbus .transport import CommType
34
34
from pymodbus .utilities import ModbusTransactionState , hexlify_packets
35
35
@@ -167,13 +167,13 @@ def _set_adu_size(self):
167
167
else :
168
168
self .base_adu_size = - 1
169
169
170
- def _calculate_response_length (self , expected_pdu_size ) :
170
+ def _calculate_response_length (self , expected_pdu_size : int ) -> int | None :
171
171
"""Calculate response length."""
172
172
if self .base_adu_size == - 1 :
173
173
return None
174
174
return self .base_adu_size + expected_pdu_size
175
175
176
- def _calculate_exception_length (self ):
176
+ def _calculate_exception_length (self ) -> int | None :
177
177
"""Return the length of the Modbus Exception Response according to the type of Framer."""
178
178
if isinstance (self .client .framer , (ModbusSocketFramer , ModbusTlsFramer )):
179
179
return self .base_adu_size + 2 # Fcode(1), ExceptionCode(1)
@@ -183,7 +183,9 @@ def _calculate_exception_length(self):
183
183
return self .base_adu_size + 2 # Fcode(1), ExceptionCode(1)
184
184
return None
185
185
186
- def _validate_response (self , request : ModbusRequest , response , exp_resp_len , is_udp = False ):
186
+ def _validate_response (
187
+ self , request : ModbusRequest , response : bytes | int , exp_resp_len : int | None , is_udp = False
188
+ ) -> bool :
187
189
"""Validate Incoming response against request.
188
190
189
191
:param request: Request sent
@@ -208,7 +210,7 @@ def _validate_response(self, request: ModbusRequest, response, exp_resp_len, is_
208
210
return mbap .get ("length" ) == exp_resp_len
209
211
return True
210
212
211
- def execute (self , request : ModbusRequest ): # noqa: C901
213
+ def execute (self , request : ModbusRequest ) -> ModbusResponse | bytes | ModbusIOException : # noqa: C901
212
214
"""Start the producer to send the next request to consumer.write(Frame(request))."""
213
215
with self ._transaction_lock :
214
216
try :
@@ -333,7 +335,9 @@ def execute(self, request: ModbusRequest): # noqa: C901
333
335
self .client .close ()
334
336
return exc
335
337
336
- def _retry_transaction (self , retries , reason , packet , response_length , full = False ):
338
+ def _retry_transaction (
339
+ self , retries : int , reason : str , request : ModbusRequest , response_length : int | None , full = False
340
+ ) -> tuple [bytes , str | Exception | None ]:
337
341
"""Retry transaction."""
338
342
Log .debug ("Retry on {} response - {}" , reason , retries )
339
343
Log .debug ('Changing transaction state from "WAITING_FOR_REPLY" to "RETRYING"' )
@@ -350,9 +354,11 @@ def _retry_transaction(self, retries, reason, packet, response_length, full=Fals
350
354
if response_length == in_waiting :
351
355
result = self ._recv (response_length , full )
352
356
return result , None
353
- return self ._transact (packet , response_length , full = full )
357
+ return self ._transact (request , response_length , full = full )
354
358
355
- def _transact (self , request : ModbusRequest , response_length , full = False , broadcast = False ):
359
+ def _transact (
360
+ self , request : ModbusRequest , response_length : int | None , full = False , broadcast = False
361
+ ) -> tuple [bytes , str | Exception | None ]:
356
362
"""Do a Write and Read transaction.
357
363
358
364
:param packet: packet to be sent
@@ -368,16 +374,12 @@ def _transact(self, request: ModbusRequest, response_length, full=False, broadca
368
374
packet = self .client .framer .buildPacket (request )
369
375
Log .debug ("SEND: {}" , packet , ":hex" )
370
376
size = self ._send (packet )
371
- if (
372
- isinstance (size , bytes )
373
- and self .client .state == ModbusTransactionState .RETRYING
374
- ):
377
+ if size and self .client .state == ModbusTransactionState .RETRYING :
375
378
Log .debug (
376
379
"Changing transaction state from "
377
380
'"RETRYING" to "PROCESSING REPLY"'
378
381
)
379
382
self .client .state = ModbusTransactionState .PROCESSING_REPLY
380
- return size , None
381
383
if self .client .comm_params .handle_local_echo is True :
382
384
if self ._recv (size , full ) != packet :
383
385
return b"" , "Wrong local echo"
@@ -405,23 +407,22 @@ def _transact(self, request: ModbusRequest, response_length, full=False, broadca
405
407
result = b""
406
408
return result , last_exception
407
409
408
- def _send (self , packet : bytes , _retrying = False ):
410
+ def _send (self , packet : bytes , _retrying = False ) -> int :
409
411
"""Send."""
410
412
return self .client .framer .sendPacket (packet )
411
413
412
- def _recv (self , expected_response_length , full ) -> bytes : # noqa: C901
414
+ def _recv (self , expected_response_length : int | None , full : bool ) -> bytes : # noqa: C901
413
415
"""Receive."""
414
416
total = None
415
417
if not full :
416
418
exception_length = self ._calculate_exception_length ()
419
+ min_size = expected_response_length
417
420
if isinstance (self .client .framer , ModbusSocketFramer ):
418
421
min_size = 8
419
422
elif isinstance (self .client .framer , ModbusRtuFramer ):
420
423
min_size = 4
421
424
elif isinstance (self .client .framer , ModbusAsciiFramer ):
422
425
min_size = 5
423
- else :
424
- min_size = expected_response_length
425
426
426
427
read_min = self .client .framer .recvPacket (min_size )
427
428
if len (read_min ) != min_size :
@@ -462,7 +463,7 @@ def _recv(self, expected_response_length, full) -> bytes: # noqa: C901
462
463
if expected_response_length is not None :
463
464
expected_response_length -= min_size
464
465
total = expected_response_length + min_size
465
- else :
466
+ if func_code >= 0x80 and exception_length :
466
467
expected_response_length = exception_length - min_size
467
468
total = expected_response_length + min_size
468
469
else :
0 commit comments