You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Devices/Test Centre "Clock latched" readout (ConnectionReadout.clockLatchedLabel) reads "no (waiting for the strap clock)" on every WHOOP 5.0/MG connection, regardless of whether the strap's clock is actually set — not just on a fresh strap with no banked history.
Root cause
GET_CLOCK's COMMAND_RESPONSE is sent to WHOOP 5/MG straps (as part of the #78 fix that made history offload work) and the strap does reply, but the reply is silently dropped end-to-end:
decodeWhoop5CommandResponse (Packages/WhoopProtocol/Sources/WhoopProtocol/Interpreter.swift) only handles GET_BATTERY_LEVEL, GET_DATA_RANGE, and GET_HELLO — there's no case for GET_CLOCK (cmd 11), so parsed["clock"] never gets set for a 5/MG frame.
FrameRouter.swift's COMMAND_RESPONSE handling gates its per-command branches on family == .whoop4 — nothing routes a 5/MG GET_CLOCK reply anywhere.
The documented fallback signal (strapNewestUnix, from GET_DATA_RANGE, added in on DEVICES, the strap says Clock latched: no #261) is also dead for 5/MG: GET_DATA_RANGE (cmd 34) is never sent to a 5/MG strap at all — the only call site is inside the WHOOP4-only connect-handshake block.
So both inputs to clockLatchedLabel are structurally nil for the whole 5/MG family.
Plan
Add a GET_CLOCK debug probe (mirroring the #592/#690 extended-battery/body-location probe pattern) to capture the raw WHOOP 5.0 GET_CLOCK COMMAND_RESPONSE payload from real hardware.
Use the captured bytes to write a real decodeWhoop5CommandResponse case for GET_CLOCK, wire it through FrameRouter, and feed a real signal into clockLatchedLabel for 5/MG.
Android: deferred to a follow-up once the Swift/macOS side is confirmed on hardware.
Note: GET_DATA_RANGE never being sent for 5/MG at all is a separate, likely more impactful gap — tracked separately, out of scope here.
Problem
The Devices/Test Centre "Clock latched" readout (
ConnectionReadout.clockLatchedLabel) reads "no (waiting for the strap clock)" on every WHOOP 5.0/MG connection, regardless of whether the strap's clock is actually set — not just on a fresh strap with no banked history.Root cause
GET_CLOCK's COMMAND_RESPONSE is sent to WHOOP 5/MG straps (as part of the #78 fix that made history offload work) and the strap does reply, but the reply is silently dropped end-to-end:decodeWhoop5CommandResponse(Packages/WhoopProtocol/Sources/WhoopProtocol/Interpreter.swift) only handlesGET_BATTERY_LEVEL,GET_DATA_RANGE, andGET_HELLO— there's no case forGET_CLOCK(cmd 11), soparsed["clock"]never gets set for a 5/MG frame.FrameRouter.swift'sCOMMAND_RESPONSEhandling gates its per-command branches onfamily == .whoop4— nothing routes a 5/MG GET_CLOCK reply anywhere.strapNewestUnix, fromGET_DATA_RANGE, added in on DEVICES, the strap says Clock latched: no #261) is also dead for 5/MG:GET_DATA_RANGE(cmd 34) is never sent to a 5/MG strap at all — the only call site is inside the WHOOP4-only connect-handshake block.So both inputs to
clockLatchedLabelare structurally nil for the whole 5/MG family.Plan
#592/#690extended-battery/body-location probe pattern) to capture the raw WHOOP 5.0 GET_CLOCK COMMAND_RESPONSE payload from real hardware.decodeWhoop5CommandResponsecase for GET_CLOCK, wire it throughFrameRouter, and feed a real signal intoclockLatchedLabelfor 5/MG.Note:
GET_DATA_RANGEnever being sent for 5/MG at all is a separate, likely more impactful gap — tracked separately, out of scope here.