Files
yaris-obd/BUGS.md
T
Mathieu Moran c9d36cca33 docs: close BUG-23 + record fix in Phase 29
Move BUG-23 to Resolved with commit 78aea2d and verification (Pi trips
57 -> 49 after rebuild). Add matching entry to PLAN.md Phase 29.
2026-08-15 16:08:29 -04:00

16 KiB
Raw Blame History

yaris-obd Bug Tracker

Standalone bug/issue tracker. One ## BUG-XX per issue. Numbering sequential. Status: OPEN → IN PROGRESS → CLOSED (with commit ref + verification). When CLOSED, move the entire entry to Resolved — don't duplicate.


Open bugs

BUG-19 — Dashboard OBD values slow to appear while the car is running

  • Status: OPEN 2026-08-13
  • Phase: 29
  • Symptom: on the Pi dashboard, the speed/RPM/coolant/fuel/throttle cards stay on "—" for a long time after the page loads (or after ignition) before populating, even though the car is running and OBD is connected.
  • Cause: the value cards were populated only by socket.io push events from the OBD polling threads — the dashboard never pulled a current snapshot on load, so a freshly loaded page had to wait for the next poll tick (plus any reconnect/probe latency). /api/obd/status only returned the connection state, not the actual values, so there was no REST fallback either.
  • Fix: emit a full current-value snapshot on socket connect, and extend /api/obd/status to return live speed/RPM/coolant/fuel/throttle/MIL so the dashboard fills the cards immediately on load (and every 15 s) via REST. Needs in-car verification.

Resolved

BUG-23 — Pi and server trip counts diverge (server drops short trips the Pi keeps)

  • Status: CLOSED 2026-08-15
  • Commit: 78aea2d
  • Fix: the Pi's build_trip_summaries() now applies the same minimum-trip filter as the server (duration < 30s OR distance < 0.05km → reject), so GPS lock-in drift while the car is stationary no longer spawns false trips. It also sorts normalized rows by datetime (the server orders by recorded_at ASC), so clock-rollback rows can't make a trip span a backwards time jump. TRIP_BUILD_VERSION bumped 3 → 4 to force a Pi rebuild.
  • Verification: unit tests updated and pass (12/12), including a new regression test for short GPS-drift rejection. On the Pi, trips dropped 57 → 49 after rebuild (trip_build_state = (8562, 4)). The remaining gap vs the portal's 10 is the 41 intentionally-deleted trips (server-side deleted_trip_markers) plus ~2 trips from the server holding 279 more raw points than the Pi — both documented in the original analysis, not regressions.

BUG-22 — Trip max speed ignores GPS-only stretch (shows OBD max only)

  • Status: CLOSED 2026-08-14
  • Commit: 90cfd7b
  • Fix: max_speed_kmh was computed from OBD speeds only, so the top speed reached during the 20-min OBD dropout wasn't reflected. Both trip builders now union OBD speeds with GPS-derived speeds computed over a trailing ~30s window (GPS_SPEED_WINDOW=6) to average out GPS position jitter — raw 5s segments swing wildly (e.g. 58→141→58 km/h, peaks ~162), so an unsmoothed union overshoots the real top speed. Also bumped TRIP_BUILD_VERSION to force a Pi-side trip rebuild.
  • Verification: trip #9 max went 111 (OBD-only) → 162 (raw union) → 119 (smoothed), and trip #8 → 127.8, identical on the server and the Pi. The 135.6 the scrubber showed was a single noisy 5s GPS sample, not the sustained top speed.

BUG-21 — OBD speed drops out mid-drive, replay shows 0 km/h (GPS-only)

  • Status: CLOSED 2026-08-14
  • Commit: 7c8f27b
  • Fix: the Pi's OBD adapter (ELM327) stopped returning speed for ~20 min on 2026-08-13 (last OBD reading 22:23:50 UTC, back at 22:43:41 UTC), so the portal replay flatlined at 0 km/h for that stretch. The server's get_trip_route() now mirrors the Pi's route_points GPS-speed fallback — when OBD speed is missing it derives speed from the previous point's movement (haversine / elapsed time, ≥8 m, ≤220 km/h). The Pi's own replay already did this; only the portal was missing it.
  • Verification: trip #9 points at 22:23:55 previously returned speed 0.0 — now return GPS-derived speeds (e.g. 61.9 km/h at 22:23:55, labelled gps). API rebuilt + healthy.
  • Follow-up: investigate why the OBD adapter dropped for ~20 min (reconnect on stalled reads).

