BLE CSC wheel sensor client and wheel-circumference calibration #18

Closed
opened 2026-08-31 17:14:40 +02:00 by robert · 1 comment
robert commented 2026-08-31 17:14:40 +02:00 (Migrated from git.butzei.de)

Goal

Optional wheel sensor for instant, tunnel-proof speed.

Acceptance criteria

  • Scan for and connect to the standard BLE Cycling Speed and Cadence service 0x1816
  • CSC Measurement characteristic 0x2A5B parsed: cumulative wheel revolutions and last wheel event time
  • 16-bit event-time and 32-bit revolution wraparound handled correctly
  • Wheel circumference configurable, with common presets
  • Auto-reconnect when the sensor wakes
  • Sensor battery level read where the peripheral exposes it

Files

  • companion/.../sensors/CscClient.kt
## Goal Optional wheel sensor for instant, tunnel-proof speed. ## Acceptance criteria - [ ] Scan for and connect to the standard BLE Cycling Speed and Cadence service `0x1816` - [ ] `CSC Measurement` characteristic `0x2A5B` parsed: cumulative wheel revolutions and last wheel event time - [ ] 16-bit event-time and 32-bit revolution wraparound handled correctly - [ ] Wheel circumference configurable, with common presets - [ ] Auto-reconnect when the sensor wakes - [ ] Sensor battery level read where the peripheral exposes it ## Files - `companion/.../sensors/CscClient.kt`
Owner

Closed by PR #99 (merged): CSC UUIDs verified live against the current Bluetooth SIG spec (0x1816/0x2A5B/0x2A5C), wraparound-safe uint32/uint16 delta math via Math.floorMod (JVM's always-non-negative modulo, not %'s sign-follows-dividend), 23 host tests including fixtures that actually cross real uint16 and uint32 rollover boundaries. WheelSpeedTracker wired directly against #44's WheelCircumference settings type. Sensor state modeled as a proper sealed class (NotConnected/Scanning/Connecting/Reconnecting/Connected) so "no sensor" and "sensor stationary" (NoNewRevolution) can never collapse into a fabricated 0 speed \u2014 sets #19 (speed-source arbitration) up to consume this honestly later.\n\nReal bug caught by actually compiling against this project's real compileSdk 37: API 37 deprecates the old connectGatt(Context, boolean, callback, transport) overload in favor of connectGatt(BluetoothGattConnectionSettings, Executor, callback) \u2014 confirmed via the installed SDK's api-versions.xml, not assumed. AndroidCscClient branches on SDK_INT since minSdk is 31.\n\nVerified: :companion:core:test 23/23, :companion:sensors:assembleDebug/:companion:assembleDebug both clean. No Bluetooth hardware in this sandbox \u2014 the scan/connect/notify path against a real sensor was compiled, not exercised.

Closed by PR #99 (merged): CSC UUIDs verified live against the current Bluetooth SIG spec (0x1816/0x2A5B/0x2A5C), wraparound-safe uint32/uint16 delta math via Math.floorMod (JVM's always-non-negative modulo, not %'s sign-follows-dividend), 23 host tests including fixtures that actually cross real uint16 and uint32 rollover boundaries. WheelSpeedTracker wired directly against #44's WheelCircumference settings type. Sensor state modeled as a proper sealed class (NotConnected/Scanning/Connecting/Reconnecting/Connected) so \"no sensor\" and \"sensor stationary\" (NoNewRevolution) can never collapse into a fabricated 0 speed \u2014 sets #19 (speed-source arbitration) up to consume this honestly later.\n\n**Real bug caught by actually compiling against this project's real compileSdk 37**: API 37 deprecates the old connectGatt(Context, boolean, callback, transport) overload in favor of connectGatt(BluetoothGattConnectionSettings, Executor, callback) \u2014 confirmed via the installed SDK's api-versions.xml, not assumed. AndroidCscClient branches on SDK_INT since minSdk is 31.\n\n**Verified**: `:companion:core:test` 23/23, `:companion:sensors:assembleDebug`/`:companion:assembleDebug` both clean. No Bluetooth hardware in this sandbox \u2014 the scan/connect/notify path against a real sensor was compiled, not exercised.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
robert/PedalPebble#18
No description provided.