Cadence from the CSC sensor #49
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Depends on
#18 BLE CSC wheel sensor client and wheel-circumference calibration
robert/PedalPebble
Reference
robert/PedalPebble#49
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
The Cycling Speed & Cadence characteristic already being parsed for wheel speed also carries crank revolutions. Exposing cadence is nearly free.
Acceptance criteria
0x2A5BFiles
companion/.../sensors/CscClient.ktwatchapp/src/c/view_ride.cNotes
See docs/DECISIONS.md D16.
Closed by PR #108 (merged). Crank-field decoding already existed from #18 (CrankRevolutionData off the 0x2A5B characteristic); this issue's real scope was the raw-to-RPM conversion and wiring it anywhere. New CrankCadenceTracker mirrors WheelSpeedTracker exactly, reusing uint16Delta for both crank fields (revolution count and event time are both 16-bit per the CSC spec), with a real rollover test. Feeds AvgCadenceAccumulator (#65) end to end for real now -- that gap is closed.
Real bug found and fixed along the way: AndroidCscClient.handleMeasurement previously did
measurement.wheel ?: return, so any crank-only sensor's notifications (no wheel field at all) never updated state at all -- cadence was structurally unreachable for that whole device class. Wheel and crank fields are now processed independently, each falling back to its own last-known value when a given notification doesn't carry it, rather than one missing field dropping the whole update.Wheel-only vs. stopped-cranks are kept distinct: CscSensorState.Connected.cadence is CadenceSample? -- null means this sensor has never reported crank data at all (encodes to the real UINT8 sentinel, never 0), while CadenceSample.NoNewRevolution means a real cadence sensor with stationary cranks (encodes to a genuine 0). Two different types, not two branches of one nullable number.
Verified for real: :companion:core:test, :companion:pebble:testDebugUnitTest, :companion:assembleDebug (touched Android-SDK-bound AndroidCscClient.kt) all green.
Out of scope, stated explicitly: watch-side display (watchapp/) and GPX TrackPointExtension recording (no ride-recording pipeline exists in companion/ yet to hang it on).