From 918eab33e7bc4c2dffab59c041ddfbcc57838ebc Mon Sep 17 00:00:00 2001 From: Alex Wagner Date: Tue, 25 Aug 2026 16:17:07 +0200 Subject: [PATCH] record the hello revision byte instead of gating on it The official 5.458.0 parser records body[0] but reads the fixed revision-1 offsets regardless of its value; only the short-body rejection is a real parse failure. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01DCrELi9LMQr55gW9hCJoeN --- lib/src/control.dart | 9 ++++----- test/gen5_historical_test.dart | 11 +++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/src/control.dart b/lib/src/control.dart index d62b563..482181d 100644 --- a/lib/src/control.dart +++ b/lib/src/control.dart @@ -414,16 +414,15 @@ class Gen5HelloInfo { /// Parse EXACTLY the response body (no header). Returns null when the body is /// shorter than the [semanticBodyLen] the fixed-offset parser needs — a short - /// body is a failed/foreign reply, never a partially-filled hello — or when - /// the body does not announce hello revision 1, since every offset below is - /// revision-1-specific and reading them out of an unknown revision would - /// invent an identity rather than decode one. + /// body is a failed/foreign reply, never a partially-filled hello. The + /// revision byte is recorded in [helloRevision] but is not a gate: the + /// official parser reads the fixed revision-1 offsets regardless of its + /// value. /// /// Callers should additionally gate on the command-response STATUS byte; a /// non-success reply leaves the body unpopulated (see [parseCommandResponse]). static Gen5HelloInfo? parse(Uint8List body) { if (body.length < semanticBodyLen) return null; - if (body[0] != 1) return null; // revision-1 map only String cstr(int start, int end) { final sb = StringBuffer(); for (int i = start; i < end && i < body.length; i++) { diff --git a/test/gen5_historical_test.dart b/test/gen5_historical_test.dart index 2a917a6..66df0a0 100644 --- a/test/gen5_historical_test.dart +++ b/test/gen5_historical_test.dart @@ -799,10 +799,17 @@ void main() { } }); - test('an unknown hello revision is refused, not read at rev-1 offsets', () { + test('a non-1 hello revision still parses at the fixed offsets', () { + // The revision byte is recorded, not a gate — the official parser reads + // the fixed offsets regardless of its value. final body = gen5HelloBody(); body[0] = 2; // some future revision - expect(Gen5HelloInfo.parse(body), isNull); + final h = Gen5HelloInfo.parse(body)!; + expect(h.helloRevision, 2); + expect(h.batteryPct, 90); + expect(h.serial, '5AG0000001'); + expect(h.firmwareVersion, '50.40.1.0'); + expect(h.wristOn, isTrue); }); test('an out-of-range battery is omitted, never clamped', () {