Skip to content

Commit 6df2963

Browse files
committed
improve response parsing
1 parent 2a8c0a7 commit 6df2963

File tree

1 file changed

+45
-39
lines changed

1 file changed

+45
-39
lines changed

pylabrobot/plate_reading/byonoy.py

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,11 @@ def _background_ping_worker(self) -> None:
5353
async def _ping_loop(self) -> None:
5454
"""Main ping loop that runs in the background thread."""
5555
while not self._stop_background.is_set():
56-
try:
57-
# Only send ping if pings are enabled
58-
if self._sending_pings:
59-
# Send ping command
60-
cmd = "40000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008040"
61-
print("> " + cmd + " (background ping)")
62-
await self.io.write(bytes.fromhex(cmd))
63-
except Exception as e:
64-
print(f"Error in background ping: {e}")
56+
# Only send ping if pings are enabled
57+
if self._sending_pings:
58+
# Send ping command
59+
cmd = "40000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008040"
60+
await self.io.write(bytes.fromhex(cmd))
6561

6662
# Wait for the ping interval or until stop is requested
6763
self._stop_background.wait(self._ping_interval)
@@ -78,8 +74,6 @@ async def _read_until_empty(self, timeout=30):
7874
chunk = await self.io.read(64, timeout=timeout)
7975
if not chunk:
8076
break
81-
else:
82-
print("< ", chunk.hex())
8377
data += chunk
8478

8579
if chunk.startswith(b"\x70"):
@@ -99,8 +93,7 @@ async def _wait_for_response(self, timeout=30):
9993
if len(data) > 64:
10094
break
10195
if time.time() - t0 > timeout:
102-
print("Timeout waiting for response")
103-
return data
96+
raise TimeoutError("Timeout waiting for response")
10497
time.sleep(0.1)
10598
return data
10699

@@ -152,7 +145,6 @@ async def read_luminescence(self, plate: Plate, focal_height: float) -> List[Lis
152145
)
153146

154147
t0 = time.time()
155-
r = b""
156148
reading_data = False
157149
data = b""
158150

@@ -169,7 +161,6 @@ async def read_luminescence(self, plate: Plate, focal_height: float) -> List[Lis
169161
)
170162
in chunk
171163
):
172-
print("Received result")
173164
reading_data = True
174165
self._stop_background_pings()
175166

@@ -180,35 +171,50 @@ async def read_luminescence(self, plate: Plate, focal_height: float) -> List[Lis
180171
break
181172

182173
cmd = "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040"
183-
print("> " + cmd)
184174
await self.io.write(bytes.fromhex(cmd))
185175

186176
self._start_background_pings()
187177

188178
# split data in 64 byte chunks
189-
data_chunks = [data[i : i + 64] for i in range(0, len(data), 64)]
190-
191-
measurements = []
192-
reading_measurements = False
193-
read_n_data_packets = 0
194-
for line in data_chunks:
195-
if reading_measurements:
196-
segment = line
197-
measurements.append(segment)
198-
read_n_data_packets += 1
199-
200-
if b"hybrid result" in line:
201-
reading_measurements = True
202-
203-
if read_n_data_packets == 8:
204-
break
205-
206-
floats = [
207-
f
208-
for line in [l[12:-4] for l in measurements]
209-
for f in struct.unpack("f" * (len(line) // 4), line)
210-
]
211-
return floats
179+
start = 64 * 5
180+
blob_size = 64 * 9
181+
num_blobs = 8
182+
blobs = [data[start + i * blob_size : start + (i + 1) * blob_size] for i in range(num_blobs)]
183+
(
184+
hybrid_result_b,
185+
counting_result_b,
186+
sampling_result_b,
187+
micro_counting_result_b,
188+
micro_integration_result_b,
189+
repetition_count_b,
190+
integration_time_b,
191+
below_breakdown_measurement_b,
192+
) = blobs
193+
194+
def get_floats(data):
195+
"""Extract floats from a 9 * 64 byte chunk.
196+
First 64 bytes are ignored.
197+
Then for each 64 byte chunk, the first 12 and lat 4 bytes are ignored,
198+
"""
199+
chunks64 = [data[i : i + 64] for i in range(0, len(data), 64)]
200+
floats = []
201+
for chunk in chunks64[1:]:
202+
float_bytes = chunk[12:-8]
203+
floats.extend(
204+
[struct.unpack("f", float_bytes[i : i + 4])[0] for i in range(0, len(float_bytes), 4)]
205+
)
206+
return floats
207+
208+
hybrid_result = get_floats(hybrid_result_b)
209+
_ = get_floats(counting_result_b)
210+
_ = get_floats(sampling_result_b)
211+
_ = get_floats(micro_counting_result_b) # don't know if they are floats
212+
_ = get_floats(micro_integration_result_b) # don't know if they are floats
213+
_ = get_floats(repetition_count_b)
214+
_ = get_floats(integration_time_b)
215+
_ = get_floats(below_breakdown_measurement_b)
216+
217+
return hybrid_result
212218

213219
async def read_absorbance(self, plate: Plate, wavelength: int) -> List[List[float]]:
214220
"""Read the absorbance from the plate reader. This should return a list of lists, where the

0 commit comments

Comments
 (0)