Files
yaris-obd/BUGS.md
T

203 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-15 — Phone can't host the hotspot and connect to the Pi's AP at once
- **Status**: `OPEN` 2026-08-12
- **Symptom**: With the phone hosting the hotspot (Pi's uplink) *and* connected to the
Pi's AP ("vroom vroom yaris de course"), the Pi loses internet. Uploads fail with
`NameResolutionError` — the phone's WiFi-sharing routes the hotspot's traffic back
through the no-internet AP, creating a routing loop.
- **Cause**: phone-OS limitation — a single phone can't cleanly be both the Pi's
internet uplink (AP/hotspot host) and its WiFi client (on the Pi's AP) simultaneously.
- **Intended use / workaround**: 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" shows it), or from a second
device on the AP.
- **Pi-side hardening shipped 2026-08-12**: `phone-hotspot` now forces public DNS
(`8.8.8.8`/`1.1.1.1`) and the Settings page surfaces the correct URL per uplink mode.
### BUG-17 — Server trip timestamps wrong after an offline period
- **Status**: `OPEN` 2026-08-13
- **Phase**: 29
- **Symptom**: two trips from the 2026-08-13 drive have bad timestamps on the server:
- Trip **25136** — time is wrong.
- Trip **25137** — starts 09:59, then jumps to 14:xx after the first point.
- **Cause (hypothesis)**: the Pi has no RTC, so while offline it runs on a stale
`fake-hwclock` time; when NTP later re-syncs, the clock snaps forward, producing the
timestamp jump mid-trip. Root cause is BUG-18.
### BUG-18 — Pi needs offline timekeeping (no RTC)
- **Status**: `OPEN` 2026-08-13
- **Phase**: 29
- **Problem**: the Pi 3 has no real-time clock. Without internet (no NTP) the system clock
is wrong across power cycles, corrupting tracking/trip timestamps (BUG-16/BUG-17).
- **Fix plan (both, they complement each other)**:
1. **DS3231 RTC module (primary)** — battery-backed RTC on the free I²C bus (SDA pin 3,
SCL pin 5, 3.3V pin 1, GND pin 6). Enable `dtparam=i2c_arm=on` +
`dtoverlay=i2c-rtc,ds3231` in `/boot/firmware/config.txt`, install `i2c-tools`, disable
`fake-hwclock`. Use a **CR2032** and first **desolder the module's charging resistor +
diode** (cheap ZS-042-style boards charge the coin cell — unsafe for a CR2032; the
well-known DS3231 charging-circuit issue). Gives correct time instantly at boot, ±2 ppm.
2. **SIM868 CR1220 RTC backup (secondary)** — the HAT has a CR1220 holder on the back
(item 20). A CR1220 keeps the SIM868's internal RTC alive across power-off, enabling
faster GNSS warm starts and letting the Pi optionally read the module time at boot
(`AT+CCLK`) as an offline fallback.
- Keep `systemd-timesyncd` for online NTP; fall back to the RTC (DS3231) and optionally
GNSS time when offline.
---
## Resolved
### 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.