# HG changeset patch # User Daniel O'Connor # Date 1727395053 -34200 # Node ID 576f112e0aba49854b1841eac2f1409a71cb39e6 # Parent b6ebe05f250f8699b84e7781c755724ae2dbeb87 Fix read timeout handling so it works over imperfect links. diff -r b6ebe05f250f -r 576f112e0aba rsib.py --- 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)