184 lines
11 KiB
Markdown
184 lines
11 KiB
Markdown
# yaris-obd Feature Requests
|
|
|
|
Ideas and requests for **new features** (distinct from bugs, which belong in `BUGS.md`, and the
|
|
phase-by-phase implementation history in `PLAN.md`). Use this file to record anything that should
|
|
be built eventually but isn't an active roadmap phase yet. When a feature gets picked up, create a
|
|
dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it here.
|
|
|
|
## How to use this file
|
|
|
|
- **One `## FEAT-XX` section per idea.** Keep numbering sequential.
|
|
- **Status field**: `IDEA` (brainstormed, not planned) → `PLANNED` (has an assigned phase) →
|
|
`IN PROGRESS` → `SHIPPED` (deployed + verified) or `WONTFIX`/`SUPERSEDED` as appropriate.
|
|
- **Relate to roadmap**: when a feature lands in a phase, note the phase here and drop a link back
|
|
here from PLAN.md so the two stay in sync.
|
|
- **Keep each entry small and one-idea-per-entry** so it's easy to pick up and scope.
|
|
|
|
---
|
|
|
|
## Feature ideas
|
|
|
|
### FEAT-01 — Parallel/concurrent chunked dashcam uploads
|
|
- **Status**: `IDEA`
|
|
- **Area**: `modules/app_upload.py` (Pi upload client)
|
|
- **Phase**: Phase 27
|
|
- **Requested**: noted in Phase 10 of PLAN.md as a possible future optimization; not yet requested
|
|
explicitly by the owner.
|
|
- **Idea**: upload multiple dashcam chunks (and/or multiple files) concurrently instead of the
|
|
current strictly sequential one-chunk-then-one-file at a time. Would speed up the multi-hour
|
|
full-backlog drain of a large local dashcam archive, at the cost of more complexity (bounded
|
|
concurrency, per-file state, failure handling for the individual concurrent workers).
|
|
- **Outstanding considerations**: memory budget on the Pi (~900MB, no swap — must stay streaming),
|
|
and whether the sequential pace is actually annoying enough in practice to justify the added
|
|
complexity.
|
|
|
|
### FEAT-02 — QR / claim-code device pairing flow
|
|
- **Status**: `IDEA`
|
|
- **Area**: server device provisioning + Pi credential setup (Phase 25.5c)
|
|
- **Phase**: Phase 27
|
|
- **Requested**: discussed in Phase 25.5c as a possible follow-up to the manual copy/paste API-key
|
|
provisioning.
|
|
- **Idea**: zero-manual-copy provisioning of `YARIS_SERVER_URL` / `YARIS_DEVICE_NAME` /
|
|
`YARIS_API_KEY` onto the Pi — e.g. the portal shows a short-lived claim code / QR that the Pi
|
|
app (or owner) enters/scans once to adopt the device, instead of typing credentials by hand.
|
|
- **Outstanding considerations**: bigger scope than the current copy/paste flow; ship copy/paste
|
|
first, add pairing only if provisioning still feels annoying.
|
|
|
|
### FEAT-03 — Manual start odometer fallback when OBD odometer is unavailable
|
|
- **Status**: `SHIPPED` 2026-08-11
|
|
- **Area**: Settings page, Dashboard, `modules/app_settings.py`, `modules/app_sql.py`
|
|
- **Phase**: Phase 27
|
|
- **What**: Settings page now has an "Odometer baseline (km)" field. The app stores
|
|
this value and computes `odometer_km = baseline + cumulative trip distance`. Dashboard
|
|
shows "(manual)" label when using baseline. When baseline is 0, falls back to live
|
|
OBD reading (the original behavior). Also appears in `/api/stats` response.
|
|
|
|
### FEAT-04 — Replace SIM868 2G GSM hat with 4G LTE modem (Huawei E3372h-153)
|
|
- **Status**: `IDEA`
|
|
- **Area**: modems / uplink (Pi `modules/app_cellular.py`, `modules/app_gps.py`, uplink
|
|
switching) — replaces the current SIM868 GSM/GNSS HAT + cellular fallback path
|
|
- **Phase**: Phase 27
|
|
- **Requested**: owner — just purchased a Huawei **E3372h-153 4G LTE Modem**. The 2G/3G-only
|
|
SIM868 hat will not work in Canada (2G networks are decommissioned), so the plan is to make the
|
|
4G modem the working cellular uplink instead.
|
|
- **Idea**: integrate the Huawei E3372h-153 as the primary cellular data uplink, replacing reliance
|
|
on the SIM868's GSM (AT+HTTP) path. The E3372h-153 is a USB "stick" modem — likely supported via
|
|
Realtek / cdc_ether / usb-storage based drivers and exposes a dial-up or LTE dongle interface the
|
|
Pi can use for connectivity (e.g. via NetworkManager / ModemManager, or a static APN config).
|
|
- **Outstanding considerations**:
|
|
- Determine the E3372h-153's local mode vs stick/dial mode and the correct Linux driver/interface
|
|
(hierarchical USB mode switching may be needed; it's the "153" variant which may use the RNDIS /
|
|
ECM / CDC-NCM profile).
|
|
- Whether to run it as the *primary* uplink or just another option in the existing phone-hotspot /
|
|
home-wifi / local-AP priority chain.
|
|
- What happens to the SIM868 — keep it purely for its **GPS/GNSS** role (it's the PWRKEY-toggled
|
|
GNSS receiver on `/dev/serial0`) while dropping its **2G GSM** cellular path, vs removing it
|
|
entirely.
|
|
- The SIM868's `app_gps.py` GNSS positioning must keep working (it's the car's GPS source) even if
|
|
the 2G-modem half is retired — separate the two concerns.
|
|
- **Keep this feature as-is (2G/GSM fallback) for countries where 2G/3G still works** — don't
|
|
remove the existing cellular fallback code; gate it so the 2G path remains available there.
|
|
- LTE SIM plan/APN specifics for Canadian carriers (Rogers/Bell/Telus) and whether the modem can
|
|
run the Pi's hotspot/SSID the same way `app_network.py` currently does.
|
|
|
|
### FEAT-05 — DTC history synced to remote server with code descriptions
|
|
- **Status**: `IDEA`
|
|
- **Area**: `modules/app_upload.py`, `modules/app_sql.py`, `server/sql/`, `server/modules/db.py`,
|
|
`server/app.py`, server portal templates
|
|
- **Phase**: Phase 27
|
|
- **Requested**: 2026-08-11 — owner wants DTC codes persisted to the server (not just local SQLite)
|
|
with code + description, surviving until user deletes them or OBD reports the code cleared.
|
|
- **Current state (2026-08-11)**:
|
|
- Pi: `app_obd.py` polls DTCs from ECU → `app_sql.save_dtc_state()` persists MIL + codes
|
|
(code, description, IS_SET, FIRST_SEEN_AT, LAST_SEEN_AT) to local SQLite `dtc` table.
|
|
- Pi: `app_upload.py` uploads tracking rows and dashcam files — NO DTC upload path exists.
|
|
- Server: NO `dtc_events` table, NO DTC API, NO portal DTC page.
|
|
- **Design**:
|
|
|
|
**Server schema** (`server/sql/migrate_phase26_dtc.sql`):
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS dtc_events (
|
|
id SERIAL PRIMARY KEY,
|
|
device_id INTEGER NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
|
code VARCHAR(10) NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
mil_on BOOLEAN NOT NULL DEFAULT FALSE,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
first_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
cleared_at TIMESTAMPTZ,
|
|
UNIQUE (device_id, code)
|
|
);
|
|
```
|
|
|
|
**Server API** (`server/app.py`):
|
|
- `POST /api/v1/dtc/batch` (device auth): receives current DTC snapshot from Pi.
|
|
Body: `{"mil_on": true/false, "codes": [{"code": "P0301", "description": "Cylinder 1 Misfire"}, ...]}`
|
|
- Insert new codes, update `last_seen_at` for existing active codes.
|
|
- Mark any previously-active codes NOT in this batch as `is_active=false, cleared_at=now()`.
|
|
- Return `{received: N, cleared: M, unchanged: K}`.
|
|
- `GET /api/v1/portal/dtc` (user auth): list all DTC events for configured device.
|
|
- `DELETE /api/v1/portal/dtc/<id>` (user auth): manual deletion.
|
|
|
|
**Server portal**: new DTC page or section showing code, description, MIL state, first/last seen,
|
|
active/cleared status, cleared timestamp.
|
|
|
|
**Pi upload** (`modules/app_upload.py`):
|
|
- New `_upload_dtc_snapshot()` — called after tracking batch in `_upload_loop()`.
|
|
- Only uploads when the local DTC snapshot differs from last-uploaded (hash or version compare).
|
|
- Reuses same `_credentials()`/`_headers()` as tracking uploads.
|
|
- Same WiFi-first, cellular-fallback (if configured) path as tracking batches.
|
|
|
|
- **Deduplication logic**: server-side per `(device_id, code)` unique key. Pi sends the full
|
|
current snapshot each time. Server diffs: new codes = insert, existing = touch last_seen_at,
|
|
missing from snapshot = mark cleared. This means if a code disappears from the ECU, it
|
|
auto-clears on the server on the next upload — no manual "clear" step needed.
|
|
- **Manual deletion**: only via the server portal delete button. Cleared codes stay visible as
|
|
history. The Pi never deletes from the server automatically.
|
|
- **Outstanding considerations**:
|
|
- The Pi's local `save_dtc_state()` already handles IS_SET/cleared tracking — the upload path
|
|
just needs to read the current active snapshot from SQLite (reuse `get_persisted_dtc_state()`).
|
|
- DTC descriptions come directly from the ECU (python-obd's `GET_DTC` response) — they're the
|
|
standard SAE J2012 descriptions, no external lookup needed.
|
|
- Should we upload on every poll (every ~2s OBD cycle) or batch? Answer: batch. Upload alongside
|
|
tracking batches (every 30s idle, 1s catchup). DTCs don't change mid-drive that often.
|
|
- First upload after Pi reboot with no OBD connected: snapshot is empty → server marks all
|
|
previously-active codes as cleared. Is that desired? Probably not — should skip upload when
|
|
OBD is disconnected/unavailable (the Pi already knows this from `connection` state).
|
|
|
|
### FEAT-08 — Predictable IP on phone hotspot (DHCP client-id)
|
|
- **Status**: `SHIPPED` 2026-08-11 (Phase 22)
|
|
- **Area**: `deploy/yaris_uplink.py`, phone-hotspot NM profile
|
|
- **What**: `dhcp-client-id=yaris-obd` in the NM keyfile gives the Pi a consistent DHCP
|
|
lease. The "Last phone IP" link on Settings shows the current address. Pixel testing
|
|
confirmed same IP across disconnects.
|
|
|
|
### FEAT-09 — mDNS (yaris.local) on phone hotspot
|
|
- **Status**: `WONTFIX` 2026-08-12 — hardware/OS limitation
|
|
- **Area**: Avahi, phone-hotspot NM profile
|
|
- **What**: Phone hotspot hosts (Android, iOS) don't relay multicast DNS. Avahi publishes
|
|
correctly on wlan0 AP and home WiFi. Settings "Last phone IP" link is the workaround.
|
|
Cannot be fixed in software — this is a phone-OS limitation.
|
|
|
|
---
|
|
|
|
## Ideas that landed
|
|
|
|
(No entries yet — shipped features land here. Keep the original idea text intact and add the
|
|
shipped phase/date.)
|
|
|
|
### FEAT-07 — Phone-hotspot auto-connect documentation
|
|
- **Status**: `SHIPPED` 2026-08-11 (already implemented in Phase 22, documented here)
|
|
- **Area**: `deploy/yaris_uplink.py`, Settings page, netwatch timer
|
|
- **What**: The Pi auto-connects to a saved phone hotspot on wlan1 within ~60s of it
|
|
appearing in range, and falls back to home-wifi when it disappears. The wlan0 AP
|
|
stays up regardless. Test flow: Settings → save hotspot name + password → "Wait for
|
|
hotspot" → enable phone hotspot → verify mode changes to "Phone hotspot".
|
|
|
|
### FEAT-06 — Trip ID column in history table
|
|
- **Status**: `SHIPPED` 2026-08-11
|
|
- **Area**: `static/js/history.js`, `templates/history.html`, `server/templates/history.html`
|
|
- **Phase**: Phase 26
|
|
- **What**: Narrow `#ID` column on server history (hidden on Pi via `data-show-id`).
|
|
Checkbox column and batch-delete restored on server only.
|