10 KiB
HV BT Dashboard — Data Layer Handoff
Context for continuing work on the S300/KPro Bluetooth data layer. Paste this into a new chat to resume.
To be continued tomorrow — debugging in progress, session ended mid-investigation
Was actively live-debugging a connection lockup with the phone connected and a flutter run session attached when the user had to leave. Nothing is currently running (flutter session and Monitor were both stopped cleanly), but the investigation is mid-thread — see "Today's session" below for exactly where it left off, and pick up from "Next steps for tomorrow" at the end.
The temporary debug print is still active in sensor_provider.dart (search for TEMP: live-debugging session, remove after — two spots, a dbgFrameCount counter and a print(...) call). It logs template/rpm/gear/ect/fuelPump/mil/vtec/fan/sw2 for S300 frames, throttled to ~2/sec. Don't re-add it tomorrow — it's already there. Remove it once this investigation is actually closed out.
Reference documents (in project root)
hvbt_protocol.pdf— legacy fixed-offset frame protocol (what the app currently uses). Ground truth for byte offsets/formulas, though its own offset labels are internally inconsistent — don't trust them without a live capture.Bluetooth.pdf— Hondata's official, newer, self-describing channel-based protocol (v1.6, 2020). Confirmed via live probe that this specific hardware does NOT support it — legacy protocol is the only option.Requrements.pdf— original customer UI/UX requirements, references a "TunerView" app as the visual benchmark.
Today's session: fuel pump held-during-template fix, then a fresh reproduction of the lockup
- Fixed:
fuelPump,mil,vtec,fanOutare now also held from last-known-good during S300 template frames (sensor_provider.dart), not just RPM/VSS/MAP/etc and gear/ECT/IAT/BAT from the previous round. This was prompted by the user seeing fuel pump flip to a wrong value after leaving the app idle without changing anything on the bench — consistent with the connection sitting in a run of template frames (where SW2 was still being decoded fresh and showing whatever the frozen pattern happened to contain) during that idle stretch. - Reproduced a worse case live: reconnected and watched a fresh session start with 100% template frames — zero live frames — for the first 103+ consecutive polls. Since
lastGoodhad never been populated yet (no live frame had ever arrived), the hold logic had nothing to fall back on and just displayed raw template garbage (RPM=0, gear=1) directly. A manual disconnect/reconnect fixed it — RPM immediately started tracking real changes again (535 of the next 1159 frames were live). - User raised a valid concern: will this lockup recur after sitting idle again? Proposed (but did not build, pending a decision) an auto-reconnect feature: detect N consecutive template frames with zero live data and trigger an automatic disconnect+reconnect, rather than requiring the user to notice and do it manually.
- It recurred within the same debugging session, unprompted, while just sitting idle — caught a long run of
template=true, rpm=0again in the log. It eventually broke free on its own (one live frame came through), but then the live debug session itself died:flutter runreported "Lost connection to device" and exited (the background bash task completed with exit code 0). This is the phone's USB/ADB link to the laptop dropping, not necessarily the phone's Bluetooth link to the ECU — those are two different connections and losing one doesn't necessarily mean the other dropped too. - Unresolved when the session ended: whether the app itself (on the phone, independent of the USB debug tether) is still running/connected to the ECU via Bluetooth, or whether it also crashed/disconnected. Debug builds tied to an active
flutter runsession sometimes get killed when that session ends — this needs to be checked first thing tomorrow.adb devicesshowed the phone reachable again by the end of the session, so the USB/ADB link itself recovered at least.
Next steps for tomorrow, in order
- Check whether the app survived the "Lost connection to device" event — is it still open and showing data on the phone, or did it close? If it closed, that's itself worth understanding (does losing the USB/ADB tether kill the debug-mode app process, or was this a coincidental separate crash?).
- Decide on the auto-reconnect feature (see point 3 above) — now that the lockup has reproduced twice in one session, including a from-cold-start 100%-template case that the hold-last-good-value fix can't help with at all, this is probably worth building. Tradeoff to weigh: an automatic reconnect means a brief, visible disconnect/reconnect blip whenever it triggers, and if tuned too aggressively could interrupt a legitimately long-but-real stretch of template frames.
- Relaunch live debugging (see Environment notes) to keep characterizing the lockup — specifically it would help to know: does it always eventually self-recover (like it did once today), or does it sometimes stay stuck indefinitely without a manual reconnect? How long does a "stuck" stretch typically last? Does it correlate with anything (idle time specifically, or could be triggered by anything)?
- Once the lockup itself is on firmer ground, return to the still-open data fields below.
Confirmed & fixed (shipped, working — from before today, still holding)
- RPM, VSS, MAP, IGN formulas: match the official doc / live captures. (IGN's formula itself may be worth a second look — one live check showed a big mismatch — not investigated further, low priority.)
- TPS (offset 9,
raw*100/255), Gear (offset 27): confirmed correct against live USB captures. - ECT (offset 33), IAT (offset 34), BAT (offset 36): all moved from earlier wrong offsets and confirmed via live capture matching USB closely.
- Fuel Pump (SW2 bit 2, active-low:
(sw2 & 0x04) == 0): confirmed correct when frame is live (non-template). - S300 "template frame" detection and hold logic:
isS300TemplateFrame()ins300_parser.dartdetects the frozen byte pattern (bytes 0-16, plus bytes 32-36 covering gear/ECT/IAT/BAT).sensor_provider.dartnow holds RPM/VSS/MAP/TPS/INJ/IGN/knock/O2/gear/ECT/IAT/BAT/fuelPump/mil/vtec/fanOut from last-known-good during these frames. This only works once at least one live frame has been seen — a connection stuck in 100% template from the very start has nothing to hold and shows raw garbage (see today's session, point 2). - Root cause of the template-frame phenomenon itself is still unknown. Most likely an adapter-side sampling/buffering limitation, possibly related to whatever's now also causing full lockups (100% template, no live frames at all) after idle periods — these might be the same underlying issue at different severities, not two separate problems.
- Bluetooth ECU-type persistence: connecting no longer shows a "S300 or KPro?" popup every time — it connects directly using whatever's set in Settings (persisted via
SharedPreferences, survives app restart).bt_picker_screen.dart/settings_provider.dart. - Sanity clamp, dashboard scrolling, official protocol probe: unchanged from before, still working.
- Clear DTC command: still not getting acknowledged over Bluetooth despite the ECU accepting it via USB — unresolved, lower priority than the connection lockup.
Still open — data fields needing live data to resolve (lower priority than the lockup investigation above)
- SW1 during template frames — never actually confirmed either way for this specific frame type.
- AFR: confirmed wrong (aliased to ERR03's byte). No correct offset found.
- PA: candidate at offset 50 is close (~3 kPa off) but not confirmed.
- IGN formula: flagged as possibly wrong, not investigated.
Verification method that has worked every time
- Set a bench value to something specific and known.
- Screenshot the USB tool's reading (fuller flag panel = more cross-checks per shot).
- Attach a live debug session and read raw frame data straight from the console at the same moment — cross-check RPM between the screenshot and the log line to confirm they're actually simultaneous.
- Compute the byte offset/formula that reproduces the known value.
- Get a second data point or a stability check across many consecutive frames before changing code.
Do not guess offsets from the PDF's offset column labels alone. Always confirm against a live capture, and always check whether the frame in question is a template frame before trusting its bytes beyond 16.
Not started yet (deferred until data layer + connection stability are solid)
UI/UX gaps from Requrements.pdf: dashboard tile count (need 10, have 6), missing "SubSensor" next to main gauge, flag pills should be selectable (spec says 4, currently a fixed 7), datalog playback not wired to live display screens.
Environment notes
- Test device: Samsung SM_S948W,
adb -s R3GL40CPKMP(transport ID changes across reconnects, device serial stays the same). - Build/install cycle:
flutter build apk --debugthenadb -s R3GL40CPKMP install -r build\app\outputs\flutter-apk\app-debug.apk. - Live debug session (preferred method, used heavily and successfully this whole project):
flutter run -d R3GL40CPKMP --debug(run in background). Pair with a Monitor that dedupes or does stateful filtering (e.g. only alert on entering/leaving a "stuck" run of N consecutive template frames) rather than raw tail+grep, which gets rate-limited. Known failure mode: the session can die with "Lost connection to device" if the phone's USB/ADB link drops — checkadb devicesand relaunch if so. - All parser changes should get a unit test in
test/s300_parser_test.dart(orkpro_parser_test.dart) built from actual captured bytes. git statusshows all data-layer, DTC/debug-screen, and BT-connection changes as uncommitted modifications, plus the three reference PDFs and this handoff doc as untracked. Nothing has been committed this project.