- Clicking the amber max-speed map marker now jumps the replay to that point
- Add an amber tick on the scrubber at the max-speed position (clickable too)
- Both on Pi and server portal
When a route loads, add an amber circle + permanent 'Max speed: X km/h'
tooltip at the point with the highest speed. Shared history.js, so it
applies to both the Pi and the server portal.
obd_speed() now counts consecutive null-speed polls. If the ELM327 returns
null for 10 polls (~20s) while still reporting CAR_CONNECTED, it force-closes
the connection so the reconnect loop re-handshakes instead of silently
flatlining until the next ignition cycle.
route_points (Pi) and get_trip_route (server) derived GPS speed from a
single 5s segment, so GPS position jitter could read 150+ km/h when the car
wasn't going that fast. Both now average over a trailing ~30s window (same
as the max-speed calc), so spikes are damped.
Set html { font-size: 90% } so the whole UI (sidebar, typography, spacing)
renders at the ~90% browser-zoom look the owner prefers, consistently on
both the Pi and the remote server.
Add an explicit .375rem vertical cell padding for .data-list tables. The
CSS/templates were already byte-identical across Pi and server, so this
makes the compact row height deterministic on both and rules out any
Bootstrap-default drift or stale-cache difference.
The portal's trip list had an extra 'ID' column the Pi's list doesn't
have. Remove it (and its showId data attribute) so both tables render the
same columns: checkbox, Started, km, Time, Max, Odometer, delete.
- Pi history page gets a select checkbox column + 'Delete selected' button
(mirrors the server UI)
- POST /api/trips/delete batch endpoint
- app_sql.delete_trips_batch() + deleted_trip_markers table so a later trip
rebuild can't resurrect locally-deleted trips
- Deletion is local-only: raw tracking rows are kept and the remote server
is never notified (it keeps its archival copy recomputed from uploaded rows)
Add the server's minimum-trip filter to build_trip_summaries() — duration
< 30s OR distance < 0.05km is rejected — so GPS lock-in drift no longer
spawns false trips on the Pi. Also sort normalized rows by datetime (the
server already orders by recorded_at ASC), fixing clock-rollback trip
boundaries. Bump TRIP_BUILD_VERSION to force a Pi-side rebuild.
Root-caused the discrepancy by replicating the server's trip builder over
live data: 58 raw groups -> 51 after the server's duration/distance floor
(7 short trips dropped that the Pi keeps) -> 10 after skipping 41 deleted
trip markers. Documents the min-trip filter mismatch and the row-set
mismatch as the actual bugs.
- DB lives under db/sql/<account>_<car>.db, not the repo root (was -maxdepth 1)
- Pick the most recently modified DB (active account) instead of the first
found, which was the stale TestUser_SubaruWRX.db
- Query UPLOADED=0 instead of sent=0 (column was renamed long ago)
- Use the venv Python's sqlite3 for queries — the sqlite3 CLI isn't installed
on the Pi, so integrity/row-count checks were silently failing
Trips starting/ending on speed-only rows violated the trips.*GPSX NOT NULL
constraint. Use the first/last GPS-bearing row for start/end coordinates, and
skip a trip that never got any GPS fix (no location to record).
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 has been silently blocked since BUG-10 landed.
Also persist the flag to the settings table so a drive followed by a reboot
still builds trips, and clean up dead code in was_car_ever_connected().
- _log_loop: when GPS has no fix but OBD speed > 1, write speed-only rows
(NULL coordinates) instead of dropping the motion
- insert_tracking: accept None gps_x/gps_y -> NULL GPSX/GPSY
- app_trip: keep NULL-coord rows through normalize; _segment returns 0 for
missing coords; route_points drops them (no position to draw)
- tests: speed-only rows build a trip with max speed + zero distance
- docs: FEAT-12 + readme note; server already filters NULL-GPS safely
- Settings: when the Pi is on the phone's hotspot (mode phone), show the
Pi's hotspot IP (http://<ip>) with an LTE-only hint instead of the AP URL
- BUG-15 documents the phone dual-role routing loop (host hotspot + connect
to AP simultaneously breaks the uplink)