From 242666f3583134b9920790970f7ca1e3e90aec86 Mon Sep 17 00:00:00 2001 From: Brian Harrison Date: Fri, 24 Apr 2026 12:52:02 -0400 Subject: [PATCH] fix(protocol): correct chunk counter formula for accurate data streaming --- minimateplus/protocol.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/minimateplus/protocol.py b/minimateplus/protocol.py index 9f48bc5..5a2537f 100644 --- a/minimateplus/protocol.py +++ b/minimateplus/protocol.py @@ -583,8 +583,17 @@ class MiniMateProtocol: frames_data: list[S3Frame] = [] counter = 0 + # BW counter formula (confirmed from 4-3-26 capture for key 0111245a): + # counter for chunk n = key4[2:4] + (n - 1) * 0x0400 + # key4[2:4] is the event's circular-buffer base offset — without it, chunk + # requests address the wrong region of the device buffer and the device + # streams data from the wrong event (no "Project:" in any response). + # PREVIOUSLY WRONG NOTE: "device does not validate counter; chunk_num*0x0400 + # is correct" — that was only true for key 01110000 where key4[2:4]==0x0000. + _key4_offset = (key4[2] << 8) | key4[3] + # ── Step 1: probe ──────────────────────────────────────────────────── - log.debug("5A probe key=%s", key4.hex()) + log.debug("5A probe key=%s key4_offset=0x%04X", key4.hex(), _key4_offset) params = bulk_waveform_params(key4, 0, is_probe=True) self._send(build_5a_frame(_BULK_CHUNK_OFFSET, params)) self._parser.reset() # reset bytes_fed counter before probe recv @@ -601,13 +610,15 @@ class MiniMateProtocol: log.debug("5A A5[0] page_key=0x%04X %d bytes", rsp.page_key, len(rsp.data)) # ── Step 2: chunk loop ─────────────────────────────────────────────── - # Chunk counters are monotonic: chunk_num * 0x0400 for all chunks. - # The 4-2-26 BW TX capture showed 0x1004 for chunk 1, but this is a - # Blastware artifact — the device accepts any counter value and streams - # data regardless. Empirically confirmed 2026-04-06: 0x0400 for chunk 1 - # works; 0x1004 causes the device to ignore the frame (timeout). + # Correct counter formula: key4[2:4] + (chunk_num - 1) * 0x0400 + # This matches Blastware exactly (confirmed from 4-3-26 capture). + # For events where key4[2:4]==0 (e.g. 01110000), this gives the same + # result as the old chunk_num*0x0400 formula shifted by one step, which + # the device also accepted — but for events with a non-zero base offset + # (e.g. key 01111884 with key4[2:4]=0x1884) the old formula sends + # completely wrong counters and the device streams the wrong buffer region. for chunk_num in range(1, max_chunks + 1): - counter = chunk_num * _BULK_COUNTER_STEP + counter = _key4_offset + (chunk_num - 1) * _BULK_COUNTER_STEP params = bulk_waveform_params(key4, counter) log.debug("5A chunk %d counter=0x%04X", chunk_num, counter) self._send(build_5a_frame(_BULK_CHUNK_OFFSET, params)) @@ -662,7 +673,7 @@ class MiniMateProtocol: chunk_num, extra_chunks_after_metadata) for _extra_n in range(extra_chunks_after_metadata): chunk_num += 1 - counter = chunk_num * _BULK_COUNTER_STEP + counter = _key4_offset + (chunk_num - 1) * _BULK_COUNTER_STEP params = bulk_waveform_params(key4, counter) self._send(build_5a_frame(_BULK_CHUNK_OFFSET, params)) try: