Add fresh-Pi deploy guide and uplink consistency fixes

- add deploy/readme.md with full fresh install + quick bootstrap block
- update README with deploy guide link and hardware photo
- fix app_network interface detection for wlan1-first setup
- make dispatcher hook handle wlan0 and wlan1
- update PLAN.md with Phase 24.8 completion notes

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Mathieu Moran
2026-08-10 15:54:36 -04:00
co-authored by Copilot
parent 0cd798ee19
commit ae0bcc7ea8
6 changed files with 214 additions and 4 deletions
+15
View File
@@ -1383,6 +1383,21 @@ including two UX polish passes and multiple bug-fix rounds.
- **Map zoom limits** — `history.js` now reads `data-min-zoom`/`data-max-zoom`/`data-tile-subdomains` from the `#history-map` div. Pi template caps to zoom 8–15 (matches offline cached tile range). Server template allows full 3–19. Prevents grey tiles when zooming outside cached range. - **Map zoom limits** — `history.js` now reads `data-min-zoom`/`data-max-zoom`/`data-tile-subdomains` from the `#history-map` div. Pi template caps to zoom 8–15 (matches offline cached tile range). Server template allows full 3–19. Prevents grey tiles when zooming outside cached range.
- **`tiles.addTo(map)` at init** — tiles were previously only added lazily on first trip click; now added immediately so the map background shows on page load. - **`tiles.addTo(map)` at init** — tiles were previously only added lazily on first trip click; now added immediately so the map background shows on page load.
### Phase 24.8: Deploy onboarding docs + uplink interface consistency — ✅ DONE
**Completed 2026-08-10.** Tightened the fresh-install path and aligned network-status plumbing with the Phase 23 wlan1-first architecture.
#### Changes
- **`deploy/readme.md`** — added a complete fresh-Pi install guide with:
- required packages (`network-manager`, `nftables`, `avahi-daemon`, `dnsmasq-base`, Python tooling),
- required NetworkManager profiles (`home-wifi`, `Hotspot`) with concrete `nmcli` examples,
- deploy script run order (`install_service`, `install_port_redirect`, `install_netwatch`, `install_video_tools`, optional watchdog),
- post-install verification and update/recovery commands.
- **Quick copy/paste bootstrap** — added a "Quick install" block at the top of `deploy/readme.md` for faster onboarding when provisioning a fresh Pi.
- **Root README deploy link** — `readme.md` now explicitly points to `deploy/readme.md` for clean Pi setup, instead of requiring PLAN deep-reading for first-time install.
- **Network status interface fix (`modules/app_network.py`)** — status endpoint previously hardcoded `wlan0`, which could misreport real uplink state after the T3U migration. It now resolves interface at runtime (`wlan1` primary, `wlan0` fallback) and reports the active interface in the response.
- **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.
### Phase 25: 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 **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 routes, attached-hardware tests, and stationary Pi runs cannot prove the complete system works
+4 -1
View File
@@ -1,6 +1,9 @@
#!/bin/sh #!/bin/sh
[ "$1" = "wlan0" ] || exit 0 case "$1" in
wlan0|wlan1) ;;
*) exit 0 ;;
esac
case "$2" in case "$2" in
up|down|connectivity-change|dhcp4-change) up|down|connectivity-change|dhcp4-change)
+172
View File
@@ -0,0 +1,172 @@
# Fresh Raspberry Pi install (deploy guide)
This guide installs `yaris-obd` on a clean Raspberry Pi so the web app auto-starts on boot and is reachable at `http://yaris.local`.
## Quick install (copy/paste)
If your Pi already has Raspberry Pi OS Bookworm and internet, this is the fastest path:
```bash
sudo adduser --disabled-password --gecos "" yaris 2>/dev/null || true
sudo usermod -aG sudo yaris
sudo apt-get update
sudo apt-get install -y \
git python3 python3-venv python3-pip \
network-manager nftables avahi-daemon dnsmasq-base
sudo systemctl enable --now NetworkManager
sudo -u yaris mkdir -p /home/yaris/app
sudo -u yaris git clone https://github.com/quoije/yaris-obd.git /home/yaris/app/yaris-obd 2>/dev/null || true
cd /home/yaris/app/yaris-obd
# REQUIRED before netwatch install:
# Create/update NetworkManager profiles named exactly:
# - home-wifi (client WiFi)
# - Hotspot (local AP, shared at 10.42.0.1/24)
# See section 4 below for exact nmcli commands.
bash deploy/install_service.sh
bash deploy/install_port_redirect.sh
bash deploy/install_netwatch.sh
bash deploy/install_video_tools.sh
# Optional:
# bash deploy/install_watchdog.sh
```
Then verify:
```bash
sudo systemctl status yaris-obd.service --no-pager
sudo systemctl status yaris-netwatch.timer --no-pager
curl -I http://127.0.0.1/
```
## 1) Base OS and assumptions
- Raspberry Pi OS Bookworm (Lite is fine)
- Internet access for package install
- User account named `yaris`
- Repo path: `/home/yaris/app/yaris-obd` (required by `deploy/yaris-obd.service`)
If the `yaris` user does not exist yet:
```bash
sudo adduser yaris
sudo usermod -aG sudo yaris
```
## 2) Install system packages
```bash
sudo apt-get update
sudo apt-get install -y \
git python3 python3-venv python3-pip \
network-manager nftables avahi-daemon dnsmasq-base
```
Enable NetworkManager on boot:
```bash
sudo systemctl enable --now NetworkManager
```
## 3) Clone the project
```bash
sudo -u yaris mkdir -p /home/yaris/app
sudo -u yaris git clone https://github.com/quoije/yaris-obd.git /home/yaris/app/yaris-obd
cd /home/yaris/app/yaris-obd
```
## 4) Create required NetworkManager profiles
`deploy/install_netwatch.sh` expects two profiles to already exist:
- `home-wifi` (normal client connection)
- `Hotspot` (local AP for phones/laptops in the car)
### 4a) Home WiFi profile (edit SSID/password)
```bash
sudo nmcli connection add \
type wifi \
con-name home-wifi \
ifname wlan1 \
ssid "<HOME_WIFI_SSID>" \
wifi-sec.key-mgmt wpa-psk \
wifi-sec.psk "<HOME_WIFI_PASSWORD>" \
connection.autoconnect yes \
connection.autoconnect-priority 30
```
### 4b) Local hotspot profile (edit password)
```bash
sudo nmcli connection add type wifi con-name Hotspot ifname wlan1 ssid yaris-obd
sudo nmcli connection modify Hotspot \
802-11-wireless.mode ap \
802-11-wireless.band bg \
wifi-sec.key-mgmt wpa-psk \
wifi-sec.psk "<HOTSPOT_PASSWORD>" \
ipv4.method shared \
ipv4.addresses 10.42.0.1/24 \
connection.autoconnect yes \
connection.autoconnect-priority 10
```
> If you do not use the TP-Link T3U (`wlan1`), switch `ifname wlan1` to `ifname wlan0` above and update `WLAN`/`WLAN_FB` in `deploy/install_netwatch.sh` before running it.
## 5) Run deploy installers (in order)
From `/home/yaris/app/yaris-obd`:
```bash
bash deploy/install_service.sh
bash deploy/install_port_redirect.sh
bash deploy/install_netwatch.sh
bash deploy/install_video_tools.sh
```
Optional (recommended on real hardware):
```bash
bash deploy/install_watchdog.sh
```
## 6) Verify
```bash
sudo systemctl status yaris-obd.service --no-pager
sudo systemctl status yaris-netwatch.timer --no-pager
sudo nft list ruleset | grep -n "dport 80"
curl -I http://127.0.0.1/
```
Expected:
- `yaris-obd.service` is `active (running)`
- `yaris-netwatch.timer` is active
- nftables has redirect from port `80` to `5000`
- local HTTP on port 80 returns 200/302
Then test from another device:
- `http://yaris.local`
- if mDNS is not available on that client, try `http://10.42.0.1`
## 7) Updating later
```bash
cd /home/yaris/app/yaris-obd
git pull --ff-only
bash deploy/install_service.sh
sudo systemctl restart yaris-obd.service
```
If deploy files changed, rerun the corresponding installer script(s) (`install_netwatch.sh`, `install_port_redirect.sh`, etc.).
## 8) Useful diagnostics
```bash
bash /home/yaris/app/yaris-obd/scripts/diagnose.sh
bash /home/yaris/app/yaris-obd/scripts/diagnose.sh --fix
```
+17 -2
View File
@@ -9,7 +9,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
INSTALLED_HELPER = "/usr/local/bin/yaris-uplink" INSTALLED_HELPER = "/usr/local/bin/yaris-uplink"
REPO_HELPER = os.path.join(BASE_DIR, "deploy", "yaris_uplink.py") REPO_HELPER = os.path.join(BASE_DIR, "deploy", "yaris_uplink.py")
PHONE_CONNECTION = "phone-hotspot" PHONE_CONNECTION = "phone-hotspot"
INTERFACE = "wlan0" PRIMARY_INTERFACE = "wlan1"
FALLBACK_INTERFACE = "wlan0"
STATUS_PATH = "/var/lib/yaris-obd/uplink-status.json" STATUS_PATH = "/var/lib/yaris-obd/uplink-status.json"
@@ -17,6 +18,18 @@ class NetworkConfigurationError(RuntimeError):
pass pass
def _interface_exists(iface):
return os.path.exists(f"/sys/class/net/{iface}")
def _resolve_interface():
if _interface_exists(PRIMARY_INTERFACE):
return PRIMARY_INTERFACE
if _interface_exists(FALLBACK_INTERFACE):
return FALLBACK_INTERFACE
return PRIMARY_INTERFACE
def _helper_command(action): def _helper_command(action):
if os.path.isfile(INSTALLED_HELPER): if os.path.isfile(INSTALLED_HELPER):
return ["sudo", "-n", INSTALLED_HELPER, action] return ["sudo", "-n", INSTALLED_HELPER, action]
@@ -99,12 +112,13 @@ def _phone_ssid():
def get_status(): def get_status():
interface = _resolve_interface()
values = _nmcli( values = _nmcli(
"-g", "-g",
"GENERAL.CONNECTION,GENERAL.STATE,GENERAL.IP4-CONNECTIVITY,IP4.ADDRESS", "GENERAL.CONNECTION,GENERAL.STATE,GENERAL.IP4-CONNECTIVITY,IP4.ADDRESS",
"device", "device",
"show", "show",
INTERFACE, interface,
).splitlines() ).splitlines()
values += [""] * (4 - len(values)) values += [""] * (4 - len(values))
last_transition = {} last_transition = {}
@@ -134,6 +148,7 @@ def get_status():
"state": values[1], "state": values[1],
"internet_reachable": internet_reachable, "internet_reachable": internet_reachable,
"connectivity": connectivity, "connectivity": connectivity,
"interface": interface,
"ip_address": values[3].split("/", 1)[0], "ip_address": values[3].split("/", 1)[0],
"phone_configured": bool(phone_ssid), "phone_configured": bool(phone_ssid),
"phone_ssid": phone_ssid, "phone_ssid": phone_ssid,
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

