# yaris-obd — full build & install guide This is the complete **hardware → software** walkthrough for building a `yaris-obd` unit from fresh parts and getting it running on a freshly flashed Raspberry Pi OS. It assumes you are comfortable with basic Linux (flashing an SD card, SSH, running commands), basic soldering, and basic 12V/5V electronics — but have never touched this particular project before. The end result is a Pi that auto-starts the `yaris-obd` web app on boot and serves it at `http://yaris.local` over the car's own WiFi hotspot, with GPS tracking, live OBD-II data, dashcam import, and background uploads to a self-hosted server. For the project's full phase-by-phase history and hardware bring-up notes, see [`PLAN.md`](../PLAN.md). --- ## 1) Parts list | Part | Purpose | Notes | | --- | --- | --- | | Raspberry Pi 3 Model B | Runs the app, logs data, hosts the hotspot | Pi 3 B is the reference build; a Pi 3B+/4 works too | | Waveshare SIM868 HAT | GNSS (GPS) + optional GSM/GPRS | GSM needs a SIM and 2G coverage (often none in NA); GPS is the part in use | | SIM868 antennas | GSM + GPS reception | Two **separate** antennas — GSM and GNSS each plug into their own u.FL port on the HAT | | USB OBD-II adapter | Reads live vehicle data | PL2303-chip ELM327-compatible (USB). Appears as `/dev/ttyUSB*` | | 2× TP-Link Archer T3U | WiFi — `wlan1` = in-car 5GHz AP, `wlan2` = internet uplink | RTL8812BU chipset, needs a DKMS driver (the installer builds it) | | DS3231 RTC module | Keeps the clock correct with no internet | Optional but strongly recommended; on the I²C bus `i2c-1` | | CR2032 cell | Backup battery for the RTC | Must be **non-rechargeable** type for the ZS-042 board (see below) | | 5V power source | Powers the Pi | Either a quality USB PSU **or** a hard-wired 5V/GND feed to the GPIO header | | USB dashcam | Records video; files are imported over USB | Any brand that enumerates as USB mass storage | | SD card (≥16GB) | Pi boot + app storage | A2/U3 card recommended | | Car | The patient | Reference car: 2013 Toyota Yaris | --- ## 2) Hardware assembly > **Safety first.** Anything mounted in a car must not interfere with pedals, > steering, airbags, visibility, or occupants. Route and secure every cable. > Never do this work while driving. If you are tapping vehicle 12V, fuse the > feed as close to the source as possible. ### 2.1 Raspberry Pi - Fit the SD card after flashing (Section 3). - If you plan to run the Pi without a keyboard/monitor, set up SSH during flashing so you can work on it headlessly. ### 2.2 SIM868 HAT (GPS) The SIM868 HAT stacks on the Pi's 40-pin GPIO header. 1. **Set the UART jumper to `B` (Pi ↔ SIM868).** This is the 3-position jumper on the HAT: `A` = USB↔SIM868, `B` = Pi GPIO↔SIM868, `C` = USB↔Pi console. It must be on **B** or the Pi cannot talk to the module. 2. **Connect both antennas.** The **GPS/GNSS antenna** and the **GSM antenna** go into their **own separate u.FL sockets** on the HAT. A GPS fix is impossible with only the GSM antenna connected — this was the single most common bring-up mistake in the reference build. 3. **PWRKEY.** This HAT revision ships with the "P4" GPIO power-on mod wire already installed (header pin 7 = BCM GPIO4). The app pulses it automatically at boot to power the module chip on. If your board does not have that wire, you must press the HAT's PWRKEY button for ~1–2s after every Pi power-up, or add the mod wire yourself. 4. Run the installer with `--with-sim868` (Section 4) so the Pi frees the full UART for the HAT (`enable_uart=1`, `dtoverlay=disable-bt`, no serial login shell, `hciuart` disabled). Baud rate is **115200**. ### 2.3 DS3231 RTC (recommended) Without an RTC the Pi boots with a wrong clock every time the car has no internet, which corrupts trip timestamps. | DS3231 (ZS-042) pin | Pi GPIO header pin | | --- | --- | | VCC | **Pin 1 — 3.3V** (not 5V) | | GND | Pin 6 | | SDA | Pin 3 (I²C SDA) | | SCL | Pin 5 (I²C SCL) | - **Remove the charge diode** on the ZS-042 board if you fit a non-rechargeable CR2032 — the board's trickle-charge circuit is unsafe for non-rechargeable cells. - If `i2cdetect -y 1` shows nothing at `0x68`, your SDA/SCL are crossed or a joint is cold. A lit LED only means power is present. - Run the installer with `--with-rtc` (Section 4) to add the overlay, disable `fake-hwclock`, and load the `i2c-dev` module. ### 2.4 USB OBD-II adapter - Any PL2303/CH340-based ELM327 USB adapter works. It enumerates as `/dev/ttyUSB0` (or the first available `/dev/ttyUSB*`). - The app auto-detects the port; you can override it later with the `OBD_PORT` env var in the systemd unit if needed. ### 2.5 WiFi dongles (2× T3U) - Plug one T3U into each USB port. The **interface names follow USB enumeration order**, so on a given Pi `wlan1` and `wlan2` are stable only as long as the dongles stay in the same ports. If you ever swap ports, the AP and uplink roles will swap too. - The installer builds the RTL8812BU DKMS driver. On a Pi 3 the two identical dongles are distinguished only by their position, not by MAC — a MAC-based udev rule is a possible future improvement (not required for normal use). - Expected roles: - `wlan1` — hosts the in-car **AP** (5GHz, `10.42.0.1`) - `wlan2` — carries the **internet uplink** (home WiFi + optional phone hotspot) - `wlan0` — onboard radio, kept as a weak fallback only ### 2.6 Power Two valid approaches: - **Simplest:** a good 5V/2.5A+ USB PSU (the official Pi 3 PSU is ideal). Avoid thin cables — voltage drop is the #1 cause of `vcgencmd get_throttled` undervoltage flags. - **Robust for permanent install (reference build):** hard-wire regulated 5V/GND directly to the GPIO header — **red to Pin 2 (5V), black to Pin 6 (GND)** — fed from a fused 12V→5V buck converter (≥3A) or a quality cigarette-lighter USB supply. This bypasses the fragile micro-USB connector. Whichever you choose, verify after install: ```bash vcgencmd get_throttled # 0x0 = no undervoltage, no throttling (what you want) ``` A non-zero current undervoltage/throttling bit means the power feed is inadequate and must be fixed before the unit lives in the car. ### 2.7 Dashcam - Any dashcam that mounts as generic USB mass storage works — the app detects USB storage via `lsblk` and walks it for video files. - **Known manual step:** many dashcams boot into a "select mode" menu (dashcam / mass-storage / webcam) when they sense live USB data lines. To record, the USB data lines must be absent; to import, they must be present. The project does **not** switch this automatically — unplug/replug (or use a data-blocking cable) when switching between recording and importing. ### 2.8 Final in-car placement - Keep the GPS antenna with a skyward view (dash top is usually fine). - Keep the Pi and dongles clear of direct sunlight and away from heater vents. - Strap everything down; a loose Pi near the pedals is a hazard. --- ## 3) Flash Raspberry Pi OS 1. Download **Raspberry Pi Imager** and write **Raspberry Pi OS Bookworm** (Lite is fine) to the SD card. 2. In Imager's advanced options (gear icon) set: - hostname: `yaris` - enable SSH (password or key) - your primary username + password (the installer creates a separate `yaris` service user; this is just for you to log in) - optional: your home WiFi credentials so the Pi is reachable for the install 3. Boot the Pi, find it on your network, and SSH in: ```bash ssh @yaris.local # or fall back to the IP if mDNS isn't working yet ``` --- ## 4) Run the one-shot installer The installer (`deploy/auto_install.sh`) takes a fresh OS from zero to running. It installs packages, creates the `yaris` user, clones the repo, builds the T3U driver, creates the NetworkManager WiFi profiles, and runs every `deploy/install_*.sh` in the right order. ### 4.1 Get the script onto the Pi **Option A — download it directly (recommended):** ```bash curl -fsSL -o auto_install.sh \ https://raw.githubusercontent.com/quoije/yaris-obd/shameless-aislop/deploy/auto_install.sh ``` > Replace `shameless-aislop` with the repo's current default branch if it has > changed since this was written. **Option B — clone the repo and run from inside it:** ```bash git clone https://github.com/quoije/yaris-obd.git cd yaris-obd # the script clones again into /home/yaris/app/yaris-obd; that is expected ``` ### 4.2 Run it The only required inputs are your **home WiFi** and **in-car hotspot** credentials. Pass them through the environment (or let the script prompt you): ```bash sudo -E bash auto_install.sh \ --with-rtc \ --with-sim868 ``` with these environment variables set: ```bash export HOME_WIFI_SSID="MyHomeWiFi" export HOME_WIFI_PSK="home-wifi-password" export HOTSPOT_SSID="yaris-obd" # in-car AP; default is "yaris-obd" export HOTSPOT_PSK="in-car-password" # optional phone hotspot uplink: export PHONE_HOTSPOT_SSID="MyPhoneHotspot" export PHONE_HOTSPOT_PSK="phone-hotspot-password" ``` Fully non-interactive (no prompts) — fails if a required value is missing: ```bash sudo -E bash auto_install.sh --non-interactive --with-rtc --with-sim868 ``` ### 4.3 Flags | Flag | Effect | | --- | --- | | `--with-rtc` | Enable the DS3231 RTC (I²C overlay, disable `fake-hwclock`) | | `--with-sim868` | Enable the SIM868 UART (`enable_uart=1`, `disable-bt`, no serial console, `hciuart` off) | | `--skip-t3u-driver` | Skip the RTL8812BU build (if you're not using T3U dongles) | | `--no-watchdog` | Skip the 10s hardware watchdog | | `--no-app-updater` | Skip the Android APK mirror timer | | `--non-interactive` | Never prompt; error out on missing credentials | | `-h` / `--help` | Print help | Optional env vars also honoured: `GIT_URL`, `GIT_BRANCH`, `YARIS_PASSWORD`, `OWNER_NAME`, `CAR_MODEL`, `DEVICE_NAME`, `YARIS_SERVER_URL`, `YARIS_DEVICE_NAME`, `YARIS_API_KEY`. ### 4.4 What the installer does 1. Installs base packages (`git`, Python tooling, NetworkManager, nftables, avahi, dnsmasq-base, `iw`) and enables NetworkManager. 2. Creates the `yaris` service user (groups: `sudo`, `dialout`, `gpio`, `i2c`). 3. Clones the repo to `/home/yaris/app/yaris-obd`. 4. Applies `--with-rtc` / `--with-sim868` boot-config changes if requested. 5. Builds the RTL8812BU driver (unless skipped). 6. Creates/updates the `home-wifi`, `Hotspot-local`, and optional `phone-hotspot` NetworkManager profiles. 7. Runs, in order: `install_service.sh`, `install_port_redirect.sh`, `install_netwatch.sh`, `install_video_tools.sh`, and (unless disabled) `install_watchdog.sh` + `install_app_updater.sh`. 8. Optionally prefills `config/device.json` and `db/upload_creds.env` from env vars, fixes repo ownership, and creates the writable data directories. ### 4.5 Reboot If you used `--with-rtc` or `--with-sim868`, reboot so the boot-config changes apply: ```bash sudo reboot ``` --- ## 5) Verify After reboot, on the Pi: ```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/ curl -s http://127.0.0.1/api/gps/status ``` Expected: - `yaris-obd.service` is `active (running)` - `yaris-netwatch.timer` is active - nftables redirects port `80` → `5000` - local HTTP on port 80 returns 200/302 - `/api/gps/status` returns JSON (GPS thread alive) From another device on your home WiFi: - `http://yaris.local` From a phone connected to the **in-car hotspot** (`HOTSPOT_SSID`): - `http://yaris.local` — or `http://10.42.0.1` if the phone doesn't resolve mDNS If the T3U dongles don't appear after the driver build: ```bash ip link show wlan1 ip link show wlan2 ``` If `wlan1` is missing, fix the driver first (see Section 9), then re-run `sudo bash deploy/install_netwatch.sh`. --- ## 6) Configure device identity The Pi shows an owner name, car model, device name, and avatar. Either edit the file directly: ```bash sudo nano /home/yaris/app/yaris-obd/config/device.json ``` ```json { "owner_name": "Your Name", "car_model": "Toyota Yaris 2013", "device_name": "My Yaris OBD", "avatar_path": "img/yaris.png" } ``` or open the web UI → **Settings** and manage it there. - **`owner_name`** — top-right of the topbar - **`car_model`** — left sidebar, next to the car icon - **`device_name`** — device identity used for remote-server sync - **`avatar_path`** — avatar image, relative to `static/` (drop your image in `static/img/` and update the path, or replace `static/img/yaris.png`) Restart after editing the file: ```bash sudo systemctl restart yaris-obd.service ``` > **Heads-up:** the local SQLite database filename is derived from `owner_name` > (`db/sql/_.db`). Changing `owner_name` later creates a > new empty database and orphans the old one — rename the old file to match if > you want to keep the data. --- ## 7) Connect to the remote server (optional but recommended) Trip logs and dashcam footage upload to a self-hosted Flask + Postgres server (`server/` in this repo). See [`server/README.md`](../server/README.md) for deploying it. Once the server is up and a device is registered, put the credentials on the Pi either via the web UI (**Settings → Remote server credentials → Test connection → Sync now**) or by prefilling `db/upload_creds.env`: ```bash sudo nano /home/yaris/app/yaris-obd/db/upload_creds.env ``` ```ini YARIS_SERVER_URL = "https://your-server.example" YARIS_DEVICE_NAME = "yaris-2013" YARIS_API_KEY = "your-one-time-key" ``` Then enable **Sync with server** in Settings if you want the server to own the device identity. --- ## 8) Daily use & updates Update the Pi to the latest code: ```bash cd /home/yaris/app/yaris-obd git pull --ff-only sudo bash deploy/install_service.sh # re-deploy the unit + sudoers sudo systemctl restart yaris-obd.service ``` If any `deploy/` files changed, re-run the matching installer(s) (`install_netwatch.sh`, `install_port_redirect.sh`, `install_app_updater.sh`, …). In-car, connect your phone to the hotspot and browse `http://yaris.local`. Dashcam files are imported from the **Dashcam** page; live telemetry is on the **Dashboard**; past drives are under **History**. --- ## 9) Troubleshooting ```bash bash /home/yaris/app/yaris-obd/scripts/diagnose.sh # read-only check bash /home/yaris/app/yaris-obd/scripts/diagnose.sh --fix # attempt auto-fix ``` Common issues: | Symptom | Likely cause | Fix | | --- | --- | --- | | `wlan1`/`wlan2` missing | RTL8812BU driver didn't build | Re-run the driver build from Section 4; check `dkms status` | | GPS never gets a fix | GPS antenna on wrong u.FL / not seated; HAT jumper not on `B`; SIM868 chip not powered | Re-check antennas + jumper; confirm the app pulses PWRKEY (or press the button 1–2s) | | Wrong time after a cold boot | No RTC or RTC not configured | `i2cdetect -y 1` should show `UU` at `0x68`; check wiring (3.3V!) | | `vcgencmd get_throttled` ≠ `0x0` | Weak power feed | Use a better PSU/cable, or hard-wire 5V to GPIO pins 2 & 6 | | Dashcam import hangs | `yaris` lacks passwordless sudo for mount/rm | Re-run `sudo bash deploy/install_service.sh` (installs `yaris-dashcam.sudoers`) | | Hotspot SSID/password changes don't save | `yaris-hotspot.sudoers` missing | Re-run `sudo bash deploy/install_netwatch.sh` | | `yaris.local` not resolving on a phone | mDNS blocked / phone doesn't relay mDNS on the hotspot | Use `http://10.42.0.1` directly | | `pip install -r requirements.txt` fails | Outdated checkout with the concatenated `requests-toolbeltreverse_geocoder` line | `git pull --ff-only` (fixed in current repo) | | SSH drops when NetworkManager is enabled (Bookworm Lite) | NM takes over the interface and has no profile for your current WiFi yet | Run the installer over **Ethernet**, or pre-create the profile before enabling NM; after the run, re-connect to your WiFi | --- ### Manual reference: the installers `auto_install.sh` is just a wrapper around these individual scripts, which you can also run by hand from `/home/yaris/app/yaris-obd`: ```bash sudo bash deploy/install_service.sh # systemd unit + venv + sudoers sudo bash deploy/install_port_redirect.sh # nftables port 80 -> 5000 sudo bash deploy/install_netwatch.sh # uplink watcher + hotspot profiles sudo bash deploy/install_video_tools.sh # ffmpeg for dashcam thumbnails sudo bash deploy/install_watchdog.sh # 10s hardware watchdog sudo bash deploy/install_app_updater.sh # Android APK mirror timer ``` The manual order matters: `install_netwatch.sh` expects the `home-wifi` and `Hotspot-local` profiles to already exist (create them with `nmcli`, or just let `auto_install.sh` do it).