BUG-20 — Server trip IDs inflate far beyond the real trip count

  • Status: CLOSED 2026-08-14
  • Commit: 9af71e2
  • Fix: trips.id BIGSERIAL burned a sequence value on every upsert in compute_trips_for_device() (which runs after every upload batch), so IDs climbed far past the real trip count. Now the sequence is clamped to MAX(id) after each recompute (server/modules/db.py), and a one-time migration (server/sql/migrate_phase29_trip_ids.sql) renumbered existing trips compactly and reset the sequence.
  • Verification: before — COUNT=10, MAX(id)=27091; after — MIN(id)=1, MAX(id)=10, sequence last_value=10 (next insert gets 11). API container rebuilt and healthy.

BUG-18 — Pi needs offline timekeeping (no RTC)

  • Status: CLOSED 2026-08-14
  • Commit: bf4f3d3
  • Fix: DS3231 RTC module installed on the free I²C bus (SDA pin 3, SCL pin 5, 3.3V pin 1, GND pin 6) with a CR2032 (charge diode removed). Pi config: dtparam=i2c_arm=on + dtoverlay=i2c-rtc,ds3231 in /boot/firmware/config.txt, i2c-tools installed, fake-hwclock disabled, i2c-dev persisted via modules-load.d. CR1220 also installed in the SIM868 HAT holder (secondary RTC backup).
  • Verification: DS3231 probes at 0x68 (UU), its 24C32 EEPROM at 0x57, /dev/rtc0 registered. Power-cycle test passed — after a full unplug/replug the boot log reads setting system clock to 2026-08-14… from the RTC (was 2000-01-01 before), and hwclock -r matches system time; the SET TIME! recovery line no longer appears (stable oscillator on CR2032). (Debugging note: the first scans were an empty bus due to a data-line wiring issue, resolved during re-soldering.) SIM868 HAT RTC was also set to the correct time via AT+CCLK (was factory-default 2004) — its CR1220 hold will be confirmed on the next power cycle.

