diff --git a/PLAN.md b/PLAN.md index bd512aa..f1770c1 100644 --- a/PLAN.md +++ b/PLAN.md @@ -717,7 +717,7 @@ all in `modules/app_obd.py` / `modules/app_events.py`: both available from `python-obd`'s connection object) written once per successful connect - useful evidence to sanity-check against Toyota's expected protocol on the very first real test. - **Expand the data pulled from the car beyond speed/RPM** (backend only - the dashboard cards - displaying this land in Phase 22 once the redesign reaches them): coolant temperature, fuel + displaying this land in Phase 23 once the redesign reaches them): coolant temperature, fuel level, throttle position, and DTC/MIL status (check-engine light on/off + stored trouble codes, reusing/wiring up the already-scaffolded but currently-empty `/dtc` page and `GET_DTC` command). **Odometer/mileage is not guaranteed** - the standard OBD-II mode 1 PID for total odometer @@ -784,13 +784,13 @@ classic cause of SD card corruption on embedded Pi projects. Two complementary a **New phase, pulled forward from the old "do the whole redesign at the end" plan.** Building the Phase 16/17 file browsers (and later the trip-history/Pi-health/settings pages) against the current old admin-template style just means rebuilding the same UI twice once the full redesign -(Phase 22) happens. Instead, do a *small, scoped* slice of the redesign right now: a shared page +(Phase 23) happens. Instead, do a *small, scoped* slice of the redesign right now: a shared page layout/shell plus one reusable list/table component (sortable columns, per-row action buttons, delete-with-confirmation pattern, empty-state messaging) that every subsequent list-based feature in this plan (dashcam browser, video browser, trip history, settings) can be built on directly, instead of writing bespoke list/delete UI code from scratch each time. Not a full redesign of every existing page yet - just establishes the pattern once so nothing built after this point -needs to be redone in Phase 22. +needs to be redone in Phase 23. **Implemented 2026-08-09**: - Added a shared Jinja shell (`templates/base.html`) for navigation, top bar, footer, common @@ -801,7 +801,7 @@ needs to be redone in Phase 22. `static/js/data-list.js` behavior for dynamic empty states, numeric/text sorting, accessible sort direction, and capture-phase confirmation that can stop destructive row handlers before they execute. `static/yaris.css` supplies the shared list/action styling. -- Used the empty `/dtc` page as the first component consumer without pulling its Phase 22 OBD +- Used the empty `/dtc` page as the first component consumer without pulling its Phase 23 OBD wiring forward. Also stopped loading dashboard-only `yaris.js` there and guarded its optional `#obd-error` target after browser testing exposed an existing null dereference. - Verified Jinja rendering and one active nav item on all three routes, JavaScript syntax, and @@ -1078,7 +1078,7 @@ When cellular is configured, ntfy delivery now uses the SIM868's small-body HTTP primary transport with the notification title, priority, tags, and optional bearer token. WiFi/Ethernet is the fallback if the modem path fails. The generalized modem POST path rejects quotes/newlines in AT-command parameters before touching hardware. This is mock/Pi-code tested but -remains explicitly unverified over a real carrier until a SIM is available; Phase 24 must prove +remains explicitly unverified over a real carrier until a SIM is available; Phase 25 must prove authenticated HTTPS, fallback, retry, and recovery behavior or remove ntfy entirely if the SIM868 cannot deliver it reliably. @@ -1092,8 +1092,40 @@ defaults and shared alert/navigation shell. Browser testing at 390x844 found and top-bar overlap by adding a dedicated bottom mobile save action; the real save then completed with no horizontal overflow or console errors. -### Phase 22: Finish web UI redesign — 🚧 PLANNED -**Roadmap decision 2026-08-09: keep this as Phase 22 rather than moving it forward.** Phase 15 +### Phase 22: Phone-hotspot internet uplink — 🚧 PLANNED +Add a no-SIM internet path where the Pi joins a user's phone hotspot as a WiFi client and uses the +phone's cellular data for outbound synchronization. This must work with an ordinary iPhone or +Android hotspot and support tracking rows, alert events/state, software/server checks, and large +dashcam-video uploads without requiring a modem SIM. + +The Pi currently creates its own hotspot for the local Web UI, so this phase must explicitly solve +the single-radio networking tradeoff rather than assuming it can be an access point and hotspot +client simultaneously: +- Add a Settings workflow to save/replace/remove a phone-hotspot SSID and password without exposing + the saved password back to browser JavaScript. Validate before applying and provide a recovery + path so a bad credential cannot permanently lock the user out of `yaris.local`. +- Prefer a deterministic NetworkManager design: when the configured phone hotspot is available, + connect as a client for internet access; when it is unavailable or association fails, restore the + Pi-hosted hotspot automatically within a bounded timeout. Preserve the existing boot/network + watchdog behavior and document the exact priority/retry rules. +- Because a Pi 3 single WiFi interface cannot reliably host and join separate networks at once, + test and document how the user reaches the local Web UI while connected to the phone hotspot. + Prefer `http://yaris.local/` on the shared phone LAN when the phone permits peer traffic. If + iOS/Android client isolation or mDNS behavior prevents that, keep the automatic Pi-hotspot + fallback and present clear current-mode/status guidance rather than promising simultaneous access. +- Surface current uplink mode, connected SSID without password, IP address, internet reachability, + last transition/error, and whether large video upload is permitted. Never mistake association + with the phone for proven internet reachability. +- Keep dashcam video off SIM868 cellular, but allow it through the phone hotspot's WiFi path. + Tracking, server alert synchronization, and other queued data must resume idempotently after the + phone hotspot appears. Existing cellular-first ntfy behavior remains separate. +- Hardware-test with at least one real phone: cold boot with hotspot present/absent, hotspot + enable/disable while running, wrong credentials, phone leaving/re-entering range, internet loss + while still associated, automatic Pi-hotspot recovery, local `yaris.local` access, tracking + catch-up, and a disposable chunked video upload. Record phone/OS limitations before committing. + +### Phase 23: Finish web UI redesign — 🚧 PLANNED +**Roadmap decision 2026-08-09: keep the redesign after functional uplink work.** Phase 15 already pulled the architecture-level work forward: every page now shares one Jinja shell and the later list-based features have a reusable component contract. Phases 16-21 still add most of the final screens and dashboard data. Redesigning their visual details before those features @@ -1121,8 +1153,8 @@ remaining cleanup once all the functional phases above have landed: framework rewrite would add deployment weight and offline assets on the Pi without improving the tracker features, and would discard the foundation deliberately built before Phases 16-21. -### Phase 23: Remote trip + dashcam portal with shared web UI — 🚧 PLANNED -**Added 2026-08-09; intentionally scheduled after Phase 22.** Phase 22 first establishes the final +### Phase 24: Remote trip + dashcam portal with shared web UI — 🚧 PLANNED +**Added 2026-08-09; intentionally scheduled after Phase 23.** Phase 23 first establishes the final visual language and complete in-car interface. Building the remote portal afterward avoids duplicating the current unfinished theme and lets both deployments deliberately share the same finished shell, components, trip list, route map, timeline replay, dashcam library, units, and @@ -1134,7 +1166,7 @@ recorded trip details, and footage can be accessed away from the car: - Add server-side trip boundary/index data equivalent to Phase 18, generated from uploaded tracking points without changing or deleting the raw records. Expose trip summaries, full/downsampled routes, timestamps, distance in km/mi, average/max speed in km/h and mph, and timeline replay. -- Reuse the redesigned Phase 22 Jinja/Bootstrap UI rather than creating a visually separate app. +- Reuse the redesigned Phase 23 Jinja/Bootstrap UI rather than creating a visually separate app. Extract/share presentation assets where practical so local and remote pages do not drift, while keeping their data providers and available actions explicit. - Make the uploaded dashcam archive a required first-class remote page, matching the redesigned @@ -1171,16 +1203,16 @@ recorded trip details, and footage can be accessed away from the car: access. The server stores per-vehicle alert history/current state, reconciles reconnects without duplicates, and exposes it in the remote portal; remote acknowledgement must not silently clear the underlying Pi condition. -- Deploy only after Phase 22 is complete: rebuild the unraid Docker stack, verify migrations against +- Deploy only after Phase 23 is complete: rebuild the unraid Docker stack, verify migrations against copied data first, compare remote trip calculations with uploaded Pi records, verify playback, Range requests, and downloads against disposable copies of real server footage, and browser-test desktop/mobile through the real hosted endpoint before committing. -### Phase 24: Pre-install Yaris 2013 compatibility test — 🚧 PLANNED (core-system gate) +### Phase 25: Pre-install Yaris 2013 compatibility test — 🚧 PLANNED (core-system gate) **Added 2026-08-09; intentionally immediately before the Android app.** Bench tests, synthetic routes, attached-hardware tests, and stationary Pi runs cannot prove the complete system works when temporarily connected to and powered by the actual 2013 Toyota Yaris. This phase is the -pre-installation acceptance gate for the complete core Pi/web/server system after Phase 23. It is +pre-installation acceptance gate for the complete core Pi/web/server system after Phase 24. It is verification and targeted correction—not permanent installation or another redesign—and the system is not considered ready to install until the results are recorded here. Permanent mounting, cable routing, trim work, and final installation are explicitly outside the roadmap and will be @@ -1217,7 +1249,7 @@ clean trip end: number for deliberate ignition gaps), correct start/end time and coordinates, plausible distance/average/max speed, km/mi and km/h/mph values, route polyline, start/end markers, timeline scrubber, play/pause marker position, and stopped portions of the route. -- **Local web UI:** test the final Phase 22 interface on the actual phone over the Pi hotspot at +- **Local web UI:** test the final Phase 23 interface on the actual phone over the Pi/phone network at `http://yaris.local/`; verify the explicit **In-car / Local Pi** identity, dashboard telemetry, DTC page, trip history, dashcam library, settings, alerts, responsive layout, reconnect behavior, and no new browser console/API errors. @@ -1228,7 +1260,7 @@ clean trip end: - **Alerts:** safely exercise conditions that can be simulated without damaging hardware (upload backlog, temporary GPS loss while OBD reports motion, and disposable threshold overrides). Confirm local bell transition/recovery/cooldown behavior and offline alert-state reconciliation - with the Phase 23 server after connectivity returns. Do not intentionally overheat, undervolt, + with the Phase 24 server after connectivity returns. Do not intentionally overheat, undervolt, fill storage, or trigger a real MIL. With a real SIM, explicitly determine whether the SIM868 transport can reliably deliver ntfy notifications while WiFi/Ethernet is unavailable, including authentication, timeout, retry, and recovery. If that cannot be made reliable on the actual @@ -1244,13 +1276,13 @@ Verify the complete remote path after connectivity returns: - Confirm every test-window tracking row uploads exactly once and the selected dashcam clip resumes or completes without corruption; compare counts, timestamps, hashes, and byte sizes locally and remotely. -- On the Phase 23 portal, verify the explicit **Remote server** identity, authenticated +- On the Phase 24 portal, verify the explicit **Remote server** identity, authenticated vehicle-scoped trip summary/replay, route and timeline agreement with the local Pi, archived clip thumbnail/playback/Range seeking/download, synchronized alert history/current state without duplicate transitions after an offline interval, and absence of local-only OBD/cellular/Pi controls. - The Android companion is intentionally outside this core acceptance gate and remains the final, - low-priority Phase 25. Its own hotspot/cellular binding, trip display, and disposable clip relay + low-priority Phase 26. Its own hotspot/cellular binding, trip display, and disposable clip relay require separate real-phone/in-car acceptance when that phase is implemented. Acceptance requires a written result for every item, captured negotiated protocol/PID support, @@ -1260,12 +1292,12 @@ must be fixed, redeployed uncommitted, and the affected in-car test repeated bef and **ready-to-install** sign-off. Afterward, the owner handles permanent installation outside the phase roadmap. -### Phase 25: Native Android companion app — 🚧 PLANNED (low priority, always last) +### Phase 26: Native Android companion app — 🚧 PLANNED (low priority, always last) Revives the phone-relay goal (Phase 11/12) properly this time, using a real native app instead of a web page - the only way to actually hold a WiFi connection to the Pi's hotspot and a cellular connection to the internet open simultaneously (`ConnectivityManager.bindProcessToNetwork()`, unavailable to browser JS - see the Phase 11 update). Explicitly **not urgent** and intentionally -kept at the end of the roadmap, after all web/server work and the Phase 24 core in-car acceptance +kept at the end of the roadmap, after all web/server work and the Phase 25 core in-car acceptance test are done. Permanent vehicle installation remains owner-handled and is not an implementation phase. Scope, at a high level (not yet designed in detail): - **Dashcam file transfer**: browse/select/delete dashcam clips already imported to the Pi (same diff --git a/readme.md b/readme.md index 06a0058..65e64a8 100644 --- a/readme.md +++ b/readme.md @@ -131,3 +131,7 @@ Notification secrets are write-only in the browser API, and network credentials the Pi out remain SSH/file-managed. When cellular is configured, small ntfy notifications use the SIM868 first and WiFi/Ethernet only as fallback; that modem path is implemented and mock-tested but still needs real-SIM/carrier verification. + +A planned pre-redesign phase will also let the Pi join a configured phone hotspot for outbound +internet when no SIM is available, including queued trip/alert synchronization and WiFi dashcam +uploads, with automatic recovery to the Pi-hosted local hotspot when the phone is unavailable.