Refresh docs and reorder roadmap
Co-authored-by: Copilot <[email protected]>
This commit is contained in:
@@ -1398,89 +1398,9 @@ including two UX polish passes and multiple bug-fix rounds.
|
|||||||
- **Dispatcher hook fix (`deploy/90-yaris-uplink`)** — previously ignored wlan1 events; now listens for both `wlan0` and `wlan1` so uplink transition recording remains accurate on current hardware.
|
- **Dispatcher hook fix (`deploy/90-yaris-uplink`)** — previously ignored wlan1 events; now listens for both `wlan0` and `wlan1` so uplink transition recording remains accurate on current hardware.
|
||||||
- **README hardware photo** — added a current hardware build image (`pics/yaris-obd-hardware.jpg`) at the bottom of `readme.md`; saved without EXIF metadata and resized for lighter page load.
|
- **README hardware photo** — added a current hardware build image (`pics/yaris-obd-hardware.jpg`) at the bottom of `readme.md`; saved without EXIF metadata and resized for lighter page load.
|
||||||
|
|
||||||
### Phase 25: Pre-install Yaris 2013 compatibility test — 🚧 PLANNED (core-system gate)
|
**Roadmap ordering note (2026-08-10):** the late phases are intentionally sequenced as
|
||||||
**Added 2026-08-09; intentionally immediately before the Android app.** Bench tests, synthetic
|
Phase 25.5a–25.5d (configuration/sync/status work) -> Phase 25 (real-car acceptance gate) ->
|
||||||
routes, attached-hardware tests, and stationary Pi runs cannot prove the complete system works
|
Phase 26 (Android, always last).
|
||||||
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 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
|
|
||||||
handled by the owner after this phase passes.
|
|
||||||
|
|
||||||
Prepare a temporary, removable test setup before driving:
|
|
||||||
- Connect the Pi, SIM868 HAT/antennas, USB OBD adapter, dashcam, and representative intended power
|
|
||||||
source without permanently mounting or routing anything. Secure every temporary component and
|
|
||||||
cable so it cannot interfere with pedals, steering, airbags, visibility, occupants, or loose-item
|
|
||||||
safety during the controlled drive; remove the setup after testing.
|
|
||||||
- Resolve the Phase 19/20 undervoltage/throttling warning before the test; confirm
|
|
||||||
`vcgencmd get_throttled` shows no current power fault at idle and under load with the temporary
|
|
||||||
representative power setup. This validates electrical compatibility, not final cable routing.
|
|
||||||
- Back up the Pi SQLite database and record baseline row/trip/video/upload counts on the Pi and
|
|
||||||
remote server. Use a uniquely timestamped test window so generated records can be reconciled
|
|
||||||
without deleting unrelated history.
|
|
||||||
- Verify the service, watchdog, storage mounts, hotspot, `http://yaris.local/`, alert engine, GPS
|
|
||||||
antenna view, dashcam recording mode, free space, and remote server health before moving.
|
|
||||||
- Use a second person for UI/log observations while the vehicle is moving, or record diagnostics
|
|
||||||
for review afterward. The driver must not operate or troubleshoot the UI while driving.
|
|
||||||
|
|
||||||
Run a controlled route containing ignition-off/on, stationary idle, low-speed streets, normal road
|
|
||||||
speed, several complete stops, turns, a short GPS-obstructed segment if safely available, and a
|
|
||||||
clean trip end:
|
|
||||||
- **OBD/ECU:** confirm the ELM327 reaches `CAR_CONNECTED`, record negotiated Toyota protocol and
|
|
||||||
adapter firmware, and verify real speed/RPM/coolant/fuel/throttle/MIL/DTC values. Compare wheel
|
|
||||||
speed against the instrument cluster at several safe speeds. Record unsupported PIDs (especially
|
|
||||||
odometer PID A6) as capabilities, not failures, and verify reconnect after ignition cycling and a
|
|
||||||
deliberate USB disconnect/reconnect.
|
|
||||||
- **GPS and motion logging:** confirm fixes while stationary and moving, route coordinates on the
|
|
||||||
offline map, OBD-speed-first motion detection, GPS displacement fallback when OBD is deliberately
|
|
||||||
unavailable, one-minute idle heartbeat behavior, and no false trip from stationary GPS drift.
|
|
||||||
- **Trip boundary/replay:** after the inactivity timeout, verify exactly one trip (or the expected
|
|
||||||
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 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.
|
|
||||||
- **Dashcam workflow:** create a known short real clip, switch the camera safely into USB storage
|
|
||||||
mode, detect/list it without confusing the OBD adapter, import only that selected file, verify
|
|
||||||
thumbnail/playback/Range seeking, preserve the source until checks finish, and confirm the camera
|
|
||||||
returns to recording afterward. Test deletion only with the disposable clip.
|
|
||||||
- **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 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
|
|
||||||
modem/network, remove the ntfy feature and its settings rather than retain a transport that fails
|
|
||||||
in the only situation where it is useful.
|
|
||||||
- **Power/reliability:** perform multiple normal ignition/power cycles, confirm automatic boot,
|
|
||||||
service/watchdog startup, SIM868 power-on, OBD/GPS recovery, no SQLite corruption, and no current
|
|
||||||
undervoltage/throttling. The deferred Phase 14 clean-shutdown limitation must be explicitly
|
|
||||||
accepted or resolved with representative delayed-power/ignition-sense hardware before declaring
|
|
||||||
the design ready for permanent installation.
|
|
||||||
|
|
||||||
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 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 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,
|
|
||||||
measured trip/count/hash comparisons, relevant logs/screenshots, no unexplained tracebacks or data
|
|
||||||
loss, and cleanup of every disposable record/file while preserving the real drive. Any defect found
|
|
||||||
must be fixed, redeployed uncommitted, and the affected in-car test repeated before the final commit
|
|
||||||
and **ready-to-install** sign-off. Afterward, the owner handles permanent installation outside the
|
|
||||||
phase roadmap.
|
|
||||||
|
|
||||||
### Phase 25.5a: Device configuration sync backend — ✅ COMPLETE (connection-driven server sync)
|
### Phase 25.5a: Device configuration sync backend — ✅ COMPLETE (connection-driven server sync)
|
||||||
**Server API and Pi sync thread implemented.** Server stores device config; Pi fetches when internet available and applies changes without restart.
|
**Server API and Pi sync thread implemented.** Server stores device config; Pi fetches when internet available and applies changes without restart.
|
||||||
@@ -1744,7 +1664,7 @@ updates its display-facing values without a manual restart once sync lands.
|
|||||||
history view still shows one configured car/device at a time until a later
|
history view still shows one configured car/device at a time until a later
|
||||||
portal-wide device selector/filter is implemented.
|
portal-wide device selector/filter is implemented.
|
||||||
|
|
||||||
### Phase 25.5d: GPS dashboard visibility / live-status debugging — 🚧 IN PROGRESS
|
### Phase 25.5d: GPS dashboard visibility / live-status debugging — ✅ COMPLETE
|
||||||
- Add an explicit Pi dashboard GPS status indicator (thread alive / live fix / stale fix / no fix)
|
- Add an explicit Pi dashboard GPS status indicator (thread alive / live fix / stale fix / no fix)
|
||||||
- Expose a local `/api/gps/status` endpoint so GPS health can be checked without relying on
|
- Expose a local `/api/gps/status` endpoint so GPS health can be checked without relying on
|
||||||
socket events alone
|
socket events alone
|
||||||
@@ -1793,6 +1713,91 @@ updates its display-facing values without a manual restart once sync lands.
|
|||||||
card now appears before the Live GPS map. Deployed to the real Pi and confirmed the rendered
|
card now appears before the Live GPS map. Deployed to the real Pi and confirmed the rendered
|
||||||
`/` HTML places `Overview` before `Live GPS`.
|
`/` HTML places `Overview` before `Live GPS`.
|
||||||
|
|
||||||
|
---
|
||||||
|
### 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 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
|
||||||
|
handled by the owner after this phase passes.
|
||||||
|
|
||||||
|
Prepare a temporary, removable test setup before driving:
|
||||||
|
- Connect the Pi, SIM868 HAT/antennas, USB OBD adapter, dashcam, and representative intended power
|
||||||
|
source without permanently mounting or routing anything. Secure every temporary component and
|
||||||
|
cable so it cannot interfere with pedals, steering, airbags, visibility, occupants, or loose-item
|
||||||
|
safety during the controlled drive; remove the setup after testing.
|
||||||
|
- Resolve the Phase 19/20 undervoltage/throttling warning before the test; confirm
|
||||||
|
`vcgencmd get_throttled` shows no current power fault at idle and under load with the temporary
|
||||||
|
representative power setup. This validates electrical compatibility, not final cable routing.
|
||||||
|
- Back up the Pi SQLite database and record baseline row/trip/video/upload counts on the Pi and
|
||||||
|
remote server. Use a uniquely timestamped test window so generated records can be reconciled
|
||||||
|
without deleting unrelated history.
|
||||||
|
- Verify the service, watchdog, storage mounts, hotspot, `http://yaris.local/`, alert engine, GPS
|
||||||
|
antenna view, dashcam recording mode, free space, and remote server health before moving.
|
||||||
|
- Use a second person for UI/log observations while the vehicle is moving, or record diagnostics
|
||||||
|
for review afterward. The driver must not operate or troubleshoot the UI while driving.
|
||||||
|
|
||||||
|
Run a controlled route containing ignition-off/on, stationary idle, low-speed streets, normal road
|
||||||
|
speed, several complete stops, turns, a short GPS-obstructed segment if safely available, and a
|
||||||
|
clean trip end:
|
||||||
|
- **OBD/ECU:** confirm the ELM327 reaches `CAR_CONNECTED`, record negotiated Toyota protocol and
|
||||||
|
adapter firmware, and verify real speed/RPM/coolant/fuel/throttle/MIL/DTC values. Compare wheel
|
||||||
|
speed against the instrument cluster at several safe speeds. Record unsupported PIDs (especially
|
||||||
|
odometer PID A6) as capabilities, not failures, and verify reconnect after ignition cycling and a
|
||||||
|
deliberate USB disconnect/reconnect.
|
||||||
|
- **GPS and motion logging:** confirm fixes while stationary and moving, route coordinates on the
|
||||||
|
offline map, OBD-speed-first motion detection, GPS displacement fallback when OBD is deliberately
|
||||||
|
unavailable, one-minute idle heartbeat behavior, and no false trip from stationary GPS drift.
|
||||||
|
- **Trip boundary/replay:** after the inactivity timeout, verify exactly one trip (or the expected
|
||||||
|
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 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.
|
||||||
|
- **Dashcam workflow:** create a known short real clip, switch the camera safely into USB storage
|
||||||
|
mode, detect/list it without confusing the OBD adapter, import only that selected file, verify
|
||||||
|
thumbnail/playback/Range seeking, preserve the source until checks finish, and confirm the camera
|
||||||
|
returns to recording afterward. Test deletion only with the disposable clip.
|
||||||
|
- **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 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
|
||||||
|
modem/network, remove the ntfy feature and its settings rather than retain a transport that fails
|
||||||
|
in the only situation where it is useful.
|
||||||
|
- **Power/reliability:** perform multiple normal ignition/power cycles, confirm automatic boot,
|
||||||
|
service/watchdog startup, SIM868 power-on, OBD/GPS recovery, no SQLite corruption, and no current
|
||||||
|
undervoltage/throttling. The deferred Phase 14 clean-shutdown limitation must be explicitly
|
||||||
|
accepted or resolved with representative delayed-power/ignition-sense hardware before declaring
|
||||||
|
the design ready for permanent installation.
|
||||||
|
|
||||||
|
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 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 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,
|
||||||
|
measured trip/count/hash comparisons, relevant logs/screenshots, no unexplained tracebacks or data
|
||||||
|
loss, and cleanup of every disposable record/file while preserving the real drive. Any defect found
|
||||||
|
must be fixed, redeployed uncommitted, and the affected in-car test repeated before the final commit
|
||||||
|
and **ready-to-install** sign-off. Afterward, the owner handles permanent installation outside the
|
||||||
|
phase roadmap.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Phase 26: Native Android companion app — 🚧 PLANNED (low priority, always last)
|
### Phase 26: Native Android companion app — 🚧 PLANNED (low priority, always last)
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ Dashboard — mobile (390 px) and desktop (1280 px):
|
|||||||
trip history with OSM/CARTO live map and route replay, dashcam archive browsing with inline
|
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
|
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
|
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 multiple devices, reveal a one-time API key at
|
pulls from the server. The portal can register/delete multiple devices, reveal a one-time API
|
||||||
creation/rotation time, and request a sync for a selected device. When the Pi has
|
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
|
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
|
both the Pi and the server — tile source and zoom limits are configured per-deployment via HTML
|
||||||
@@ -71,8 +71,9 @@ Dashboard — mobile (390 px) and desktop (1280 px):
|
|||||||
diagnostics, plus quick actions for server test, sync-now, uplink reconnect, and app restart
|
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
|
parked writes, plus retry-safe remote sync and automatic backoff
|
||||||
- 🌡️ **Pi health monitoring** — dashboard temperature, RAM, disk space, uptime, and explicit
|
- 🌡️ **Pi health + diagnostics** — a dedicated local Status page shows temperature, RAM, disk,
|
||||||
undervoltage/throttling warnings from the Raspberry Pi firmware
|
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
|
storage pressure, upload backlog, temperature/power faults, and GPS loss while moving. Optional
|
||||||
ntfy delivery is available but remains disabled until configured
|
ntfy delivery is available but remains disabled until configured
|
||||||
@@ -122,7 +123,14 @@ For the remote server (receives trip logs + dashcam uploads), see [server/README
|
|||||||
|
|
||||||
## Customizing device identity
|
## Customizing device identity
|
||||||
|
|
||||||
The Pi displays a username, car model, and avatar image. All customizable values are stored in `config/device.json` (no code edits needed).
|
The Pi displays an owner name, car model, device name, and avatar. You can manage those values in
|
||||||
|
two ways:
|
||||||
|
|
||||||
|
- **Locally on the Pi** through the Settings page
|
||||||
|
- **From the server portal** when **Sync with server** is enabled on the Pi
|
||||||
|
|
||||||
|
The local fallback/default source remains [config/device.json](./config/device.json), so the car
|
||||||
|
still boots with sensible identity values even when fully offline.
|
||||||
|
|
||||||
### Edit device configuration
|
### Edit device configuration
|
||||||
|
|
||||||
@@ -141,10 +149,10 @@ Edit [config/device.json](./config/device.json):
|
|||||||
|-------|----------|---------|
|
|-------|----------|---------|
|
||||||
| `owner_name` | Top-right of app topbar | Your name/username |
|
| `owner_name` | Top-right of app topbar | Your name/username |
|
||||||
| `car_model` | Left sidebar (next to car icon) | Vehicle model/year |
|
| `car_model` | Left sidebar (next to car icon) | Vehicle model/year |
|
||||||
| `device_name` | (Reserved) | Future server-side use in Phase 25.5 |
|
| `device_name` | Local settings / remote portal | Device identity used by server sync/provisioning |
|
||||||
| `avatar_path` | Top-right avatar circle | Profile picture (relative to `static/`) |
|
| `avatar_path` | Top-right avatar circle | Profile picture (relative to `static/`) |
|
||||||
|
|
||||||
After editing, restart the app:
|
If you edit the JSON file directly, restart the app:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# If running as a systemd service:
|
# If running as a systemd service:
|
||||||
@@ -187,15 +195,26 @@ rm db/sql/quoije_Yaris2013.db
|
|||||||
|
|
||||||
## Project status
|
## Project status
|
||||||
|
|
||||||
Phases 1–24.7 are complete. The system is fully built and audited, ready for the Phase 25 real-vehicle test:
|
The build is now at the endgame stage: the Pi app, remote server, and device-management/sync work
|
||||||
|
are implemented and verified on the real Pi/unraid setup. The remaining roadmap phases are the
|
||||||
|
temporary real-vehicle acceptance test and the low-priority Android companion.
|
||||||
|
|
||||||
- **Phases 1–23.5**: core Pi system — GPS, OBD, dashcam, trip history, web UI redesign, WiFi upgrade, cellular fallback, alerts, settings, upload
|
- **Phases 1–23.5**: core Pi system — GPS, OBD, dashcam, trip history, web UI redesign, WiFi upgrade, cellular fallback, alerts, settings, upload
|
||||||
- **Phase 24**: remote web portal at `https://yaris.ceaf.dev/` — login-protected, trip history with CARTO live map, dashcam archive, delete, overview stats
|
- **Phase 24**: remote web portal at `https://yaris.ceaf.dev/` — login-protected, trip history with CARTO live map, dashcam archive, delete, overview stats
|
||||||
- **Phase 24.5**: full code audit — 6 bugs fixed across Pi modules and server, 63 tests passing
|
- **Phase 24.5**: full code audit — 6 bugs fixed across Pi modules and server, 63 tests passing
|
||||||
- **Phase 24.6**: Yaris 2013 OBD compatibility hardening — `_decode_odometer` no longer kills the OBD session on unsupported PIDs, sensor globals reset on reconnect, `OBD_SKIP_VOLTAGE_CHECK` escape hatch for clone ELM327 adapters
|
- **Phase 24.6**: Yaris 2013 OBD compatibility hardening — `_decode_odometer` no longer kills the OBD session on unsupported PIDs, sensor globals reset on reconnect, `OBD_SKIP_VOLTAGE_CHECK` escape hatch for clone ELM327 adapters
|
||||||
- **Phase 24.7**: diagnostic script (`scripts/diagnose.sh`), map tile switch to CARTO, zoom limit fix
|
- **Phase 24.7**: diagnostic script (`scripts/diagnose.sh`), map tile switch to CARTO, zoom limit fix
|
||||||
|
- **Phase 24.8**: deployment/readme cleanup and uplink interface consistency
|
||||||
|
- **Phases 25.5a–25.5d**: offline-first device identity sync, remote portal device settings,
|
||||||
|
Pi-side hot-reload, multi-device provisioning, one-time API key rotation/registration, local
|
||||||
|
Settings UI for remote credentials, Sync now / Test connection, GPS live-status verification,
|
||||||
|
dedicated local Status page, and status-page quick actions
|
||||||
|
- **Current known limitation**: the remote portal's device-management page is multi-device, but the
|
||||||
|
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 25 — temporary real-vehicle test in the 2013 Yaris (see PLAN.md for the full acceptance checklist). Phase 26 (Android companion app) follows after that.
|
**Next**: Phase 25 — temporary real-vehicle test in the 2013 Yaris (see [PLAN.md](./PLAN.md) for
|
||||||
|
the full acceptance checklist). Phase 26 (Android companion app) follows after that.
|
||||||
|
|
||||||
Phase 14 is partially complete: the Pi's hardware watchdog is deployed and reboot-verified.
|
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
|
Read-only-root storage hardening is deferred until persistent storage is moved off the SD root
|
||||||
@@ -205,12 +224,12 @@ The browser-based phone relay was removed after real-world testing confirmed tha
|
|||||||
cannot reliably use the Pi's WiFi and cellular data simultaneously. A native Android companion is
|
cannot reliably use the Pi's WiFi and cellular data simultaneously. A native Android companion is
|
||||||
planned later instead (Phase 26).
|
planned later instead (Phase 26).
|
||||||
|
|
||||||
The local Web UI includes a Settings page for safe runtime configuration: dashcam uploads,
|
The local web UI includes a Settings page for safe runtime configuration: dashcam uploads,
|
||||||
uploaded-video retention, cellular APN fallback, optional ntfy delivery, and alert thresholds.
|
uploaded-video retention, cellular APN fallback, optional ntfy delivery, alert thresholds, local
|
||||||
Notification secrets are write-only in the browser API, and network credentials that could lock
|
device identity, and remote server credentials/API key. Notification secrets remain write-only in
|
||||||
the Pi out remain SSH/file-managed. When cellular is configured, small ntfy notifications use the
|
the browser API. When cellular is configured, small ntfy notifications use the SIM868 first and
|
||||||
SIM868 first and WiFi/Ethernet only as fallback; that modem path is implemented and mock-tested but
|
WiFi/Ethernet only as fallback; that modem path is implemented and mock-tested but still needs
|
||||||
still needs real-SIM/carrier verification.
|
real-SIM/carrier verification.
|
||||||
|
|
||||||
The Pi can also join a configured phone hotspot for outbound internet when no SIM is available,
|
The Pi can also join a configured phone hotspot for outbound internet when no SIM is available,
|
||||||
including trip synchronization and WiFi dashcam uploads, with automatic recovery to home WiFi or
|
including trip synchronization and WiFi dashcam uploads, with automatic recovery to home WiFi or
|
||||||
|
|||||||
+33
-18
@@ -21,6 +21,13 @@ docker-compose stack on an unraid server (or any Docker host).
|
|||||||
staged on disk and reassembled + sha256-verified once all have arrived, then
|
staged on disk and reassembled + sha256-verified once all have arrived, then
|
||||||
recorded the same way as the single-shot endpoint. This is what the Pi
|
recorded the same way as the single-shot endpoint. This is what the Pi
|
||||||
actually uses for real dashcam files — see "Why chunked uploads" below.
|
actually uses for real dashcam files — see "Why chunked uploads" below.
|
||||||
|
- `GET /api/device-config` — device-authenticated config fetch used by the Pi's
|
||||||
|
identity-sync thread and local **Sync now** action.
|
||||||
|
- `POST /api/v1/device-config/ack` — device-authenticated config-sync
|
||||||
|
acknowledgement so the server can record the last applied version/time.
|
||||||
|
- `/settings/device` + `/api/v1/portal/devices*` — login-protected multi-device
|
||||||
|
management UI/APIs for create, delete, rotate key, edit config, and request
|
||||||
|
sync.
|
||||||
|
|
||||||
Both `/api/v1/tracking/batch` and the dashcam upload endpoints require two
|
Both `/api/v1/tracking/batch` and the dashcam upload endpoints require two
|
||||||
headers: `X-Device-Name` and `X-Api-Key` (see
|
headers: `X-Device-Name` and `X-Api-Key` (see
|
||||||
@@ -28,13 +35,11 @@ headers: `X-Device-Name` and `X-Api-Key` (see
|
|||||||
Postgres is **not** published to the LAN — only the `api` container talks to
|
Postgres is **not** published to the LAN — only the `api` container talks to
|
||||||
it, over the internal compose network.
|
it, over the internal compose network.
|
||||||
|
|
||||||
**CORS is enabled on every response** (`Access-Control-Allow-Origin: *`) so a
|
**CORS is enabled on every response** (`Access-Control-Allow-Origin: *`) for the
|
||||||
device's registered API key can be used directly from browser JS running on a
|
device-authenticated API surface. This keeps header-authenticated device calls
|
||||||
*different* origin — specifically, the Pi's phone-relay feature (see
|
usable from browser-based tooling and same-user cross-origin utilities without
|
||||||
[PLAN.md](../PLAN.md) Phase 11), where a phone's browser calls this API
|
introducing cookie/session theft risk, because device auth is explicit
|
||||||
straight from a page served by the Pi itself. This is safe here because
|
(`X-Device-Name`/`X-Api-Key`) rather than ambient session auth.
|
||||||
auth is header-based (`X-Device-Name`/`X-Api-Key`), not cookie/session-based,
|
|
||||||
so a permissive origin can't be used to steal a logged-in session.
|
|
||||||
|
|
||||||
## Deploying on unraid
|
## Deploying on unraid
|
||||||
|
|
||||||
@@ -65,12 +70,11 @@ so a permissive origin can't be used to steal a logged-in session.
|
|||||||
docker compose ps
|
docker compose ps
|
||||||
curl http://localhost:8098/health
|
curl http://localhost:8098/health
|
||||||
```
|
```
|
||||||
5. Sign in to the remote portal and open `/settings/device` to edit the synced
|
5. Sign in to the remote portal and open `/settings/device` to manage devices:
|
||||||
owner/car/device/avatar values for the configured `DEVICE_NAME`. If the Pi
|
create/delete devices, reveal a one-time API key, rotate keys, edit synced
|
||||||
has local **Sync with server** enabled, those values hot-reload into the
|
owner/car/device/avatar values, and request a sync. If the Pi has local
|
||||||
running Pi UI after the next successful sync. Phase 25.5c also adds a
|
**Sync with server** enabled, those values hot-reload into the running Pi UI
|
||||||
multi-device list, one-time API-key reveal, key rotation, and a request-sync
|
after the next successful sync.
|
||||||
action on that page.
|
|
||||||
|
|
||||||
### Upgrading an existing unraid deployment
|
### Upgrading an existing unraid deployment
|
||||||
|
|
||||||
@@ -87,10 +91,12 @@ docker compose up -d --build
|
|||||||
|
|
||||||
Phase 25.5a adds the device identity sync columns (`owner_name`, `car_model`,
|
Phase 25.5a adds the device identity sync columns (`owner_name`, `car_model`,
|
||||||
`device_name`, `avatar_path`, `config_version`, `config_updated_at`) used by the
|
`device_name`, `avatar_path`, `config_version`, `config_updated_at`) used by the
|
||||||
Pi/server config sync flow. The browser portal page at `/settings/device` edits
|
Pi/server config sync flow. Phase 25.5c adds multi-device provisioning/status
|
||||||
those values; the Pi applies them on its next successful sync when local
|
columns (`last_config_sync_at`, `last_config_sync_version`,
|
||||||
**Sync with server** is enabled, and Phase 25.5b now hot-reloads the in-process
|
`force_sync_requested_at`, `api_key_rotated_at`). The browser portal page at
|
||||||
UI fields instead of requiring an app restart.
|
`/settings/device` edits those values; the Pi applies them on its next
|
||||||
|
successful sync when local **Sync with server** is enabled, and Phase 25.5b
|
||||||
|
hot-reloads the in-process UI fields instead of requiring an app restart.
|
||||||
|
|
||||||
## Registering a device and getting an API key
|
## Registering a device and getting an API key
|
||||||
|
|
||||||
@@ -104,14 +110,23 @@ This prints a one-time API key — copy the `YARIS_DEVICE_NAME` /
|
|||||||
`YARIS_API_KEY` values into the Pi's upload-client config. Only the
|
`YARIS_API_KEY` values into the Pi's upload-client config. Only the
|
||||||
key's sha256 hash is stored server-side; the raw key is never shown again.
|
key's sha256 hash is stored server-side; the raw key is never shown again.
|
||||||
|
|
||||||
|
On the Pi, those credentials can now be entered through the local Settings page
|
||||||
|
instead of editing `db/upload_creds.env` over SSH. The same page also exposes
|
||||||
|
**Test connection** and **Sync now** actions.
|
||||||
|
|
||||||
The browser portal at `/settings/device` can now do the same workflow without
|
The browser portal at `/settings/device` can now do the same workflow without
|
||||||
shell access:
|
shell access:
|
||||||
|
|
||||||
- create a new device
|
- create a new device
|
||||||
|
- delete a non-default device
|
||||||
- reveal a one-time API key
|
- reveal a one-time API key
|
||||||
- rotate the API key later
|
- rotate the API key later
|
||||||
- request a sync for the selected device
|
- request a sync for the selected device
|
||||||
|
|
||||||
|
Current limitation: device management is multi-device, but the main remote
|
||||||
|
overview/history/dashcam browsing pages still scope themselves to one
|
||||||
|
configured `DEVICE_NAME` until a portal-wide device selector/filter is added.
|
||||||
|
|
||||||
## Exposing it outside the LAN
|
## Exposing it outside the LAN
|
||||||
|
|
||||||
Two options, either works with this API unchanged:
|
Two options, either works with this API unchanged:
|
||||||
@@ -149,7 +164,7 @@ byte-for-byte sha256-verified against the source on the Pi.
|
|||||||
|
|
||||||
The Pi's web UI has a setting to pause dashcam file uploads while keeping
|
The Pi's web UI has a setting to pause dashcam file uploads while keeping
|
||||||
GPS/trip log uploads running — no server-side change needed, the Pi simply
|
GPS/trip log uploads running — no server-side change needed, the Pi simply
|
||||||
stops calling `/api/v1/dashcam/upload` while the toggle is off.
|
stops calling the dashcam upload status/chunk endpoints while the toggle is off.
|
||||||
|
|
||||||
## Local development / testing without unraid
|
## Local development / testing without unraid
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user