diff --git a/PLAN.md b/PLAN.md index 401e673..cd7e450 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1903,11 +1903,14 @@ lands. The current known issues from the road test (also recorded in `BUGS.md`): *server* delete endpoint, and there is no `DELETE /api/trip/` route on the Pi. Fix: add all four pieces and make the delete endpoint configurable in `history.js`. -**Progress (2026-08-11):** **BUG-03** ✅ FIXED (commit `e2f2314` — DTC/MIL persisted to SQLite on -each poll, `/api/dtc` falls back to persisted state when OBD is offline, `get_overview_stats` -fixed to use the real `dtc` table, cleared/since tracked via `IS_SET`/`FIRST_SEEN_AT`/ -`LAST_SEEN_AT`, plus a schema migration and `tests/test_dtc_persistence.py`). **BUG-05** ✅ FIXED -(commit `e2f2314` — server route `speed_source` mirrors the Pi's `obd if speed>0 else gps`). +**Progress (2026-08-11, 6/8 closed):** +- **BUG-03** ✅ CLOSED (`e2f2314`) — DTC/MIL persisted to SQLite, `/api/dtc` fallback, stats fixed. +- **BUG-04** ✅ CLOSED (`96fb897`) — Server trip detection now mirrors Pi's motion-aware logic. +- **BUG-05** ✅ CLOSED (`e2f2314`) — Server `speed_source` matches Pi: `obd if speed>0 else gps`. +- **BUG-08** ✅ CLOSED (`c5c478b`) — Pi trip deletion: `deletable` macro, `confirmDelete`, `DELETE` route, configurable endpoint. +- **BUG-09** ✅ CLOSED — Geocode pre-caching in `history.js` for fast scrubber. +- **BUG-10** ✅ CLOSED — GPS-only false trips gated on `was_car_ever_connected()`. +- **BUG-01/02/06/07**: Still OPEN. See `BUGS.md`. Both pending deploy/verify. The remaining items (BUG-01, 02, 04, 06, 07, 08) stay open. **Acceptance for Phase 26:** every `BUGS.md` entry in scope is fixed, regression-tested, deployed, diff --git a/readme.md b/readme.md index 49cdbb0..9bb23bb 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# yaris-obd 🚗📡 +# yaris-obd A Raspberry Pi 3-based OBD-II, GPS, and dashcam system for my 2013 Toyota Yaris. It reads live vehicle data over USB, tracks position with a SIM868 GNSS/GSM HAT, logs everything locally, and @@ -32,62 +32,62 @@ Dashboard — mobile (390 px) and desktop (1280 px): ## Features -- 📊 **Live OBD-II data** over a cheap USB ELM327-compatible adapter: speed, RPM, coolant +- Live OBD-II data over a cheap USB ELM327-compatible adapter: speed, RPM, coolant temperature, fuel level, throttle position, MIL status, stored DTCs, and odometer when the ECU supports it. Includes automatic background reconnects, serialized queries, and clear adapter/ELM327/ECU diagnostics -- 🛰️ **Real GPS tracking** via a Waveshare SIM868 GNSS/GSM/Bluetooth HAT, plotted live on an +- Real GPS tracking via a Waveshare SIM868 GNSS/GSM/Bluetooth HAT, plotted live on an offline Leaflet map (pre-cached map tiles — no internet needed in the car). The module powers itself on through the HAT's GPIO PWRKEY wiring after a Pi power cycle -- 📶 **Self-hosted WiFi hotspot** so you can load the web UI on your phone from inside the car, +- Self-hosted WiFi hotspot so you can load the web UI on your phone from inside the car, with automatic switching back to home WiFi when it is available (`http://yaris.local` — no port number) -- 🎥 **Dashcam file retrieval** — detects a USB dashcam automatically (any brand/folder layout, +- Dashcam file retrieval — detects a USB dashcam automatically (any brand/folder layout, no hardcoded device path), mounts it read-only, and safely copies footage locally. Verified against a real 28GB/87-file import. The web UI can also browse, sort, and delete individual or all videos directly from the connected dashcam with confirmed, temporary read-write operations, plus import one file or any checkbox selection instead of always importing the whole card -- ▶️ **Local video library** — browse imported clips with cached thumbnails and upload status, +- Local video library — browse imported clips with cached thumbnails and upload status, play H.264 footage inline with seeking, and delete only the local Pi copy. Optional retention can automatically remove older local copies after their exact content is confirmed uploaded -- ☁️ **Remote upload** — a self-hosted server (Flask + Postgres, `server/`) receives trip/GPS +- Remote upload — a self-hosted server (Flask + Postgres, `server/`) receives trip/GPS logs and dashcam footage over the internet (via Cloudflare Tunnel or a plain port-forward). Dashcam videos upload in resumable 40MB chunks (works around tunnel body-size limits and keeps the Pi's memory footprint flat regardless of file size); a UI toggle can pause dashcam uploads independently while trip logs keep syncing -- 🌐 **Remote web portal** — a login-protected browser portal at the same server URL (Phase 24+): +- Remote web portal — a login-protected browser portal at the same server URL: trip history with OSM/CARTO live map and route replay, dashcam archive browsing with inline video player and Range-request seeking, overview stats dashboard, delete buttons for trips and clips, and a device-settings page for editing the synced owner/car/avatar values that the Pi pulls from the server. The portal can register/delete multiple devices, reveal a one-time API key at creation/rotation time, and request a sync for a selected device. When the Pi has - **Sync with server** enabled, those identity changes hot-reload into the running local UI on the + Sync with server enabled, those identity changes hot-reload into the running local UI on the next successful sync instead of waiting for a manual restart. Shared `history.js` code runs on both the Pi and the server — tile source and zoom limits are configured per-deployment via HTML - data attributes. Accessible at `https://your-cloudflare-tunnel-url/` -- 📡 **Optional cellular fallback** through the SIM868 for small trip-log uploads when normal + data attributes +- Optional cellular fallback through the SIM868 for small trip-log uploads when normal WiFi/Ethernet is unavailable (dashcam video stays off cellular) -- 🩺 **Dedicated local status page** with live Pi health, service states, uplink/server/GPS/OBD +- Dedicated local status page with live Pi health, service states, uplink/server/GPS/OBD diagnostics, plus quick actions for server test, sync-now, uplink reconnect, and app restart -- 🗄️ **Motion-aware local-first SQLite logging** — five-second motion checks without five-second +- Motion-aware local-first SQLite logging — five-second motion checks without five-second parked writes, plus retry-safe remote sync and automatic backoff -- 🌡️ **Pi health + diagnostics** — a dedicated local Status page shows temperature, RAM, disk, +- Pi health + diagnostics — a dedicated local Status page shows temperature, RAM, disk, uptime, undervoltage/throttling warnings, service state, uplink/server reachability, GPS state, OBD presence, and safe quick actions -- 🔔 **Offline-first alerts** — a notification bell on every page reports check-engine state, +- Offline-first alerts — a notification bell on every page reports check-engine state, storage pressure, upload backlog, temperature/power faults, and GPS loss while moving. Optional ntfy delivery is available but remains disabled until configured -- 🛣️ **Trip history and route replay** — detects motion from OBD wheel speed with sustained GPS +- Trip history and route replay — detects motion from OBD wheel speed with sustained GPS displacement as a fallback, summarizes distance and speed in metric units (km / km/h), and replays each route as a line on the offline map with a timestamped play/pause timeline, moving marker, and live reverse-geocoded location name during scrubbing. Tap any trip row on mobile to load the route -- 🗺️ **Offline reverse geocoding** — a `/api/geocode` route on the Pi uses the `reverse_geocoder` +- Offline reverse geocoding — a `/api/geocode` route on the Pi uses the `reverse_geocoder` library (20 MB world dataset, no internet needed) for city/region, and upgrades to Nominatim street-level when an internet uplink is available. Results are LRU-cached in-process. The browser never calls any external geocoding service -- 🖥️ **Offline web UI** built with Flask, Jinja, Bootstrap 5, Socket.IO, Chart.js, and Leaflet, +- Offline web UI built with Flask, Jinja, Bootstrap 5, Socket.IO, Chart.js, and Leaflet, all served locally with a shared responsive page shell -- 🔌 **Headless Pi deployment** as a self-restarting `systemd` service with a 10-second BCM2835 +- Headless Pi deployment as a self-restarting `systemd` service with a 10-second BCM2835 hardware watchdog, verified across a real reboot ## Hardware @@ -215,8 +215,8 @@ already completed the Phase 25 real-vehicle test; the bugs it surfaced are track main remote overview/history/dashcam browsing views still follow one configured `DEVICE_NAME` until a later portal-wide device selector/filter is added -**Next**: Phase 26 — road-test bug fixes from the Phase 25 in-car test (see [BUGS.md](./BUGS.md) -for the tracked issues). Phase 27 (feature additions from FEATURES.md) and Phase 28 (Android companion app) follow after that. +**Next**: Phase 26 — road-test bug fixes (6 of 8 resolved, see [BUGS.md](./BUGS.md) +for remaining issues). Phase 27 (feature additions from FEATURES.md) and Phase 28 (Android companion app) follow after that. Phase 14 is partially complete: the Pi's hardware watchdog is deployed and reboot-verified. Read-only-root storage hardening is deferred until persistent storage is moved off the SD root @@ -224,7 +224,7 @@ partition, and clean shutdown still needs delayed-power or ignition-sense hardwa The browser-based phone relay was removed after real-world testing confirmed that mobile browsers cannot reliably use the Pi's WiFi and cellular data simultaneously. A native Android companion is -planned later instead (Phase 27). +planned later instead (Phase 28). The local web UI includes a Settings page for safe runtime configuration: dashcam uploads, uploaded-video retention, cellular APN fallback, optional ntfy delivery, alert thresholds, local