+6 -1
View File
@@ -109,7 +109,8 @@ python3 app.py
The app serves on `http://<host>:5000`. On the Pi it runs as a `systemd` service and is reachable The app serves on `http://<host>:5000`. On the Pi it runs as a `systemd` service and is reachable
with no port number at `http://yaris.local` after installing the mDNS and port-redirect setup. with no port number at `http://yaris.local` after installing the mDNS and port-redirect setup.
Deployment helpers for the app service, hotspot watcher, port redirect, and hardware watchdog are Deployment helpers for the app service, hotspot watcher, port redirect, and hardware watchdog are
in [deploy/](./deploy); see [PLAN.md](./PLAN.md) for the complete Pi setup and hardware notes. in [deploy/](./deploy). For a clean-install walkthrough on a fresh Pi, use
[deploy/readme.md](./deploy/readme.md). See [PLAN.md](./PLAN.md) for the full hardware/project history.
For the remote server (receives trip logs + dashcam uploads), see [server/README.md](./server/README.md). For the remote server (receives trip logs + dashcam uploads), see [server/README.md](./server/README.md).
@@ -160,3 +161,7 @@ bash ~/app/yaris-obd/scripts/diagnose.sh --fix # attempt auto-fix
Checks service state, OBD/UART hardware, disk/DB health, upload backlog, Pi throttling, and Checks service state, OBD/UART hardware, disk/DB health, upload backlog, Pi throttling, and
prints a cheatsheet of recovery commands. Exit code = number of critical issues found. prints a cheatsheet of recovery commands. Exit code = number of critical issues found.
## Hardware photo
![Yaris OBD hardware build](./pics/yaris-obd-hardware.jpg)