18 KiB
18 KiB
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:
OPEN2026-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/statusonly 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/statusto 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:
CLOSED2026-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 bydatetime(the server orders byrecorded_at ASC), so clock-rollback rows can't make a trip span a backwards time jump.TRIP_BUILD_VERSIONbumped 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-sidedeleted_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-24 — OBD adapter stalls mid-drive; speed flatlines until the next ignition cycle
- Status:
CLOSED2026-08-15 - Commit:
b0ad6fd - Symptom: on trip #8 (2026-08-13, 09:59–14:50), OBD speed went 102 → None at
14:14:31 and never recovered for the rest of the trip (~36 min). The log showed only
No speed data received. #['14:16:35', 102.0]— the ELM327 returned null speed responses while still reportingCAR_CONNECTED, so the 10s reconnect loop never fired. Same stall class as BUG-21 (which happened to recover on its own after ~20 min). - Fix:
obd_speed()now counts consecutive null-speed polls; after 10 nulls (~20s) it force-closes the connection via_mark_connection_lost(), so_reconnect_loopre-runsconnect_obd()and the adapter is re-handshaken instead of silently flatlining until the car is restarted. - Verification: deployed to the Pi; the forced-reconnect path will be exercised on the next real stall (in-car verification pending).
BUG-25 — Security hardening for the internet-exposed remote portal
- Status:
CLOSED2026-08-15 - Commit:
24250e0 - Findings (security review of
https://yaris.ceaf.dev):- Path traversal → arbitrary file write in
POST /api/v1/dashcam/upload/chunk— thesha256form field was concatenated into the chunk staging path with no validation, so a digest like../../../../tmp/xescapedDASHCAM_STORAGE_DIRand let a device-authenticated caller write files anywhere inside the container (as root — noUSERin the Dockerfile). - No login rate limiting —
/loginwas brute-forceable. - Session cookies lacked Secure/SameSite flags.
- Path traversal → arbitrary file write in
- Fix:
sha256is now validated as a 64-char hex digest (_is_valid_sha256) on the single-shot upload, chunk-status, and chunk-upload endpoints before it is used in any filesystem path.- In-memory failed-attempt limiter on
/login— 8 failures / 15 min per client IP (keyed fromCF-Connecting-IP, falling back toX-Forwarded-Forthenremote_addr) plus per-username; returns 429 when tripped. The app runs as a single gunicorn worker, so process-local state is sufficient (documented in a code comment for a future multi-worker deployment). SESSION_COOKIE_HTTPONLY+SESSION_COOKIE_SAMESITE="Lax"+SESSION_COOKIE_SECUREenabled (Secure can be disabled withCOOKIE_SECURE=0for plain-HTTP LAN login; env var documented inserver/.env.example).
- Verification:
python3 -m py_compile server/app.pyclean; deployed to unraid,/healthOK. - Remaining exposure (not code): the Pi's own web app (192.168.50.220:5000) is unauthenticated and binds all interfaces. It is not tunnel-exposed, but a compromised server container could reach it if the 192.168.10.x (Unraid) and 192.168.50.x (home) subnets route to each other — isolate those VLANs.
BUG-22 — Trip max speed ignores GPS-only stretch (shows OBD max only)
- Status:
CLOSED2026-08-14 - Commit:
90cfd7b - Fix:
max_speed_kmhwas 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 bumpedTRIP_BUILD_VERSIONto 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:
CLOSED2026-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'sroute_pointsGPS-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: see BUG-24 — the adapter stalls and returns null speed without dropping the "connected" status; fixed with a reconnect-on-stale-speed guard.
BUG-20 — Server trip IDs inflate far beyond the real trip count
- Status:
CLOSED2026-08-14 - Commit:
9af71e2 - Fix:
trips.id BIGSERIALburned a sequence value on every upsert incompute_trips_for_device()(which runs after every upload batch), so IDs climbed far past the real trip count. Now the sequence is clamped toMAX(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, sequencelast_value=10(next insert gets 11). API container rebuilt and healthy.
BUG-18 — Pi needs offline timekeeping (no RTC)
- Status:
CLOSED2026-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,ds3231in/boot/firmware/config.txt,i2c-toolsinstalled,fake-hwclockdisabled,i2c-devpersisted viamodules-load.d. CR1220 also installed in the SIM868 HAT holder (secondary RTC backup). - Verification: DS3231 probes at
0x68(UU), its 24C32 EEPROM at0x57,/dev/rtc0registered. Power-cycle test passed — after a full unplug/replug the boot log readssetting system clock to 2026-08-14…from the RTC (was2000-01-01before), andhwclock -rmatches system time; theSET 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 viaAT+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:
CLOSED2026-08-14 - Commit:
bf4f3d3 - Fix: root cause was BUG-18 — no RTC, so offline the Pi ran on a stale
fake-hwclocktime 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:
CLOSED2026-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 (
NameResolutionErroron 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-hotspotprofile 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:
CLOSED2026-08-13 - Commits:
e5ac14e,f5f20c3 - Fix: two root causes:
connect_obd()set_car_ever_connectedwithout aglobaldeclaration, so the module-level flag was never set andwas_car_ever_connected()always returnedFalse— local trip building had been silently blocked ever since BUG-10 landed. Added theglobaldeclaration and now persist the flag to the settings table (car_ever_connected) so it survives reboots.- Speed-only rows (NULL GPS, from FEAT-12) made trips start/end with NULL coordinates,
violating the
trips.*GPSX NOT NULLconstraint. 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
tripstable 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_stateadvanced 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:
CLOSED2026-08-12 - Commit:
8309819 - Fix: Server
_geocode_cached()now always returns a non-empty string with coordinate fallback when Nominatim/reverse_geocoder fail./api/geocodealways 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:
CLOSED2026-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 singlePOST /api/geocode/batch. Server batch endpoint simplified to sequential loop with lru_cache + dedup. - Verification:
POST /api/geocode/batchreturns{"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:
CLOSED2026-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.localresolves. 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:
CLOSED2026-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_throttledreturns0x0— no undervoltage, no throttling. Pi runs at full 1.2 GHz. GPS has fix.
BUG-03 — DTC/MIL codes never persisted
- Status:
CLOSED2026-08-11 - Commit:
e2f2314 - Fix:
save_dtc_state()persists MIL+codes each poll./api/dtcfalls back toget_persisted_dtc_state()when OBD offline. Cleared codes tracked via IS_SET timestamps. - Verification: Deployed to Pi,
/api/dtcreturns persisted snapshot, stats showactive_dtc: 0.
BUG-04 — Server merges two trips into one
- Status:
CLOSED2026-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:
CLOSED2026-08-11 - Commit:
e2f2314 - Fix:
"obd" if speed > 0 else "gps"matching Pi logic. - Verification: Docker rebuild,
/healthOK LAN + Cloudflare.
BUG-11 — Dashboard GPS shows "Stale fix" while Status shows "Live fix"
- Status:
CLOSED2026-08-11 - Commit:
9733036 - Fix:
renderGpsStatus()now readsstatus.latitude/status.longitudefrom the/api/gps/statusresponse (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:
CLOSED2026-08-11 - Commit:
7ce2a1e(upload fix), manual migration on server - Fix:
_to_tz_aware()inapp_upload.pyconverts naive SQLite timestamps to TZ-aware ISO before upload (2026-08-10 19:27:30→2026-08-10T19:27:30-04:00).- 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:
CLOSED2026-08-11 - Commit:
91281b1 - Fix: Added
/api/obd/statusendpoint. Dashboard callsrefreshObdStatus()on load + every 15s. Socket events still update in real-time. Side fix:Number()wrap on API string lat/lon prevents crash. Socketgps_locationnow passes lat/lon torenderGpsStatus(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:
CLOSED2026-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_throttledreturns0x0— no undervoltage, no throttling. GPS has fix. Pi runs at full 1.2 GHz.
BUG-07 — Trip replay on portal sometimes does nothing
- Status:
CLOSED2026-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-activerow highlight give clear feedback; geocode preload starts immediately before map rendering so cache is warm for the scrubber;signal.abortedguards after every async step (route build, fitBounds, timeline init).
- all downstream rendering on trip switch; 300ms debounce prevents double-tap stacking;
loading spinner on map +
- 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:
CLOSED2026-08-11 - Commit:
c5c478b - Fix:
deletablemacro,window.confirmDelete,DELETE /api/trip/<id>, configurabledata-delete-urlin sharedhistory.js. Raw tracking preserved. - Verification: Trip 1967 deleted (18→17 trips), 2028 tracking rows preserved.
BUG-09 — Server trip scrubber geocoding is slow
- Status:
CLOSED2026-08-11 - Fix:
preloadGeocodes()batch-fetches all unique coords (concurrency 4) on trip load.geocodePoint()checks in-memory cache first. - Verification:
preloadGeocodespresent in history.js on both Pi and server Docker container.
BUG-10 — GPS-only false trips when car not connected
- Status:
CLOSED2026-08-11 - Fix:
_car_ever_connectedflag inapp_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.