feat(android): assemble vehicle VIN from DashKit CAN stream (1/3) - #206
feat(android): assemble vehicle VIN from DashKit CAN stream (1/3)#206dkneeland wants to merge 2 commits into
Conversation
2c2f9c1 to
6d31a4e
Compare
ℹ️ Reading the
|
| Deleted lines | What actually happened |
|---|---|
| ~20 lines — the inline CAN wire-format parsing loop | Moved verbatim to parseCanPacket() in the new CanPacket.kt (needed as a shared seam so each raw frame now feeds two consumers: the dashboard decoder and the VIN assembler). Byte-for-byte same bounds checks, offsets, and LE decode. |
~13 lines — direct CCCD descriptor write in onServicesReady() |
Replaced by manager.subscribeWithRetry(...) (DashKitBleManager.kt, +41 in this PR). The old write ignored failures; Android silently refuses CCCD writes that race another GATT operation, which caused intermittent dropped CAN subscriptions. The helper retries. This is the only behavioral change in the file, and it's a bug fix. |
~8 lines — imports + stale CCCD_UUID / hardware-filtering comment |
Follow the two moves above; the comment described code that no longer exists here. |
What the additions (+27) actually are: VIN wiring only — vinState flow, assembler feed inside the (unchanged) frame loop, resetVin() on session teardown boundaries, and the retry-helper call site.
Net effect on existing functionality: none. Frame extraction is line-identical logic, decodeFrame runs in the same order on the same data, emission cadence (sample(40), single tryEmit per notification) is untouched, and VIN stays out of CarState. The relocated parser is unit-tested directly in CanPacketVinTest (ordering, batching, truncated packets).
Suggested review approach: skim this file for the VIN wiring, then review CanPacket.kt as if the deleted block had been pasted there (it essentially was).
Android's GATT client allows one operation in flight; a CCCD write that races another subscribe is silently refused, leaving CAN notifications dead until reconnect. Replace the fire-and-forget descriptor write in DashKitDataSource with DashKitBleManager .subscribeWithRetry(), which verifies the write was queued and retries (up to 3x, 250ms apart). The helper is shared and will also back the Tesla status subscription.
Add VehicleVinAssembler, a pure-Kotlin assembler for the muxed VIN frames (bus 1, CAN id 0x405) carried by the existing DashKit BLE CAN notification stream. Extract CanPacket parsing so raw (bus, address, data) tuples feed both dashboard decoding and the assembler, with the firmware build_ble_packet wire format documented alongside the parser; subscription moves to subscribeWithRetry to survive GATT-busy CCCD races. Expose ConnectionViewModel.vehicleVin as a dedicated replaying state flow; keep VIN out of CarState and reset it during connection teardown. Includes parser and assembler unit tests (ordering, duplicates, batching, malformed packets).
6d31a4e to
dd2da90
Compare
|
Superseded by the re-layered 4-PR stack - the GATT-subscribe-retry fix was extracted into its own standalone bottom layer so it can ship independently of feature review:
Merge order: 210 -> 211 -> 212 -> 213. Trees of layers 2-4 are byte-identical to this PR's reviewed content (only ancestry changed); layer diffs verified per-layer. |
Part 1 of 3 of a stacked series that supersedes #201 (closed; work redistributed across this stack).
What & why
Reads the vehicle VIN directly from DashKit's existing BLE CAN notification stream so Tesla enrollment can stop asking the user to type it.
VehicleVinAssembler— pure-Kotlin assembler for the muxed VIN frames (bus 1, CAN id0x405, mux0x10/0x11/0x12). Accepts segments in any order, tolerates duplicates, rejects short frames / unknown mux / non-ASCII / illegal VIN chars, emits only when all 17 chars validate, resets on teardown. Raw ASCII bytes are joined directly — no 56-bit DBCDoubleround-trip.CanPacket— extracted raw(bus, address, data)tuple parsing shared by dashboard decoding and the assembler, with the firmwarebuild_ble_packetwire format documented alongside the parser.DashKitDataSourcefeeds the assembler per frame; exposesvinState.ConnectionViewModel.vehicleVin— dedicated replaying flow; deliberately not added toCarState(stays out of the dash-app data contract); reset during connection teardown.DashKitBleManager.subscribeWithRetry()— generic CCCD-write retry helper shared by the CAN and Tesla status subscriptions (GATT-busy race fix, moved here from the closed PR since the data source needs it).No user-visible behavior change; additive and inert until Part 3 consumes the flow.
Tests
Assembler unit tests (ordering, duplicates, special mux-A offsets, malformed input) and data-source integration tests (single/multi-notification assembly, batching, truncated packets, unchanged
CarStatedecoding). FulltestDebugUnitTestgreen at carve time againstmain@b506147.Stack & merge order
mainSquash-merge this first. The next PR's base will retarget once this branch is deleted — click Update branch there so its diff collapses to just its own changes (repo uses squash merges).