The all-in-one folder is now Docker-AIO, so -f Docker-AIO/Dockerfile resolves without quoting. Every path that pointed at the old name follows it: the compose build stanza, the documented build commands, and the links from the two READMEs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
140 lines
7.6 KiB
Markdown
140 lines
7.6 KiB
Markdown
# 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 (the phone omits only data
|
|
export/import).
|
|
|
|
## 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) and the
|
|
**Anker Solix** V1 EV charger.
|
|
- **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 API Server runs an
|
|
**OCPP 1.6J Central System**; in own/proxy mode the charger dials back in and
|
|
the owner can start/stop and set limits from the Charging screen.
|
|
- **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: <token>` (both
|
|
`Bearer <token>` 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://<server-ip>: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
|
|
```
|