Mathieu Moran dcca46ec68 style: drop the ID column from the server trip table to match the Pi
The portal's trip list had an extra 'ID' column the Pi's list doesn't
have. Remove it (and its showId data attribute) so both tables render the
same columns: checkbox, Started, km, Time, Max, Odometer, delete.
2026-08-15 17:02:41 -04:00
2026-08-09 19:04:47 -04:00

yaris-obd

A Raspberry Pi 3-based OBD-II, GPS, and dashcam system for a 2013 Toyota Yaris. Reads live vehicle data over USB, tracks position with a SIM868 GNSS/GSM HAT, logs everything locally, and serves a web UI over the car's own WiFi hotspot. The dashboard and pre-cached map work fully offline, while trip data and dashcam footage sync to a self-hosted remote server whenever an internet uplink is available.

rené lévesque bangers i have a dream

Listen on Spotify

Screenshots

Dashboard — mobile (390 px) and desktop (1280 px):

Mobile and desktop dashboard

Features

  • Live OBD-II data — speed, RPM, coolant temp, fuel level, throttle, MIL/DTC via USB ELM327. Automatic reconnects with clear adapter/ECU diagnostics. DTC codes persist across reboots and 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 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.
  • Local video library — browse imported clips with cached thumbnails and upload status. Inline H.264 playback with seeking. Local-only delete. Optional auto-retention after confirmed upload.
  • Remote sync — trip logs and dashcam footage upload to a self-hosted Flask + Postgres server. Dashcam videos stream in resumable 40MB chunks. Independent toggles for trip and dashcam uploads.
  • Remote web portal — login-protected at the server URL. Trip history with CARTO live map and route replay, dashcam archive with inline player, overview stats, device management (create/delete/rotate keys), and server-side device identity sync that hot-reloads on the Pi.
  • Trip history and replay — motion-aware detection (OBD wheel speed primary, GPS displacement fallback). Metric summaries, offline route polyline, play/pause timeline with moving marker and live reverse-geocoded location names. Tap-to-replay on mobile. Captures OBD speed before the first GPS fix so rolling starts aren't lost.
  • Status page — Pi health (temp, RAM, disk, uptime, throttling), service states, uplink/server/ GPS/OBD diagnostics, and quick actions (test server, sync now, reconnect uplink, restart app).
  • Offline-first alerts — notification bell on every page for check-engine, storage pressure, upload backlog, temperature/power faults, and GPS loss while moving. Optional ntfy push.
  • Manual odometer — Pi Settings page accepts a baseline reading; dashboard computes odometer = baseline + trip distance. Synced to the remote server; portal shows read-only value.
  • Device config sync — server-side owner name, car model, display name, avatar path, and sync toggle hot-reload on the Pi without restart. Multi-device management on the portal with create/rotate/delete keys and one-time API-key reveal.
  • Reverse geocoding — /api/geocode uses reverse_geocoder offline (no internet needed), upgrades to Nominatim street-level when online. LRU-cached. Results pre-loaded for trip scrubbing.
  • Android companion app — native Kotlin app in android/ (Phase 28, in progress). Dual-network on the phone: browse + download dashcam clips over the car's WiFi, relay uploads over cellular. Networking gate + dashcam browser/download verified on a Pixel; cellular upload in progress.
  • Offline web UI — Flask, Bootstrap 5, Socket.IO, Chart.js, Leaflet. All assets served locally. Responsive with collapsible sidebar and mobile bottom nav.
  • Headless deployment — systemd service with auto-restart, 10-second hardware watchdog, and nftables port-80 redirect. Deploy scripts in deploy/.

Hardware

Part Notes
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)
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

See PLAN.md for full hardware bring-up notes (SIM868 jumper/UART setup, antenna gotchas, etc.) and the detailed project history.

Getting started

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 app.py

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. Deployment helpers for the app service, hotspot watcher, port redirect, and hardware watchdog are in deploy/. For a clean-install walkthrough on a fresh Pi, use deploy/readme.md. See PLAN.md for the full hardware/project history.

For the remote server (receives trip logs + dashcam uploads), see server/README.md.

Customizing device identity

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, so the car still boots with sensible identity values even when fully offline.

Edit device configuration

Edit config/device.json:

{
  "owner_name": "quoije",
  "car_model": "Yaris 2013",
  "device_name": "Yaris OBD",
  "avatar_path": "img/yaris.png"
}
Field Location Purpose
owner_name Top-right of app topbar Your name/username
car_model Left sidebar (next to car icon) Vehicle model/year
device_name Local settings / remote portal Device identity used by server sync/provisioning
avatar_path Top-right avatar circle Profile picture (relative to static/)

If you edit the JSON file directly, restart the app:

# If running as a systemd service:
sudo systemctl restart yaris-obd.service

# If running manually:
# Ctrl+C and python3 app.py

Changing the profile picture

Option 1: Replace the default image file:

cp /path/to/your/image.png static/img/yaris.png

Option 2: Add your image to static/img/ and update avatar_path:

{
  "avatar_path": "img/my-avatar.png"
}

Important: Username and database filename

The local SQLite database filename is based on owner_name: db/sql/<owner_name>_<car_model>.db (via modules/app_sql.py).

If you change owner_name and already have trip data:

  • The app will create a new database with the new name
  • Your old database remains at db/sql/quoije_Yaris2013.db (orphaned)

To preserve your data:

# Option 1: Rename the database file
mv db/sql/quoije_Yaris2013.db "db/sql/YourName_YourCar.db"

# Option 2: Start fresh
rm db/sql/quoije_Yaris2013.db

Project status

The Pi app, remote server, device sync, and the Android companion app are implemented and verified on real hardware. Phase 25 (road test) ✅, Phase 26 (road-test bug fixes — 13 bugs) ✅, Phase 27 (feature additions — DTC history sync, manual odometer, hotspot settings + 5GHz WiFi swap, trip-history odometer) ✅. Phase 28 (Android companion app) 🚧 in progress — networking gate + dashcam browser/download done, cellular upload queue in progress.

Full phase history and verification notes live in PLAN.md. Open issues in BUGS.md. Feature requests in FEATURES.md.

Diagnostics & recovery

If something goes wrong in the car, SSH in and run:

bash ~/app/yaris-obd/scripts/diagnose.sh        # read-only health check
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 prints a cheatsheet of recovery commands. Exit code = number of critical issues found.

Hardware photo

Yaris OBD hardware build

S
Description
rpi obd app with way less features... yet
Readme MIT
4.6 MiB
Languages
Python 43.5%
Kotlin 21.6%
HTML 15%
JavaScript 13.2%
Shell 5.1%
Other 1.5%