Files
yaris-obd/BUGS.md
T

12 KiB
Raw Blame History

yaris-obd Bug Tracker

Standalone bug/issue tracker for the yaris-obd project, kept separate from PLAN.md. Use this file to record, track status, and hand off bugs to another agent/session. PLAN.md still summarizes bug-fix progress in its phase sections (and Phase 26 is the dedicated road-test bug-fix phase), but the authoritative, issue-by-issue record lives here.

How to use this tracker

  • File format: one ## BUG-XX section per issue. Keep the numbering sequential.
  • Status field: OPEN → IN PROGRESS → FIXED (commit ref) → CLOSED (deployed + verified) or WONTFIX/DUP as appropriate.
  • Relate to phases: each entry's Phase field links a bug to the relevant PLAN.md phase so an agent can find the surrounding context and acceptance criteria.
  • When fixed: keep the original symptom/impact recorded (don't delete history), set status to FIXED, add the commit SHA in the Fix field, then move to CLOSED after deploy/verify. Also drop a one-line mention in the corresponding PLAN.md phase.
  • For future bugs: add new ## BUG-XX entries here rather than only burying them in chat history. Keep them SMALL and one-issue-per-entry so they are easy to pick up and verify.

Open bugs

BUG-01 — WiFi/hotspot unreachable from phone while cell data is on (and wrong documented gateway)

  • Status: OPEN
  • Severity: Medium (usability of the in-car hotspot from a phone)
  • Area: Networking / Pi hotspot (yaris-uplink, NetworkManager shared AP, docs)
  • Phase: Phase 26
  • Symptom: While a phone is connected to the Pi's no-internet hotspot and cell data is on, the phone cannot load yaris.local, 10.42.0.1, or the Pi's DHCP address at all. With cell data disabled, http://<dhcp-ip>/ loads, but yaris.local and 10.42.0.1 still do not. The working address seen was 10.112.<...>.
  • Root cause (confirmed): Phone-OS "smart network switching" — with a no-internet WiFi network associated and cellular available, the OS keeps cellular as the whole-device default route, so no traffic (even a plain page navigation or fetch()) reaches the Pi hotspot. Disabling cell data forces the hotspot WiFi to become the default network. This is the same OS-level ceiling documented in Phase 11/22. Separately, the actual NetworkManager shared-AP subnet is 10.112.0.x, not the documented 10.42.0.1, and yaris.local mDNS isn't resolved from the phone on the Pi AP.
  • Fix scope / actions:
    • Make the documented/reachable address correct (surface the Pi's real DHCP-assigned address in the UI / status page rather than hardcoding 10.42.0.1).
    • Extend the yaris.local unicast (shared-dnsmasq) fallback to the AP subnet so it resolves from a phone on the Pi hotspot.
    • Clearly document the cell-data limitation and the workaround (disable cell data / "smart network switching").
  • Acceptance: phone on the Pi hotspot can load the web UI via a documented, correct address (optionally yaris.local), and the cell-data caveat is documented.

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

  • Status: OPEN
  • Severity: Hardware (reliability/power)
  • Area: Hardware / power
  • Phase: Phase 26
  • Symptom: The Pi's micro-USB 5V power connector is worn/damaged and no longer makes a reliable connection. Power is likely to drop under vibration in the car.
  • Root cause: Physical wear on the connector.
  • Fix scope / actions: No code. Owner hard-wires 5V and GND directly to the Pi's GPIO header (pins 2/4 for 5V, 6/9/14/20/25/30/34/39 for GND) with a suitable PSU, bypassing the micro-USB port. Confirm vcgencmd get_throttled shows no current undervoltage after rewiring (the Phase 19/20 alerts monitor this).
  • Acceptance: Stable power with no undervoltage/throttling under load.

BUG-03 — DTC/MIL codes are never persisted; lost on OBD disconnect or reboot

  • Status: CLOSED (commit e2f2314; deployed + verified 2026-08-11)
  • Fix: Persist MIL + codes to SQLite on each poll (save_dtc_state), /api/dtc falls back to the persisted snapshot when OBD is offline, get_overview_stats counts the real dtc table, and a schema migration rebuilds the unused NAME/STATUS/DTC_ID table. Cleared codes are tracked via IS_SET + FIRST_SEEN_AT/LAST_SEEN_AT. Tests: tests/test_dtc_persistence.py.
  • Severity: Medium (lost diagnostic data; also a stats bug)
  • Area: modules/app_obd.py, modules/app_sql.py, get_overview_stats
  • Phase: Phase 26
  • Symptom: Stored DTC trouble codes and MIL state live only in the in-memory dtc_codes global in app_obd.py. They vanish as soon as OBD disconnects or the Pi reboots. Separately, get_overview_stats queries a table named dtc_codes that does not exist (the created table is dtc), so the post-road-test state may be wrong/broken.
  • Root cause: The SQLite dtc table is created in schema but is never written to or read from by any code path. No DTC persistence exists at all.
  • Fix scope / actions:
    • Persist MIL + DTC codes to the dtc SQLite table on each successful poll.
    • Read back from SQLite when OBD is disconnected so last-known codes stay visible.
    • Fix get_overview_stats to query the real dtc table (and use current MIL/DTC state).
    • Add a "cleared/since" concept so a code that was cleared is distinguishable from one still set.
  • Acceptance: Codes set during a drive survive a power cycle / OBD disconnect and appear on the DTC page and overview stats.

BUG-04 — Server merges two separate trips into one (motion boundary mismatch)

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

BUG-05 — Server route replay reports speed_source: "gps" even when OBD speed is present

  • Status: CLOSED (commit e2f2314; deployed + verified 2026-08-11)
  • Fix: get_trip_route now mirrors the Pi's logic: "obd" when speed > 0, otherwise "gps". Server docker container rebuilt and health-checked.

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

  • Status: OPEN
  • Severity: High-ish (all server trip times / boundaries off by the EDT offset)
  • Area: Pi upload (modules/app_upload.py / SQL), server/sql, server/modules/db.py, portal display
  • Phase: Phase 26
  • Symptom: Server shows trip times (and effectively trip boundaries/comparisons against the Pi) shifted by the Montreal-timezone-to-UTC offset (~4-5 hours depending on DST).
  • Root cause: tracking_points.recorded_at is TIMESTAMPTZ, but the Pi sends naive local (Montreal) time (datetime.now()) with no offset. Postgres (UTC container timezone) interprets that naive string as UTC.
  • Fix scope / actions (delicate — touches sending, storage, and display):
    • Pi should send timezone-aware timestamps in local Eastern time (or explicit UTC).
    • Server should store/read as America/Toronto (or consistent UTC) and display in Eastern.
    • Optional one-time migration to correct already-stored rows (depends on offset at insert time — needs a decision: re-map by DST window or accept a best-effort correction). Rebuilding the server trips table may be needed. Get owner sign-off on migrating existing data.
  • Acceptance: New data displays at the correct local time on the portal; existing shifted rows are corrected (or explicitly accepted as-is if the owner opts out of migration).

BUG-07 — Trip replay on the portal sometimes does nothing

  • Status: OPEN (needs reproduction/diagnostics)
  • Severity: Low/Medium (intermittent UI)
  • Area: static/js/history.js (shared Pi+server), server /api/v1/portal/trip/<id>
  • Phase: Phase 26
  • Symptom: Clicking a trip to replay on the /history page intermittently does nothing — no route renders, no error shown.
  • Root cause: Not yet isolated. Plausible contributors: an API/DB race (recompute_trips running concurrently with a route read), DB lock, or clicking before the map is ready. Note history.js uses shared parsing that expects space-separated Pi timestamps and "T"-separated server ones — verify both.
  • Fix scope / actions: Add targeted diagnostics (log/reproduce) before fixing. Check map readiness, error handling on the trip-fetch, and the shared timestamp parsing. Add an explicit "failed to load route" state instead of silent inaction.
  • Acceptance: Replay is reliable; any failure surfaces a visible error rather than doing nothing.

BUG-08 — No trip deletion on the local Pi (only on the remote portal)

  • Status: CLOSED (commit c5c478b; deployed + verified 2026-08-11)
  • Fix: Added deletable param to data_table macro, window.confirmDelete helper in base.html, DELETE /api/trip/<id> route + app_sql.delete_trip(), and configurable data-delete-url in history.js (shared Pi+server). Trip 1967 deleted, 18→17 trips, 2028 tracking rows preserved.

BUG-09 — Server trip scrubber geocoding is slow on each step

  • Status: OPEN
  • Severity: Medium (UX)
  • Area: static/js/history.js showReplayPoint() / scheduleGeocode()
  • Phase: Phase 26
  • Symptom: Scrubbing through the trip timeline on the server portal is sluggish — the location name takes a long time to appear because each scrub step fires a fresh /api/geocode HTTP request (debounced 600ms). On the Pi this is fast (offline reverse_geocoder), but the server calls Nominatim which adds latency.
  • Root cause: Every showReplayPoint() call triggers scheduleGeocode() → debounced fetch(/api/geocode...). No pre-caching or batch loading.
  • Fix scope / actions: Pre-fetch geocode results for ALL trip points when the route is first loaded. Store in a local JS map keyed by rounded coordinate. Show cached label instantly during scrubbing. Only fall back to live fetch for uncached points. Optionally batch-geocode at the server API level too (accept multiple lat/lon pairs).
  • Acceptance: Scrubbing through trip replay shows location names near-instantly.

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

  • Status: OPEN
  • Severity: Medium (data quality)
  • Area: modules/app_trip.py build_trip_summaries(), modules/app_sql.py refresh_trips()
  • Phase: Phase 26
  • Symptom: The Pi generates trips from GPS data alone (GPS jitter/drift) even when the car isn't connected. Since the Pi bench-tests with no OBD, GPS displacement fallback creates phantom "trips" from stationary GPS noise.
  • Root cause: The GPS motion fallback (3+ consecutive 8m displacements) can be satisfied by GPS jitter over time, especially indoors or in weak-signal areas. The system doesn't gate trip detection on whether OBD was ever present.
  • Fix scope / actions:
    • Option A (strict): Only start trips when OBD wheel speed has been detected at least once since the app started (a car_was_connected flag). No OBD ever = no trips, even with GPS.
    • Option B (lenient): Increase GPS motion requirements when OBD has never been seen (e.g. require 10+ consecutive displacements of 20m+ instead of 3×8m).
    • Recommend Option A — it matches the real-world use case: the Pi is powered by the car's ignition, so OBD should always be reachable when the car is running. No OBD = bench test, don't generate trips.
  • Acceptance: Bench-testing the Pi (no car connected) produces zero trips. Real driving with OBD connected still produces correct trips.

Resolved bugs

BUG-03 — DTC/MIL codes are never persisted; lost on OBD disconnect or reboot

  • Status: CLOSED 2026-08-11
  • Commit: e2f2314
  • Verification: Deployed to Pi, service restarted clean, /api/dtc returns persisted snapshot when OBD offline, /api/stats shows active_dtc: 0, save_dtc_state/get_persisted_dtc_state confirmed present in running code.

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

  • Status: CLOSED 2026-08-11
  • Commit: e2f2314
  • Verification: Server git reset to origin, Docker rebuild, /health OK on LAN and Cloudflare Tunnel. get_trip_route now uses "obd" if speed > 0 else "gps" matching Pi logic.