From 0ce5417e3fe1dfaeff35a490ee16dd060417e61e Mon Sep 17 00:00:00 2001 From: Victor Szabo <159083621+victor-tutor@users.noreply.github.com> Date: Wed, 9 Oct 2024 23:57:21 -0400 Subject: [PATCH] fix: Retry on timeout (#4) --- examples/example.py | 7 +------ tcp_modbus_aio/client.py | 25 ++++--------------------- tcp_modbus_aio/exceptions.py | 10 ++-------- 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/examples/example.py b/examples/example.py index 439a855..a4bf67e 100644 --- a/examples/example.py +++ b/examples/example.py @@ -3,10 +3,7 @@ from aiosocks import Socks5Addr from tcp_modbus_aio.client import TCPModbusClient -from tcp_modbus_aio.exceptions import ( - ModbusCommunicationFailureError, - ModbusCommunicationTimeoutError, -) +from tcp_modbus_aio.exceptions import ModbusCommunicationFailureError from tcp_modbus_aio.typed_functions import ReadCoils DIGITAL_IN_COILS = list(range(8)) @@ -32,8 +29,6 @@ async def example() -> None: ) assert response is not None, "we expect a response from ReadCoils" print(response.data) # noqa: T201 - except ModbusCommunicationTimeoutError as e: - print(f"{type(e).__name__}({e})") except ModbusCommunicationFailureError as e: print(f"{type(e).__name__}({e})") diff --git a/tcp_modbus_aio/client.py b/tcp_modbus_aio/client.py index 3180d3e..ff77233 100644 --- a/tcp_modbus_aio/client.py +++ b/tcp_modbus_aio/client.py @@ -13,7 +13,7 @@ from tcp_modbus_aio.exceptions import ( ModbusCommunicationFailureError, - ModbusCommunicationTimeoutError, + ModbusConcurrencyError, ModbusNotConnectedError, ) from tcp_modbus_aio.ping import ping_ip @@ -57,7 +57,6 @@ class TCPModbusClient: KEEPALIVE_MAX_FAILS: ClassVar = 5 PING_LOOP_PERIOD: ClassVar = 1 - CONSECUTIVE_TIMEOUTS_TO_RECONNECT: ClassVar = 5 COOLDOWN_BEFORE_RECONNECTING_SEC: ClassVar = 0.01 def __init__( @@ -90,9 +89,6 @@ def __init__( self._reader: asyncio.StreamReader | None = None self._writer: asyncio.StreamWriter | None = None - # Number of current consecutive modbus calls that resulted in a timeout - self._consecutive_timeouts = 0 - # Last ping time in seconds from ping loop, or None if the last ping failed self._last_ping: float | None = None @@ -192,7 +188,7 @@ async def _get_tcp_connection( ) if self.logger is not None: self.logger.warning(f"[{self}][_get_tcp_connection] {msg}") - raise ModbusCommunicationTimeoutError(msg) + raise ModbusCommunicationFailureError(msg) except OSError: msg = f"Cannot connect to TCP modbus device at {self.host}:{self.port}" if self.logger is not None: @@ -447,7 +443,7 @@ async def send_modbus_message( self._comms_lock.acquire(), time_budget_remaining ) except asyncio.TimeoutError: - raise ModbusCommunicationTimeoutError( + raise ModbusConcurrencyError( f"Failed to acquire lock to send request {msg_str} to modbus device {self.host}" ) time_budget_remaining -= lock_t() @@ -515,20 +511,7 @@ async def send_modbus_message( return None raise - except asyncio.TimeoutError as e: - self._consecutive_timeouts += 1 - if self._consecutive_timeouts >= self.CONSECUTIVE_TIMEOUTS_TO_RECONNECT: - if self.logger is not None: - self.logger.warning( - f"[{self}][send_modbus_message] {self._consecutive_timeouts} consecutive timeouts, " - "clearing connection" - ) - self.clear_tcp_connection() - - raise ModbusCommunicationTimeoutError( - f"Request {msg_str} timed out to {self.host}:{self.port}" - ) from e - except (OSError, EOFError) as e: + except (OSError, EOFError, asyncio.TimeoutError) as e: if self.logger is not None: self.logger.warning( f"[{self}][send_modbus_message] {type(e).__name__}({e}) while sending request {msg_str}, " diff --git a/tcp_modbus_aio/exceptions.py b/tcp_modbus_aio/exceptions.py index d01e6cf..95565d0 100644 --- a/tcp_modbus_aio/exceptions.py +++ b/tcp_modbus_aio/exceptions.py @@ -4,16 +4,10 @@ class ModbusCommunicationFailureError(ModbusError): """Generic modbus communication error.""" - pass - -class ModbusCommunicationTimeoutError(ModbusCommunicationFailureError): - """Timeout in communicating with modbus device.""" - - pass +class ModbusConcurrencyError(ModbusError): + """Too many concurrent requests""" class ModbusNotConnectedError(ModbusCommunicationFailureError): """Modbus not connected error.""" - - pass