Retry modbus send if no answer
authorBenjamin Braatz <bb@bbraatz.eu>
Tue, 16 Feb 2021 10:30:43 +0000 (11:30 +0100)
committerBenjamin Braatz <bb@bbraatz.eu>
Tue, 16 Feb 2021 10:30:43 +0000 (11:30 +0100)
gmodbus/transport.py

index 8405eec3b400ba6328be27a8495c809c52c12f62..89678b539419ac7b72cd03d29ba5d82d5ac49c7d 100644 (file)
@@ -168,29 +168,35 @@ class SerialClient(ClientInterface):
     return value
 
   async def __send_message(self, message: bytes) -> List[int]:
-    await self.__port.write(message)
-
-    # Check exception ADU (which is shorter than all other responses) first.
-    exception_adu_size = 5
-    response_error_adu = b''
-    try:
-        response_error_adu = await asyncio.wait_for(self.__port.read(exception_adu_size), timeout=1.0)
-    except asyncio.TimeoutError:
-        print("modbus read timed out")
-    rtu.raise_for_exception_adu(response_error_adu)
-
-    expected_response_size = \
+    success = False
+    while not success:
+      success = True
+
+      await self.__port.write(message)
+
+      # Check exception ADU (which is shorter than all other responses) first.
+      exception_adu_size = 5
+      response_error_adu = b''
+      try:
+        response_error_adu = await asyncio.wait_for(self.__port.read(exception_adu_size), timeout=0.1)
+        rtu.raise_for_exception_adu(response_error_adu)
+      except asyncio.TimeoutError:
+        print("modbus read timed out for response_error_adu")
+        exception_adu_size = 0
+
+      expected_response_size = \
         expected_response_pdu_size_from_request_pdu(message[1:-2]) + 3
-    response_remainder = b''
-    try:
-        response_remainder = await asyncio.wait_for(self.__port.read(expected_response_size - exception_adu_size), timeout=1.0)
-    except asyncio.TimeoutError:
-        print("modbus read timed out")
-
-    response = response_error_adu + response_remainder
-    if len(response) < expected_response_size:
-      return []
-    result = rtu.parse_response_adu(response, message)
-    if not isinstance(result, list):
-      return [result]
-    return result
+      response_remainder = b''
+      try:
+        response_remainder = await asyncio.wait_for(self.__port.read(expected_response_size - exception_adu_size), timeout=0.1)
+      except asyncio.TimeoutError:
+        print("modbus read timed out for response_remainder, retrying")
+        success = False
+
+      response = response_error_adu + response_remainder
+      if len(response) < expected_response_size:
+        return []
+      result = rtu.parse_response_adu(response, message)
+      if not isinstance(result, list):
+        return [result]
+      return result