diff --git a/lib/src/control.dart b/lib/src/control.dart index 5da2ad4..1b07e5e 100644 --- a/lib/src/control.dart +++ b/lib/src/control.dart @@ -1016,11 +1016,11 @@ CmdResponse? parseCommandResponse(Uint8List inner, } else if ((op == Cmd.enterHighFreqSync || op == Cmd.exitHighFreqSync)) { dec['high_freq_sync'] = HighFreqSyncResponse(op); } else if (op == Cmd.selectWrist && payload.length >= 3) { - // Status-gated like getHello above: this is a SET-style confirmation, and - // a failure reply does not populate the body, so its bytes are stale. - // Without the check a rejected wrist-selection write (bad value, or - // refused mid-handshake) would still mint a `select_wrist` object that - // looks like confirmation the selection took effect. + // Status-gated like getHello above: this is a SET-style confirmation, + // and a failure reply does not populate the body, so its bytes are + // stale. Without the check a rejected wrist-selection write (bad value, + // or refused mid-handshake) would still mint a `select_wrist` object + // that looks like confirmation the selection took effect. if (status == 1) { dec['select_wrist'] = SelectWristResponse( revision: payload[2], diff --git a/test/whoop_protocol_update_test.dart b/test/whoop_protocol_update_test.dart index eb3ff13..aafba3e 100644 --- a/test/whoop_protocol_update_test.dart +++ b/test/whoop_protocol_update_test.dart @@ -259,6 +259,16 @@ void main() { expect(ack.revision, 1); expect(ack.payload, [0x01, 0x02]); }); + + test('0x7b select wrist response is dropped when cmd_status is not ok', + () { + // Same stale-but-plausible body as above, but cmd_status = 0 (failed) + // — a failure reply's body is unpopulated, so these bytes must not be + // trusted as confirmation the wrist selection took effect. + final inner = hexToBytes('24037b' '0700' '0102'); + final resp = parseCommandResponse(inner)!; + expect(resp.decoded.containsKey('select_wrist'), isFalse); + }); }); group('WHOOP realtime HR revision 2', () {