comparison rsib.py @ 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 84f96c5fe791
comparison
equal deleted inserted replaced
74:b6ebe05f250f 75:576f112e0aba
80 MSG_HELLO = 0x40 # We send this on connect 80 MSG_HELLO = 0x40 # We send this on connect
81 MSG_CMD = 0x90 # Command to the instrument 81 MSG_CMD = 0x90 # Command to the instrument
82 MSG_SRQ = 0x91 # Query SRQ 82 MSG_SRQ = 0x91 # Query SRQ
83 83
84 import socket 84 import socket
85 import time
85 86
86 class RSIBDevice(object): 87 class RSIBDevice(object):
87 hello = '\x00\x00\x00\x40' 88 hello = '\x00\x00\x00\x40'
88 docmd = '\x00\x00\x00\x05\x90\x00\x01' 89 docmd = '\x00\x00\x00\x05\x90\x00\x01'
89 90
125 self.s1.send(msg) 126 self.s1.send(msg)
126 127
127 def read(self, timeout = 0.5): 128 def read(self, timeout = 0.5):
128 """Read data from the device, waits for up to timeout seconds for each TCP read""" 129 """Read data from the device, waits for up to timeout seconds for each TCP read"""
129 130
131 if timeout is not None:
132 timeout = time.clock_gettime(time.CLOCK_MONOTONIC) + timeout
130 self.s1.settimeout(timeout) 133 self.s1.settimeout(timeout)
131 134
132 reply = b'' 135 reply = b''
133 last = False 136 last = False
134 while not last: 137 while not last:
135 # Fetch the header 138 # Fetch the header
136 rx = b'' 139 hdr = b''
137 remain = 7 140 remain = 7
138 while len(rx) < 7: 141 while len(hdr) < 7:
139 rx = self.s1.recv(remain) 142 rx = self.s1.recv(remain)
140 if rx == b'': 143 if len(rx) == 0:
141 raise IOError("EOF from device") 144 if timeout is not None and time.clock_gettime(time.CLOCK_MONOTONIC) >= timeout:
145 raise IOError("EOF from device")
146 else:
147 time.sleep(0.1)
142 remain -= len(rx) 148 remain -= len(rx)
143 rxlen = rx[0] << 24 | rx[1] << 16 | rx[2] << 8 | rx[3] 149 hdr += rx
144 #print(rx, rxlen) 150 rxlen = rx[0] << 24 | rx[1] << 16 | rx[2] << 8 | rx[3]
145 if self.tag != rx[6]: 151 #print(rx, rxlen)
146 raise IOError("Reply out of order, got 0x%02x expected 0x%02x" % (rx[6], self.tag)) 152 if self.tag != rx[6]:
147 if rx[4] == 0x80: 153 raise IOError("Reply out of order, got 0x%02x expected 0x%02x" % (rx[6], self.tag))
148 #print('EOM') 154 if rx[4] == 0x80:
149 last = True 155 #print('EOM')
150 if rx[5] != 0: 156 last = True
151 print("Mystery byte %d != 0" % (rx[5])) 157 if rx[5] != 0:
152 158 print("Mystery byte %d != 0" % (rx[5]))
153 # Fetch the actual data block now we know the length 159
154 remain = rxlen 160 # Fetch the actual data block now we know the length
155 while remain > 0: 161 remain = rxlen
156 rx = self.s1.recv(remain) 162 while remain > 0:
157 if rx == b'': 163 rx = self.s1.recv(remain)
164 if len(rx) == 0:
165 if timeout is not None and time.clock_gettime(time.CLOCK_MONOTONIC) >= timeout:
158 raise IOError("EOF from device") 166 raise IOError("EOF from device")
159 reply += rx 167 else:
160 remain -= len(rx) 168 time.sleep(0.1)
169
170 reply += rx
171 remain -= len(rx)
161 172
162 return(reply) 173 return(reply)
163 174
164 def ask(self, s, timeout = None): 175 def ask(self, s, timeout = None):
165 '''Wrapper to send a command and wait for a reply''' 176 '''Wrapper to send a command and wait for a reply'''