fix: update event handling in MiniMateClient and protocol to address 5A timeout issue
This commit is contained in:
@@ -178,16 +178,37 @@ echo) — in both cases, all zeros means "no more events."
|
|||||||
there is only one event.
|
there is only one event.
|
||||||
|
|
||||||
**Correct iteration pattern (confirmed empirically with live device, 2+ events):**
|
**Correct iteration pattern (confirmed empirically with live device, 2+ events):**
|
||||||
|
|
||||||
|
`count_events` (browse mode only, no 5A):
|
||||||
```
|
```
|
||||||
1E(all zeros) → key0, trailing0 ← trailing0 non-zero if event 1 exists
|
1E(all zeros) → key0, trailing0 ← trailing0 non-zero if event 1 exists
|
||||||
0A(key0) ← REQUIRED: establishes device context
|
0A(key0) ← REQUIRED: establishes device context
|
||||||
0C(key0) [+ 5A(key0) for get_events] ← read record data
|
1F(all zeros / browse=True) → key1 ← use all-zero params
|
||||||
1F(all zeros / browse=True) → key1 ← use all-zero params, NOT token=0xFE
|
|
||||||
0A(key1) ← REQUIRED before each advance
|
0A(key1) ← REQUIRED before each advance
|
||||||
0C(key1) [+ 5A(key1) for get_events]
|
|
||||||
1F(all zeros) → null ← done
|
1F(all zeros) → null ← done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`get_events` (download mode, with 5A):
|
||||||
|
```
|
||||||
|
1E(all zeros) → key0, trailing0 ← trailing0 non-zero if event 1 exists
|
||||||
|
0A(key0) ← REQUIRED: establishes device context
|
||||||
|
1E(token=0xFE) ← REQUIRED: arms device for 5A; CONFIRMED 4-2-26 + 4-3-26
|
||||||
|
0C(key0) ← read waveform record
|
||||||
|
5A(key0) ← bulk stream (metadata or full waveform)
|
||||||
|
1F(all zeros / browse=True) → key1
|
||||||
|
0A(key1)
|
||||||
|
1E(token=0xFE) ← re-arm for next event's 5A
|
||||||
|
0C(key1)
|
||||||
|
5A(key1)
|
||||||
|
1F(all zeros) → null ← done
|
||||||
|
```
|
||||||
|
|
||||||
|
**The 1E(token=0xFE) arm step is the root cause of the 5A timeout (FIXED 2026-04-06):**
|
||||||
|
The device silently ignores all 5A probe frames unless a second SUB 1E with token=0xFE
|
||||||
|
has been issued between 0A and 0C. This step is present in EVERY download cycle in both
|
||||||
|
the 4-2-26 and 4-3-26 BW TX captures. Without it, `read_bulk_waveform_stream()` blocks
|
||||||
|
for the full 120 s timeout.
|
||||||
|
|
||||||
`advance_event(browse=True)` sends all-zero params; `advance_event()` default (browse=False)
|
`advance_event(browse=True)` sends all-zero params; `advance_event()` default (browse=False)
|
||||||
sends token=0xFE and is NOT used by any caller.
|
sends token=0xFE and is NOT used by any caller.
|
||||||
`advance_event()` returns `(key4, event_data8)`.
|
`advance_event()` returns `(key4, event_data8)`.
|
||||||
|
|||||||
+17
-7
@@ -301,6 +301,19 @@ class MiniMateClient:
|
|||||||
proceed = False
|
proceed = False
|
||||||
|
|
||||||
if proceed:
|
if proceed:
|
||||||
|
# SUB 1E (download-arm) — MUST be sent between 0A and 0C.
|
||||||
|
# The device ignores 5A probe frames unless this second 1E with
|
||||||
|
# token=0xFE has been issued first. Confirmed from both 4-2-26
|
||||||
|
# and 4-3-26 BW TX captures (2026-04-06).
|
||||||
|
# The returned key is the same event key we already hold — ignore it.
|
||||||
|
try:
|
||||||
|
proto.read_event_first(token=0xFE)
|
||||||
|
except ProtocolError as exc:
|
||||||
|
log.warning(
|
||||||
|
"get_events: 1E download-arm failed for key=%s: %s",
|
||||||
|
key4.hex(), exc,
|
||||||
|
)
|
||||||
|
|
||||||
# SUB 0C — full waveform record (peak values, timestamp, "Project:" string)
|
# SUB 0C — full waveform record (peak values, timestamp, "Project:" string)
|
||||||
try:
|
try:
|
||||||
record = proto.read_waveform_record(key4)
|
record = proto.read_waveform_record(key4)
|
||||||
@@ -317,8 +330,6 @@ class MiniMateClient:
|
|||||||
# is found — fetches only ~8 frames for event-time metadata.
|
# is found — fetches only ~8 frames for event-time metadata.
|
||||||
# When full_waveform=True: fetch the complete stream (stop_after_metadata=False,
|
# When full_waveform=True: fetch the complete stream (stop_after_metadata=False,
|
||||||
# max_chunks=128) and decode raw ADC samples into ev.raw_samples.
|
# max_chunks=128) and decode raw ADC samples into ev.raw_samples.
|
||||||
# The full waveform MUST be fetched here, inside the 1E→0A→0C→5A→1F loop.
|
|
||||||
# Issuing 5A after 1F has advanced the event context will time out.
|
|
||||||
try:
|
try:
|
||||||
if full_waveform:
|
if full_waveform:
|
||||||
log.info(
|
log.info(
|
||||||
@@ -364,11 +375,10 @@ class MiniMateClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# SUB 1F — advance to the next record key.
|
# SUB 1F — advance to the next record key.
|
||||||
# Uses browse mode (all-zero params) — empirically confirmed to work on
|
# Uses browse mode (all-zero params) — empirically confirmed to work
|
||||||
# this device. token=0xFE (download mode) returns null regardless of
|
# with 2+ events stored (4-3-26 browse-mode capture). BW itself uses
|
||||||
# context, even after 0A+0C+5A. The 3-31-26 capture only had one event
|
# token=0xFE here in download mode, but browse mode is simpler and
|
||||||
# so we never saw 1F actually return a second key in download mode;
|
# avoids complications with the download-arm state machine.
|
||||||
# the token=0xFE assumption was never validated for multi-event iteration.
|
|
||||||
try:
|
try:
|
||||||
key4, data8 = proto.advance_event(browse=True)
|
key4, data8 = proto.advance_event(browse=True)
|
||||||
log.info(
|
log.info(
|
||||||
|
|||||||
@@ -287,17 +287,22 @@ class MiniMateProtocol:
|
|||||||
log.debug("read_event_index: got %d bytes", len(raw))
|
log.debug("read_event_index: got %d bytes", len(raw))
|
||||||
return raw
|
return raw
|
||||||
|
|
||||||
def read_event_first(self) -> tuple[bytes, bytes]:
|
def read_event_first(self, token: int = 0) -> tuple[bytes, bytes]:
|
||||||
"""
|
"""
|
||||||
Send the SUB 1E (EVENT_HEADER) two-step read and return the first
|
Send the SUB 1E (EVENT_HEADER) two-step read and return the first
|
||||||
waveform key and accompanying 8-byte event data block.
|
waveform key and accompanying 8-byte event data block.
|
||||||
|
|
||||||
This always uses all-zero params — the device returns the first stored
|
Args:
|
||||||
event's waveform key unconditionally.
|
token: Token byte placed at params[7]. Use 0 (default) for the
|
||||||
|
initial browse-mode call that returns the first event key.
|
||||||
|
Use 0xFE for the second "download-arm" call that must be
|
||||||
|
sent between 0A and 0C when full_waveform=True; the device
|
||||||
|
will ignore 5A probe frames unless this arm step has been
|
||||||
|
issued. Confirmed from 4-2-26 and 4-3-26 BW TX captures.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(key4, event_data8) where:
|
(key4, event_data8) where:
|
||||||
key4 — 4-byte opaque waveform record address (data[11:15])
|
key4 — 4-byte opaque waveform record address (data[11:15])
|
||||||
event_data8 — full 8-byte data section (data[11:19])
|
event_data8 — full 8-byte data section (data[11:19])
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -310,13 +315,14 @@ class MiniMateProtocol:
|
|||||||
"""
|
"""
|
||||||
rsp_sub = _expected_rsp_sub(SUB_EVENT_HEADER)
|
rsp_sub = _expected_rsp_sub(SUB_EVENT_HEADER)
|
||||||
length = DATA_LENGTHS[SUB_EVENT_HEADER] # 0x08
|
length = DATA_LENGTHS[SUB_EVENT_HEADER] # 0x08
|
||||||
|
params = token_params(token)
|
||||||
|
|
||||||
log.debug("read_event_first: 1E probe")
|
log.debug("read_event_first: 1E probe (token=0x%02X)", token)
|
||||||
self._send(build_bw_frame(SUB_EVENT_HEADER, 0))
|
self._send(build_bw_frame(SUB_EVENT_HEADER, 0, params))
|
||||||
self._recv_one(expected_sub=rsp_sub)
|
self._recv_one(expected_sub=rsp_sub)
|
||||||
|
|
||||||
log.debug("read_event_first: 1E data request offset=0x%02X", length)
|
log.debug("read_event_first: 1E data request offset=0x%02X (token=0x%02X)", length, token)
|
||||||
self._send(build_bw_frame(SUB_EVENT_HEADER, length))
|
self._send(build_bw_frame(SUB_EVENT_HEADER, length, params))
|
||||||
data_rsp = self._recv_one(expected_sub=rsp_sub)
|
data_rsp = self._recv_one(expected_sub=rsp_sub)
|
||||||
|
|
||||||
event_data8 = data_rsp.data[11:19]
|
event_data8 = data_rsp.data[11:19]
|
||||||
|
|||||||
Reference in New Issue
Block a user