# DriverVault A car control & service-tracking system (originally "Car Control Project"). Built incrementally — starting with a **car maintenance tracker** (modeled on `Car Service.xlsx`) and growing toward live integration with the car via a cellular ESP32 device and third-party services (Toyota Connected, EV chargers). ## Architecture All clients communicate with the database **only through the API Server** — nothing talks to PocketBase directly. ``` ┌──────────────────┐ Web App (Vue) ─────▶│ │ Phone App (Flutter)▶│ API Server │────▶ PocketBase Home Assistant ────▶│ (Go, stdlib) │ (10.2.1.10:8027) Car Agent (ESP32) ─▶│ │ └──────────────────┘ ``` | Component | Stack | Status | Docs | |---|---|---|---| | **API Server** | Go (stdlib) | ✅ built, running, verified | [API Server/README.md](API%20Server/README.md) | | **Database** | PocketBase | ✅ running, schema + seed done | — | | **Web App** | Vue 3 + Vite + Tailwind v4 | ✅ full feature set (below) | [Web App/README.md](Web%20App/README.md) | | **Phone App** | Flutter (Android) | ✅ web parity + biometric login | [Phone App/README.md](Phone%20App/README.md) | | **Docker** | Compose (multi-container / all-in-one) | ✅ deployment configs | [Docker/README.md](Docker/README.md) · [Docker-AIO/README.md](Docker-AIO/README.md) | | **Car Agent Device** | ESP32 + SIM7600 (LILYGO TTGO) | 🚧 firmware in progress | [Car Agent Device](Car%20Agent%20Device) | | **Home Assistant Plugin** | — | ⬜ later | — | The Web and Phone apps are at feature parity. ## Features - **Maintenance tracking** — cars, service history (date/odometer + which parts were changed), and a per-car parts catalog, with next-due date/km status from the spreadsheet formulas. - **Technical checks** — the mandatory roadworthiness inspections (przegląd techniczny / MOT / TÜV): result, cost, station and the certificate's valid-until, which overrides the car's interval and drives the next-due date. - **Maintenance log** — workshop visits and repairs outside the routine schedule: type/status, workshop, parts used, labour + parts cost, invoice, warranty-until. - **Fuel tracking** — refills with derived efficiency (average / best / worst consumption, cost per km, price per litre). Consumption is measured between full tanks, so partial fills roll into the next full one. - **Documents** — insurance, registration, road tax and the rest, each with a server-computed renewal/expiry state. - **Reminders** — date- and/or odometer-triggered, one-off or recurring, plus read-only reminders the server derives from documents and service records. - **Attachments** — one optional file (PDF or image) per service record, technical check, maintenance entry, refill, document and part; fetched back through the API Server, never a public URL. - **Accounts** — PocketBase-token login, profile + appearance preferences (theme/locale/date format/currency/font), avatar, email verification, data export/import, and an account-deletion state machine. - **Organizations & roles** — multi-tenant `user` / `admin` / `superadmin` roles; admins manage users within their own organization, superadmins span all. Any user without an organization can create one and becomes its admin. - **Per-user ownership & sharing** — each car has an owner and can be shared with other users as read or write; the UI mirrors the server's access checks. - **Integrations** — per-user connectors under a superadmin → org-admin → user cascade. Built-in today: **Toyota Connected** (read-only vehicle data), the **Anker Solix** V1 EV charger and the **Greencell** HabuDen wallbox (read over the owner's own MQTT broker — no Greencell cloud is involved). **Apprise** joins them as a server-wide connector rather than a per-user one: it hands a message to an Apprise gateway the operator runs, which fans it out to any of the 100+ services Apprise speaks. - **Cars from the manufacturer's own service** — import a car straight off a connected account (MyToyota today), choosing what to pull in, and read everything that service knows about it from a dedicated first tab on the car. Generic over providers: the next manufacturer is one adapter in the API Server. - **EV charging control** — for Anker Solix chargers the owner can start, stop and limit charging from the Charging screen over whichever of three transports their control mode picks: **Anker's own cloud** (commands ride the connection the charger already holds to Anker, so nothing has to be reachable — the mode for a charger on a customer's network), **Modbus TCP** on the local network, or an **OCPP 1.6J Central System** the charger dials back into. - **Translated UI** — the interface reads its text from per-language files (English, Polish, Danish today), with English as the fallback for any untranslated string. See [TRANSLATIONS.md](TRANSLATIONS.md). - **Phone biometric login & app lock** — fingerprint / face sign-in with an app-lock that requires an unlock on relaunch. See the Phone App README. ## Auth model All apps share one auth model: **authentication is PocketBase's own.** `POST /api/auth/login` is proxied to the PocketBase users collection and the client keeps the token PocketBase minted — the API Server does **not** issue its own JWT. Every protected request carries `Authorization: ` (both `Bearer ` and a raw token are accepted) and the server re-resolves it against PocketBase on each call, so a role change or a deletion takes effect immediately. Tokens are stateless, so there is no per-device session list; changing an account's password rotates its token key and invalidates every token already issued. Access to cars/records is gated by per-user ownership and shares; user management requires the admin or superadmin role. Creating an organization is the one management action open to a plain user — it promotes them to admin of the organization they just created. ## Domain (from `Car Service.xlsx`) - **Cars** — one per vehicle (was: one spreadsheet sheet), with spec fields (engine / transmission / differential oil, brake fluid, coolant, VIN, fuel type, build / first-registration dates, …) and configurable service intervals. - **Service records** — date + odometer per service, plus which parts were changed (oil & oil filter, engine air filter, cabin air filter). - **Parts** — per-car catalog of part numbers. Key spreadsheet formulas, reproduced by the API Server on read: ``` Next Service Date = service date + serviceIntervalDays (default 365; Excel: =A+365) Next Service Km = service km + serviceIntervalKm (default 15 000; Excel: =B+15000) ``` Intervals are configurable per car. ## Getting started Bring up the stack in this order — each app's README has the details: 1. **[API Server](API%20Server/README.md)** — configure `.env`, run `setup-pocketbase.mjs`, start the server. This must be running for either app. 2. **[Web App](Web%20App/README.md)** — `npm install && npm run dev` (proxies `/api` to the server). 3. **[Phone App](Phone%20App/README.md)** — `flutter build apk` / `flutter run` with `--dart-define=API_BASE=http://:8080/api`. Or skip all of that and bring the whole stack up with **Docker**, which runs the schema setup itself — see [Docker](Docker/README.md) (PocketBase + API Server + Web App as three containers) or [Docker-AIO](Docker-AIO/README.md) (all three in a single image). ## Layout ``` DriverVault/ ├── API Server/ # Go gateway to PocketBase (the only DB client) ├── Web App/ # Vue 3 + Vite + Tailwind v4 SPA + Go BFF ├── Phone App/ # Flutter (Android) ├── Car Agent Device/ # ESP32 + SIM7600 firmware (LILYGO TTGO T-SIM7600) ├── Home Assistant Plugin/ # later phase ├── Docker/ # Compose deployment (API Server + Web App) └── Docker-AIO/ # single all-in-one image ```