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)
- yaris_uplink configure() keyfile: dns=8.8.8.8;1.1.1.1 + ignore-auto-dns=true
so the Pi doesn't rely on the phone's DHCP DNS, which failed to resolve
yaris.ceaf.dev (NameResolutionError) and broke uploads on the hotspot
- test asserts the DNS lines are written to the keyfile
adb-pushed files are invisible to the app due to scoped storage, so add a
'Create 120 MB test file' button in the Downloads tab that writes the file
through the app's own uid (visible in its contribution set).
setProgressAsync (fire-and-forget) was dropping/coalescing updates before
they were persisted. Switch to awaited suspend setProgress() in both
UploadWorker and DownloadWorker so each progress write lands and the
LiveData observer actually sees pct advance.
- Hide upload button when file is in uploadedNames (already on server)
- UploadWorker still guards via /status already_uploaded check
- Indeterminate progress bar during Hashing/Checking phases
- Upload label always shows percentage