1717from pymodbus .client .mixin import ModbusClientMixin
1818from pymodbus .datastore import ModbusSlaveContext
1919from pymodbus .datastore .store import ModbusSequentialDataBlock
20- from pymodbus .exceptions import ConnectionException
20+ from pymodbus .exceptions import ConnectionException , ModbusIOException
2121from pymodbus .framer .ascii_framer import ModbusAsciiFramer
2222from pymodbus .framer .rtu_framer import ModbusRtuFramer
2323from pymodbus .framer .socket_framer import ModbusSocketFramer
@@ -365,9 +365,10 @@ async def test_client_protocol_handler():
365365class MockTransport :
366366 """Mock transport class which responds with an appropriate encoded packet"""
367367
368- def __init__ (self , base , req ):
368+ def __init__ (self , base , req , retries = 0 ):
369369 """Initialize MockTransport"""
370370 self .base = base
371+ self .retries = retries
371372
372373 db = ModbusSequentialDataBlock (0 , [0 ] * 100 )
373374 self .ctx = ModbusSlaveContext (di = db , co = db , hr = db , ir = db )
@@ -382,6 +383,9 @@ async def delayed_resp(self):
382383
383384 def write (self , data , addr = None ):
384385 """Write data to the transport, start a task to send the response"""
386+ if self .retries :
387+ self .retries -= 1
388+ return
385389 self .delayed_resp_task = asyncio .create_task (self .delayed_resp ())
386390
387391 def close (self ):
@@ -401,6 +405,35 @@ async def test_client_protocol_execute():
401405 assert isinstance (response , pdu_bit_read .ReadCoilsResponse )
402406
403407
408+ async def test_client_protocol_retry ():
409+ """Test the client protocol execute method with retries"""
410+ base = ModbusBaseClient (host = "127.0.0.1" , framer = ModbusSocketFramer , timeout = 0.1 )
411+ request = pdu_bit_read .ReadCoilsRequest (1 , 1 )
412+ transport = MockTransport (base , request , retries = 2 )
413+ base .connection_made (transport = transport )
414+
415+ response = await base .async_execute (request )
416+ assert transport .retries == 0
417+ assert not response .isError ()
418+ assert isinstance (response , pdu_bit_read .ReadCoilsResponse )
419+
420+
421+ async def test_client_protocol_timeout ():
422+ """Test the client protocol execute method with timeout"""
423+ base = ModbusBaseClient (
424+ host = "127.0.0.1" , framer = ModbusSocketFramer , timeout = 0.1 , retries = 2
425+ )
426+ # Avoid creating do_reconnect() task
427+ base .connection_lost = mock .MagicMock ()
428+ request = pdu_bit_read .ReadCoilsRequest (1 , 1 )
429+ transport = MockTransport (base , request , retries = 4 )
430+ base .connection_made (transport = transport )
431+
432+ with pytest .raises (ModbusIOException ):
433+ await base .async_execute (request )
434+ assert transport .retries == 1
435+
436+
404437def test_client_udp_connect ():
405438 """Test the Udp client connection method"""
406439 with mock .patch .object (socket , "socket" ) as mock_method :
0 commit comments