BUG-17 — Server trip timestamps wrong after an offline period

  • Status: CLOSED 2026-08-14
  • Commit: bf4f3d3
  • Fix: root cause was BUG-18 — no RTC, so offline the Pi ran on a stale fake-hwclock time and NTP snapped the clock forward mid-trip. Fixed by installing the DS3231 (BUG-18).
  • Verification: RTC power-cycle test passed (BUG-18). Historical trips 25136/25137 keep their bad timestamps (raw tracking rows were recorded with a wrong clock and can't be retroactively corrected) — future trips will be correct.

BUG-15 — Phone can't host the hotspot and connect to the Pi's AP at once

  • Status: CLOSED 2026-08-13
  • Commit: ab79820
  • Resolution: Confirmed a phone-OS limitation, not a Pi bug. A single phone can't cleanly be both the Pi's internet uplink (hotspot/AP host) and its WiFi client (on the Pi's AP) at the same time — doing so routes the hotspot's traffic back through the no-internet AP, creating a routing loop (NameResolutionError on uploads).
  • Workaround (documented): the phone must be LTE-only (WiFi off) to serve as the Pi's uplink. Reach the Pi UI from that phone over the hotspot at http://<pi-hotspot-ip> (Settings → "In-car hotspot"), or from a second device on the AP.
  • Pi-side hardening shipped: phone-hotspot profile forces public DNS (8.8.8.8/1.1.1.1), and the Settings page surfaces the correct URL per uplink mode.

BUG-16 — Trip missing from Pi local history (present on server)

  • Status: CLOSED 2026-08-13
  • Commits: e5ac14e, f5f20c3
  • Fix: two root causes:
    1. connect_obd() set _car_ever_connected without a global declaration, so the module-level flag was never set and was_car_ever_connected() always returned False — local trip building had been silently blocked ever since BUG-10 landed. Added the global declaration and now persist the flag to the settings table (car_ever_connected) so it survives reboots.
    2. Speed-only rows (NULL GPS, from FEAT-12) made trips start/end with NULL coordinates, violating the trips.*GPSX NOT NULL constraint. The trip builder now uses the first/last GPS-bearing row for start/end coordinates, and skips a trip that never got any fix.
  • Verification: backfilled the persisted flag on the Pi (the car has been connected before), triggered a rebuild — the local trips table now contains the 2026-08-13 drive (e.g. a 48.5 km trip) plus several earlier trips that had been silently dropped. trip_build_state advanced to LAST_TRACKING_ID=7009. Timestamps for the 08-13 data are still wrong — that's BUG-17 (no RTC).

BUG-13 — Server Web UI shows raw coordinates instead of geocoded location on trips

  • Status: CLOSED 2026-08-12
  • Commit: 8309819
  • Fix: Server _geocode_cached() now always returns a non-empty string with coordinate fallback when Nominatim/reverse_geocoder fail. /api/geocode always returns HTTP 200 with {label} (never 204). Batch endpoint includes all keys. Nominatim params + reverse_geocoder mode aligned with Pi. Pi also hardened against empty reverse_geocoder label.
  • Verification: Deployed to Unraid (Docker rebuild) and Pi (git pull + restart). Both healthy. Unraid now uses SSH deploy key for git fetch (was failing on HTTPS auth).

BUG-14 — Geocode slow/unreliable — location labels fail to load during scrubbing

  • Status: CLOSED 2026-08-12
  • Commit: 0ddfe39
  • Fix: Ditched Nominatim entirely — it was slow (1 req/sec rate limit, ~4s timeouts) and often blocked/throttled from Docker/Cloudflare IPs. Replaced with reverse_geocoder exclusively: an offline Python library that maps lat/lon → city/province instantly with no network. JS preload() switched from N individual GET requests to single POST /api/geocode/batch. Server batch endpoint simplified to sequential loop with lru_cache + dedup.
  • Verification: POST /api/geocode/batch returns {"Montreal, Quebec", "Longueuil, Quebec"} instantly on Pi. Server Docker rebuilt and healthy.

BUG-01 — WiFi/hotspot unreachable from phone while cell data is on

  • Status: CLOSED 2026-08-11
  • Fix: Dual-radio — wlan0="yaris 911" at 10.42.0.1 (password "yaris911!"), wlan1=uplink. Never touches wlan0. Phone-hotspot auto-connect on wlan1 within ~60s, falls back to home-wifi. Settings page shows in-car access card.
  • Verification: iOS + Android connect to AP, yaris.local resolves. Phone-hotspot uplink tested: auto-connects when hotspot enabled, falls back when disabled. wlan0 AP stays up throughout.

BUG-02 — Micro-USB power port on the Pi is physically damaged

  • Status: CLOSED 2026-08-11
  • Fix: Hard-wired 5V/GND directly to GPIO header — red to Pin 2 (5V), black to Pin 6 (GND), bypassing the worn micro-USB port.
  • Verification: vcgencmd get_throttled returns 0x0 — no undervoltage, no throttling. Pi runs at full 1.2 GHz. GPS has fix.

BUG-03 — DTC/MIL codes never persisted

  • Status: CLOSED 2026-08-11
  • Commit: e2f2314
  • Fix: save_dtc_state() persists MIL+codes each poll. /api/dtc falls back to get_persisted_dtc_state() when OBD offline. Cleared codes tracked via IS_SET timestamps.
  • Verification: Deployed to Pi, /api/dtc returns persisted snapshot, stats show active_dtc: 0.

BUG-04 — Server merges two trips into one

  • Status: CLOSED 2026-08-11
  • Commit: 96fb897
  • Fix: Replaced time-gap splitting with Pi's motion-aware logic: OBD > 1 km/h primary, GPS >= 8m × 3 consecutive fallback, 5-min inactivity gap.
  • Verification: Server trips cleared + recomputed. 17 trips on both Pi and server.

BUG-05 — Server route replay speed_source always "gps"

  • Status: CLOSED 2026-08-11
  • Commit: e2f2314
  • Fix: "obd" if speed > 0 else "gps" matching Pi logic.
  • Verification: Docker rebuild, /health OK LAN + Cloudflare.

BUG-11 — Dashboard GPS shows "Stale fix" while Status shows "Live fix"

  • Status: CLOSED 2026-08-11
  • Commit: 9733036
  • Fix: renderGpsStatus() now reads status.latitude/status.longitude from the /api/gps/status response (not just socket events). Status page now uses the same 30s staleness threshold (fix_age_seconds > 30 → "Stale fix") instead of calling any fix "Live" regardless of age.
  • Verification: Deployed to Pi, dashboard GPS card now shows lat/lon coordinates even when fix is stale. Both pages agree on fix status.

BUG-06 — Server timestamps are shifted (naive local time stored as UTC)

  • Status: CLOSED 2026-08-11
  • Commit: 7ce2a1e (upload fix), manual migration on server
  • Fix:
    1. _to_tz_aware() in app_upload.py converts naive SQLite timestamps to TZ-aware ISO before upload (2026-08-10 19:27:30 → 2026-08-10T19:27:30-04:00).
    2. One-time SQL migration on Unraid: shifted 3,593 tracking rows +4h EDT, cleared deleted-trip markers, recomputed 43 trips from corrected data.
  • Verification: Server trips now show Aug 10 at 7:27 PM / 7:58 PM (was 3:27 / 3:58).

BUG-12 — Dashboard OBD shows "—" while Status page shows correct OBD state

  • Status: CLOSED 2026-08-11
  • Commit: 91281b1
  • Fix: Added /api/obd/status endpoint. Dashboard calls refreshObdStatus() on load + every 15s. Socket events still update in real-time. Side fix: Number() wrap on API string lat/lon prevents crash. Socket gps_location now passes lat/lon to renderGpsStatus (a4a92cc).
  • Verification: Dashboard shows "Adapter only" matching Status page. GPS lat/lon display correctly. Confirmed on live Pi.

BUG-02 — Micro-USB power port on the Pi is physically damaged

  • Status: CLOSED 2026-08-11
  • Fix: Hard-wired 5V/GND directly to GPIO header — red to Pin 2 (5V), black to Pin 6 (GND), bypassing the worn micro-USB port.
  • Verification: vcgencmd get_throttled returns 0x0 — no undervoltage, no throttling. GPS has fix. Pi runs at full 1.2 GHz.

BUG-07 — Trip replay on portal sometimes does nothing

  • Status: CLOSED 2026-08-11
  • Commit: fa93384
  • Fix: Full rewrite of static/js/history.js: unified AbortController cancels fetch
    • all downstream rendering on trip switch; 300ms debounce prevents double-tap stacking; loading spinner on map + .table-active row highlight give clear feedback; geocode preload starts immediately before map rendering so cache is warm for the scrubber; signal.aborted guards after every async step (route build, fitBounds, timeline init).
  • Verification: Deployed to Pi and server. Rapid trip-switching no longer freezes. Verified on both platforms 2026-08-11.

BUG-08 — No trip deletion on local Pi

  • Status: CLOSED 2026-08-11
  • Commit: c5c478b
  • Fix: deletable macro, window.confirmDelete, DELETE /api/trip/<id>, configurable data-delete-url in shared history.js. Raw tracking preserved.
  • Verification: Trip 1967 deleted (18→17 trips), 2028 tracking rows preserved.

BUG-09 — Server trip scrubber geocoding is slow

  • Status: CLOSED 2026-08-11
  • Fix: preloadGeocodes() batch-fetches all unique coords (concurrency 4) on trip load. geocodePoint() checks in-memory cache first.
  • Verification: preloadGeocodes present in history.js on both Pi and server Docker container.

BUG-10 — GPS-only false trips when car not connected

  • Status: CLOSED 2026-08-11
  • Fix: _car_ever_connected flag in app_obd.py. build_trip_summaries() returns empty list when car was never connected.
  • Verification: Pi bench-test shows 0 trips. No OBD = no GPS-only trips.