protocol(mg): decode the type-43 REALTIME_RAW_DATA record on both platforms - #1765
Merged
Merged
Conversation
…tforms The 240-byte type-43 record is the live sample carrier the ryanbr#891/ryanbr#1100 turn-on sequence produces. Its layout was observed on one MG (WS50_r00, fw 50.39.1.0): a constant sub-header at 24..33, 101 i16-LE samples at 34..235, CRC32 trailer. The decoder lives with the other Labrador protocol facts so the consumers to come cannot drift apart, exposes one signal-present rule, and is pure on both platforms with mirrored tests pinning the layout, sign handling, the sample count, and that the sub-header is counted for fill but never decoded as waveform.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Adds a decoder for the 240-byte type-43
REALTIME_RAW_DATArecord — the packet the MG streams once the #1727 turn-on order (139 = 1then124 = 2) has opened the stream. Pure protocol on both platforms: no transport, no UI, no storage, no enum changes, and nothing sent to a strap.The layout, observed across 315 records in one session on a WHOOP MG (
WS50_r00, fw50.39.1.0):What it exposes:
isRealtimeRawRecord,realtimeRawSamples,realtimeRawBodyNonZeroBytes, and onerealtimeRawSignalPresentrule, plus the named offsets.Why it belongs in the protocol layer
Three consumers need this record — a live view, a signal classifier, a waveform export — and in my working tree each had grown its own copy with magic offsets
8/24/34/236and a bare43. Two of them had drifted to different definitions of "signal present": one counted non-zero samples, the other non-zero body bytes. Neither could be tested without a strap.Putting it here with the other Labrador facts means the copies cannot disagree, and the decode gets unit tests that need no hardware. That is the whole PR — the consumers are separate work and none of them is in this diff.
What it does not claim
HEADER_LENGTH) belongs to the FILTERED packet, and whether it also sits inside this record is still open (WHOOP 5 MG: all three TOGGLE_LABRADOR (ECG) commands return SUCCESS and produce no data — six hypotheses, and which ones you can help rule out #891).docs/CONTRIBUTING.md.Type of change
How it was tested
Not on the BLE path. Everything added is a pure function over a byte array.
Six mirrored tests per platform (
Whoop5EcgRawRecordTest/Whoop5EcgRawRecordTests), pinning:signalPresentis one rule shared by every consumer, asserted at its boundary./gradlew testFullDebugUnitTest --rerun-tasks --no-build-cacheon Windows 11 / JDK 17 againstmain@9991f7b: 4,959 tests across 606 classes, 0 failures, 0 errors (6 skipped, pre-existing).Whoop5EcgRawRecordTest6/6, and the neighbouringWhoop5EcgTest(38) andWhoop5EcgProbeTest(20) unchanged and green.python Tools/doc_comment_lint.pyclean.python Tools/i18n_audit.py --ciexit 0.The gap I would rather state than have you find: the Swift half is not run locally, no Apple machine.
Whoop5EcgRawRecordTestslives inPackages/WhoopProtocol, whichswift-packages.ymlcovers. The Swift decoder mirrors the Kotlin one and its tests pin the same six properties, but that is reasoning plus CI rather than a local run — the same declared gap that CI correctly caught on #1727.Checklist
swift-packages.yml./gradlew testFullDebugUnitTest, full suite)StrandDesigntokens — n/a, no UIdocs/CONTRIBUTING.mdRelated issues
Refs #891 and #1100, whose turn-on sequence produces these records, and #1727, which corrected the argument that starts them.
Closes nothing. This is the decode only; what reads it is separate work I would rather propose one piece at a time.