fix: correct event count field offset and eliminate count_events() walk

_decode_event_count: read uint16 BE at offset 10 (confirmed 2026-04-10 from
live BE11529 event index — data[10:12]=0x0006=6, matches device LCD).
Previous uint32 at offset 3 always returned 1 regardless of event count.

ach_server.py: use device_info.event_count (already fetched during connect())
instead of calling count_events() separately. This saves 2*N round-trips and
avoids the 1F linked-list walk which was overcounting on some devices.
count_events() kept as fallback when connect() is skipped (--events-only).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 01:10:49 -04:00
parent 9d9c14af79
commit 3d2ebfc057
2 changed files with 24 additions and 28 deletions
+10 -21
View File
@@ -910,36 +910,25 @@ def _decode_event_count(data: bytes) -> int:
"""
Extract stored event count from SUB F7 (EVENT_INDEX_RESPONSE) payload.
Layout per §7.4 (offsets from data section start):
+00: 00 58 09 — total index size or record count ❓
+03: 00 00 00 01 — possibly stored event count = 1 ❓
Confirmed 2026-04-10 from live BE11529 event index (88 bytes):
data[10:12] uint16 BE = stored event count (confirmed: 0x0006 = 6, matches LCD)
data[3:7] uint32 BE = 0x00000001 (NOT the count — meaning TBD)
We use bytes +03..+06 interpreted as uint32 BE as the event count.
This is inferred (🔶) — the exact meaning of the first 3 bytes is unclear.
Previous implementation read uint32 at offset 3, which returned 1 regardless
of how many events were stored.
"""
if len(data) < 7:
if len(data) < 12:
log.warning("event index payload too short (%d bytes), assuming 0 events", len(data))
return 0
# Log the full payload so we can reverse-engineer the format
log.warning("event_index raw (%d bytes total):", len(data))
for off in range(0, len(data), 16):
chunk = data[off:off+16]
hex_part = " ".join(f"{b:02x}" for b in chunk)
asc_part = "".join(chr(b) if 0x20 <= b < 0x7f else "." for b in chunk)
log.warning(" [%04x]: %-47s %s", off, hex_part, asc_part)
count = struct.unpack_from(">H", data, 10)[0]
# Try the uint32 at +3 first
count = struct.unpack_from(">I", data, 3)[0]
# Sanity check: MiniMate Plus manual says max ~1000 events
# Sanity check: MiniMate Plus max storage is ~1000 events
if count > 1000:
log.warning(
"event count %d looks unreasonably large — clamping to 0", count
)
log.warning("event count %d looks unreasonably large — clamping to 0", count)
return 0
log.warning("event_index decoded count=%d (uint32 BE at offset +3)", count)
log.debug("event_index decoded count=%d (uint16 BE at offset 10)", count)
return count