changeset 75:576f112e0aba

Fix read timeout handling so it works over imperfect links.
author Daniel O'Connor <doconnor@gsoft.com.au>
date Fri, 27 Sep 2024 09:27:33 +0930
parents b6ebe05f250f
children e2bb136bd2ed
files rsib.py
diffstat 1 files changed, 31 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/rsib.py	Wed Sep 25 21:10:01 2024 +0930
+++ b/rsib.py	Fri Sep 27 09:27:33 2024 +0930
@@ -82,6 +82,7 @@
 MSG_SRQ = 0x91	   # Query SRQ
 
 import socket
+import time
 
 class RSIBDevice(object):
     hello = '\x00\x00\x00\x40'
@@ -127,37 +128,47 @@
     def read(self, timeout = 0.5):
         """Read data from the device, waits for up to timeout seconds for each TCP read"""
 
+        if timeout is not None:
+            timeout = time.clock_gettime(time.CLOCK_MONOTONIC) + timeout
         self.s1.settimeout(timeout)
 
         reply = b''
         last = False
         while not last:
             # Fetch the header
-            rx = b''
+            hdr = b''
             remain = 7
-            while len(rx) < 7:
+            while len(hdr) < 7:
                 rx = self.s1.recv(remain)
-                if rx == b'':
-                    raise IOError("EOF from device")
+                if len(rx) == 0:
+                    if timeout is not None and time.clock_gettime(time.CLOCK_MONOTONIC) >= timeout:
+                        raise IOError("EOF from device")
+                    else:
+                        time.sleep(0.1)
                 remain -= len(rx)
-                rxlen = rx[0] << 24 | rx[1] << 16 | rx[2] << 8 | rx[3]
-                #print(rx, rxlen)
-                if self.tag != rx[6]:
-                    raise IOError("Reply out of order, got 0x%02x expected 0x%02x" % (rx[6], self.tag))
-                if rx[4] == 0x80:
-                    #print('EOM')
-                    last = True
-                if rx[5] != 0:
-                    print("Mystery byte %d != 0" % (rx[5]))
+                hdr += rx
+            rxlen = rx[0] << 24 | rx[1] << 16 | rx[2] << 8 | rx[3]
+            #print(rx, rxlen)
+            if self.tag != rx[6]:
+                raise IOError("Reply out of order, got 0x%02x expected 0x%02x" % (rx[6], self.tag))
+            if rx[4] == 0x80:
+                #print('EOM')
+                last = True
+            if rx[5] != 0:
+                print("Mystery byte %d != 0" % (rx[5]))
 
-                # Fetch the actual data block now we know the length
-                remain = rxlen
-                while remain > 0:
-                    rx = self.s1.recv(remain)
-                    if rx == b'':
+            # Fetch the actual data block now we know the length
+            remain = rxlen
+            while remain > 0:
+                rx = self.s1.recv(remain)
+                if len(rx) == 0:
+                    if timeout is not None and time.clock_gettime(time.CLOCK_MONOTONIC) >= timeout:
                         raise IOError("EOF from device")
-                    reply += rx
-                    remain -= len(rx)
+                    else:
+                        time.sleep(0.1)
+
+                reply += rx
+                remain -= len(rx)
 
         return(reply)