diff --git a/FEATURES.md b/FEATURES.md index 162ae1a..b26bf55 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -33,7 +33,7 @@ dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it | FEAT-11 | `SHIPPED` | Hotspot SSID/password settings + 5GHz WiFi role swap | Phase 27 | | FEAT-12 | `SHIPPED` | Log OBD speed before GPS fix (rolling-start capture) | Phase 27 | | FEAT-13 | `IDEA` | Flush uploaded tracking rows from local DB | unassigned | -| FEAT-14 | `IDEA` | Second T3U to replace onboard wlan0 (dual AC radios) | unassigned | +| FEAT-14 | `SHIPPED` | Second T3U to replace onboard wlan0 (dual AC radios) | Phase 29 | | FEAT-15 | `SHIPPED` | Clear DTC codes from the DTC page | Phase 29 | --- @@ -259,21 +259,22 @@ dedicated PLAN.md phase (or fold it into the relevant existing work) and mark it ### FEAT-14 — Second T3U to replace onboard wlan0 (dual AC radios) -- **Status**: `IDEA` -- **Area**: hardware + `deploy/yaris_uplink.py`, `deploy/install_netwatch.sh`, `modules/app_network.py` -- **Phase**: unassigned -- **What**: Owner bought a second TP-Link Archer T3U (RTL8812BU) to replace the onboard - BCM43438 currently serving as the internet uplink (wlan0). Both radios would then be fast - AC1300 T3U dongles — one AP (wlan1, 5GHz) and one uplink (wlan0) — removing the current - tradeoff where away-from-home uploads run over the weak onboard radio. -- **Considerations**: - - Both dongles share the Pi 3's USB 2.0 bus (~480 Mbps total), so two AC dongles can't both - run at full speed simultaneously — but each still far exceeds the onboard radio. - - Power: two AC dongles draw more than onboard + one; verify the 5V GPIO feed holds - (`vcgencmd get_throttled` should stay `0x0` for no undervoltage). - - Interface naming: both radios are USB now, so `wlan0`/`wlan1` may not map predictably — - pin `connection.interface-name` and/or add MAC-based udev rules so AP vs uplink never swap. - - The rtl88x2bu driver is already built; a second identical dongle should be plug-and-play. +- **Status**: `SHIPPED` 2026-08-14 +- **Area**: hardware + `deploy/yaris_uplink.py`, `deploy/install_netwatch.sh`, `modules/app_network.py`, `deploy/90-yaris-uplink` +- **Phase**: Phase 29 +- **What**: Owner added a second TP-Link Archer T3U (RTL8812BU) to replace the onboard + BCM43438 as the internet uplink. Both radios are now AC1300 T3U dongles — `wlan1` (T3U #1) + hosts the 5GHz in-car AP, `wlan2` (T3U #2) carries the uplink (home-wifi + phone-hotspot), + and the onboard `wlan0` is retired to a weak fallback. Removes the old tradeoff where + away-from-home uploads ran over the weak onboard radio. +- **Changes**: `PRIMARY_INTERFACE=wlan2` / `FALLBACK_INTERFACE=wlan0` / `AP_INTERFACE=wlan1` + in `yaris_uplink.py` + `app_network.py`; `install_netwatch.sh` rebinds `home-wifi` + + `phone-hotspot` to wlan2 and recreates the `home-wifi-fb` fallback on wlan0; the NM + dispatcher (`90-yaris-uplink`) now listens on `wlan0|wlan1|wlan2`. +- **Verified**: the second T3U enumerates as `wlan2` (rtl88x2bu) and + `vcgencmd get_throttled` = `0x0` (no undervoltage with both dongles powered). +- **Open item**: interface-name pinning relies on USB enumeration order; if the two T3Us ever + swap ports, `wlan1`/`wlan2` swap — a MAC-based udev/`.link` rule is the robust follow-up. ### FEAT-15 — Clear DTC codes from the DTC page diff --git a/PLAN.md b/PLAN.md index 8125797..e54e46a 100644 --- a/PLAN.md +++ b/PLAN.md @@ -12,14 +12,13 @@ pick up the project without needing prior chat history. - **Board**: Raspberry Pi 3 Model B Rev 1.2, 906MB RAM. Confirmed too weak to run an AI coding agent — all agent-assisted dev work happens on a separate local machine; the Pi is only used for hardware bring-up/testing/deployment via SSH (`yaris@`). -- **WiFi**: Dual-radio setup — **TP-Link Archer T3U (RTL8812BU)** USB dongle as `wlan1` and the - onboard BCM43438 as `wlan0`. **2026-08-12 role swap**: the fast T3U now hosts the in-car AP - ("vroom vroom yaris de course" on 5GHz at 10.42.0.1) for fast phone access (Android dev, video - browsing); the weak onboard radio carries the internet uplink (home WiFi "BuzzBis" + - phone hotspot, static IP 192.168.50.220, gw 192.168.50.1). Both radios active simultaneously. - Tradeoff: away-from-home uploads (dashcam/trip sync) now run over the weak onboard radio — a - background task, accepted by owner. A single radio cannot be AP + client at once, so the - phone-hotspot uplink cannot also live on wlan1 while it hosts the AP. +- **WiFi**: **Dual T3U** setup (2026-08-14, FEAT-14) — two TP-Link Archer T3U (RTL8812BU) + dongles: `wlan1` hosts the in-car AP ("vroom vroom yaris de course" on 5GHz at 10.42.0.1) + and `wlan2` carries the internet uplink (home WiFi "BuzzBis" + phone hotspot, static IP + 192.168.50.220, gw 192.168.50.1). The onboard BCM43438 (`wlan0`) is retired to a weak + fallback. Away-from-home uploads (dashcam/trip sync) now run on a fast AC radio. A single + radio cannot be AP + client at once, so the phone-hotspot uplink cannot live on wlan1 while + it hosts the AP. - **GPS/GSM**: Waveshare **SIM868 GSM/GPRS/GNSS/Bluetooth HAT**. GNSS provides live GPS fixes (confirmed working, ~7 satellites, ~80s cold-start TTFF). GSM/GPRS cellular is **not in use** (no SIM card available); a Huawei **E3372h-153 4G LTE modem** has been purchased as a future diff --git a/app.py b/app.py index e38efef..eb14a65 100644 --- a/app.py +++ b/app.py @@ -131,7 +131,7 @@ def uplink_connect(): return jsonify(error=str(error)), 503 return jsonify(status="connection_requested"), 202 -_HOTSPOT_PROFILE = "Hotspot-local" # wlan0 AP profile name in NetworkManager +_HOTSPOT_PROFILE = "Hotspot-local" # AP profile name in NetworkManager (hosted on wlan1) @app.route('/api/hotspot') diff --git a/deploy/90-yaris-uplink b/deploy/90-yaris-uplink index 3d86591..73084a5 100644 --- a/deploy/90-yaris-uplink +++ b/deploy/90-yaris-uplink @@ -1,7 +1,7 @@ #!/bin/sh case "$1" in - wlan0|wlan1) ;; + wlan0|wlan1|wlan2) ;; *) exit 0 ;; esac diff --git a/deploy/install_netwatch.sh b/deploy/install_netwatch.sh index 3aad479..52457b6 100755 --- a/deploy/install_netwatch.sh +++ b/deploy/install_netwatch.sh @@ -7,15 +7,15 @@ # already exist (see PLAN.md Phase 6). The optional "phone-hotspot" profile is # created through the Settings page. # -# Since 2026-08-12: the fast TP-Link T3U (wlan1) hosts the in-car AP -# ("Hotspot-local"), while the onboard BCM43438 (wlan0) carries the internet -# uplink (home-wifi / phone-hotspot). +# Since 2026-08-14 (FEAT-14): dual T3U — wlan1 (T3U #1) hosts the in-car AP +# ("Hotspot-local"), and a second T3U (wlan2) carries the internet uplink +# (home-wifi / phone-hotspot); the onboard BCM43438 (wlan0) is the fallback. set -euo pipefail REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -WLAN=wlan0 # onboard — internet uplink -WLAN_FB=wlan1 # T3U — uplink fallback -AP_IFACE=wlan1 # T3U — hosts the in-car AP +WLAN=wlan2 # T3U #2 — internet uplink +WLAN_FB=wlan0 # onboard BCM43438 — uplink fallback +AP_IFACE=wlan1 # T3U #1 — hosts the in-car AP sudo systemctl stop yaris-uplink-wait.service 2>/dev/null || true sudo systemctl stop yaris-netwatch.timer yaris-netwatch.service 2>/dev/null || true @@ -28,9 +28,9 @@ sudo install -m 644 "$REPO_DIR/deploy/yaris-hotspot-dns.conf" \ sudo install -m 755 "$REPO_DIR/deploy/90-yaris-uplink" \ /etc/NetworkManager/dispatcher.d/90-yaris-uplink -# Bind the internet uplink to the onboard radio (wlan0) +# Bind the internet uplink to the second T3U (wlan2) sudo nmcli connection modify home-wifi connection.interface-name "$WLAN" -# The in-car AP lives on the fast T3U (wlan1), forced to 5GHz +# The in-car AP lives on T3U #1 (wlan1), forced to 5GHz sudo nmcli connection modify Hotspot-local \ connection.interface-name "$AP_IFACE" \ 802-11-wireless.band a \ @@ -44,8 +44,8 @@ if nmcli connection show phone-hotspot >/dev/null 2>&1; then 802-11-wireless.mtu 1400 fi -# Create wlan1 fallback profile (lower autoconnect-priority so wlan0 wins) -# home-wifi-fb: same SSID as home-wifi but on wlan1 (T3U) +# Create wlan0 fallback profile (lower autoconnect-priority so wlan2 wins) +# home-wifi-fb: same SSID as home-wifi but on wlan0 (onboard) HOME_SSID=$(nmcli -g 802-11-wireless.ssid connection show home-wifi 2>/dev/null || true) HOME_PSK=$(sudo nmcli -g 802-11-wireless-security.psk connection show --show-secrets home-wifi 2>/dev/null || true) if [ -n "$HOME_SSID" ] && [ -n "$HOME_PSK" ]; then @@ -62,7 +62,7 @@ if [ -n "$HOME_SSID" ] && [ -n "$HOME_PSK" ]; then echo "Created home-wifi-fb fallback on $WLAN_FB" fi -# Re-enable wlan0 as a managed (but low-priority) fallback +# Re-enable wlan0 (onboard) as a managed low-priority fallback sudo nmcli device set "$WLAN_FB" managed yes 2>/dev/null || true sudo cp "$REPO_DIR/deploy/yaris-netwatch.service" /etc/systemd/system/yaris-netwatch.service diff --git a/deploy/readme.md b/deploy/readme.md index 900b789..ae2eb6c 100644 --- a/deploy/readme.md +++ b/deploy/readme.md @@ -20,7 +20,7 @@ cd /home/yaris/app/yaris-obd # REQUIRED before netwatch install: # Create/update NetworkManager profiles named exactly: -# - home-wifi (client WiFi → wlan0, the internet uplink) +# - home-wifi (client WiFi → wlan2, the internet uplink) # - Hotspot-local (local AP, shared at 10.42.0.1/24, on wlan1) # See section 4 below for exact nmcli commands. @@ -42,10 +42,10 @@ curl -I http://127.0.0.1/ ## TP-Link Archer T3U (RTL8812BU) driver -This project expects the T3U USB adapter as `wlan1` for the in-car AP (5GHz) -and the onboard radio as `wlan0` for the internet uplink (home WiFi + phone -hotspot). On a fresh Pi, install the RTL8812BU DKMS driver before configuring -WiFi profiles: +This project expects two T3U USB adapters — `wlan1` for the in-car AP (5GHz) +and `wlan2` for the internet uplink (home WiFi + phone hotspot); the onboard +`wlan0` is a fallback. On a fresh Pi, install the RTL8812BU DKMS driver before +configuring WiFi profiles: ```bash sudo apt-get update diff --git a/deploy/yaris_uplink.py b/deploy/yaris_uplink.py index b542907..aed0e84 100644 --- a/deploy/yaris_uplink.py +++ b/deploy/yaris_uplink.py @@ -12,12 +12,12 @@ import uuid PHONE_CONNECTION = "phone-hotspot" HOME_CONNECTION = "home-wifi" AP_CONNECTION = "Hotspot-local" -# 2026-08-12 swap: the fast TP-Link T3U (wlan1) hosts the in-car AP so phones -# get 5GHz AC throughput; the weak onboard BCM43438 (wlan0) carries the -# internet uplink (home-wifi / phone-hotspot), which is background traffic. +# 2026-08-14 (FEAT-14): dual T3U — wlan1 (T3U #1) hosts the in-car AP so phones +# get 5GHz AC throughput; a second T3U (wlan2) carries the internet uplink +# (home-wifi / phone-hotspot); the onboard BCM43438 (wlan0) is only a fallback. AP_INTERFACE = "wlan1" -PRIMARY_INTERFACE = "wlan0" # onboard — internet uplink -FALLBACK_INTERFACE = "wlan1" # T3U — uplink fallback if onboard is absent +PRIMARY_INTERFACE = "wlan2" # T3U #2 — internet uplink +FALLBACK_INTERFACE = "wlan0" # onboard BCM43438 — fallback if T3U #2 is absent STATUS_PATH = "/var/lib/yaris-obd/uplink-status.json" PHONE_KEYFILE = ( "/etc/NetworkManager/system-connections/" @@ -224,7 +224,7 @@ def _ap_client_count(): def check_uplink(): - """Manage internet uplink on wlan0 only. wlan1 AP is never touched.""" + """Manage internet uplink on the uplink interface only. wlan1 AP is never touched.""" current = active_connection() phone_configured = connection_exists(PHONE_CONNECTION) @@ -275,7 +275,7 @@ def check_uplink(): return True return _connect_home_or_idle() - # Phone not configured. Home wifi is the only uplink on wlan1. + # Phone not configured. Home wifi is the only uplink. if current == HOME_CONNECTION: write_status("home_connected_no_phone") return True diff --git a/modules/app_network.py b/modules/app_network.py index 29cc0be..b8f6871 100644 --- a/modules/app_network.py +++ b/modules/app_network.py @@ -9,10 +9,10 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) INSTALLED_HELPER = "/usr/local/bin/yaris-uplink" REPO_HELPER = os.path.join(BASE_DIR, "deploy", "yaris_uplink.py") PHONE_CONNECTION = "phone-hotspot" -# 2026-08-12 swap: onboard (wlan0) carries the internet uplink; the fast -# T3U (wlan1) hosts the in-car AP. -PRIMARY_INTERFACE = "wlan0" -FALLBACK_INTERFACE = "wlan1" +# 2026-08-14 (FEAT-14): dual T3U — wlan1 (T3U #1) hosts the in-car AP; the +# second T3U (wlan2) carries the internet uplink; onboard wlan0 is a fallback. +PRIMARY_INTERFACE = "wlan2" +FALLBACK_INTERFACE = "wlan0" AP_INTERFACE = "wlan1" STATUS_PATH = "/var/lib/yaris-obd/uplink-status.json" diff --git a/readme.md b/readme.md index 56e1f2c..c4ff71c 100644 --- a/readme.md +++ b/readme.md @@ -37,8 +37,8 @@ Dashboard — mobile (390 px) and desktop (1280 px): can be cleared straight from the DTC page. - **Real GPS tracking** — Waveshare SIM868 GNSS HAT with GPIO PWRKEY auto-power-on. Live position plotted on an offline Leaflet map (pre-cached tiles, no internet needed). -- **WiFi hotspot** — fast 5GHz in-car AP on the T3U (wlan1), internet uplink (home WiFi + - phone hotspot) on the onboard radio (wlan0). SSID/password configurable from the Settings page. +- **WiFi hotspot** — fast 5GHz in-car AP on a T3U (wlan1), internet uplink (home WiFi + + phone hotspot) on a second T3U (wlan2); the onboard radio is a fallback. SSID/password configurable from the Settings page. - **Dashcam workflow** — auto-detects any USB dashcam, mounts read-only, browses files before importing. Import one, selected, or all files. Delete individual or all files directly from the dashcam. Verified against real 28GB/87-file hardware. @@ -79,8 +79,8 @@ Dashboard — mobile (390 px) and desktop (1280 px): | Raspberry Pi 3 Model B Rev 1.2 | Web UI host, logger, uploader, and WiFi hotspot | | Waveshare SIM868 HAT | GNSS (GPS) + optional GSM/GPRS uplink, unused Bluetooth | | USB OBD-II adapter | PL2303-based, ELM327-compatible (originally Bluetooth, switched to USB) | -| TP-Link Archer T3U (RTL8812BU) | USB WiFi dongle — AC1300 dual-band. Hosts the 5GHz in-car AP (wlan1) since 2026-08-12 | -| Onboard BCM43438 (wlan0) | Internet uplink (home WiFi + phone hotspot) since 2026-08-12 | +| 2× TP-Link Archer T3U (RTL8812BU) | USB WiFi dongles — AC1300 dual-band. wlan1 hosts the 5GHz in-car AP; wlan2 carries the internet uplink since 2026-08-14 | +| Onboard BCM43438 (wlan0) | Fallback only — was the internet uplink until 2026-08-14 | | USB dashcam | Any brand — detected as generic USB mass storage | | 2013 Toyota Yaris | The patient |