From d4fb4ba3af01855dd1aa658caf6845e1d72a6701 Mon Sep 17 00:00:00 2001 From: Nils Stinnesbeck Date: Sat, 17 Oct 2026 13:51:01 +0200 Subject: [PATCH] Plan the car server (InfluxDB 2, ABRP forwarder, k8s manifests) in SPECS.md Co-Authored-By: Claude Opus 5.5 --- SPECS.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/SPECS.md b/SPECS.md index c06b748..a315240 100644 --- a/SPECS.md +++ b/SPECS.md @@ -7,6 +7,68 @@ what has been changed, and what is still to do. - Upstream: https://github.com/fatihdonmezdev/FatihsMG4 (itself a fork of malys / EVABRPUploader and Leon Kernan / ABRP_Uploader). Credited in the app's About dialog. +## Plan: car server at car.stinnesbeck.com + +The car sends everything to our own server. The server stores it and forwards live telemetry to +ABRP, so the ABRP token lives only on the server, never in the APK. + +``` +car ──live telemetry───▶ car.stinnesbeck.com ──▶ ABRP api.iternio.com/1/tlm/send + ──daily totals─────▶ │ + ──charging sessions▶ ▼ + InfluxDB 2 +``` + +### Server — extend `web/` (Next.js) + +- **Storage: MongoDB → InfluxDB 2.** Rewrite `web/src/lib/mongo.ts` / `data.ts` against one bucket + (tag `installationId` on every point): + + | Measurement | Timestamp | Tags | Fields | + |---|---|---|---| + | `telemetry` | sample time | — | soc, power, speed, lat, lon, heading, elevation, is_charging, is_dcfc, is_parked, capacity, soe, odometer, est_battery_range, batt_temp, cabin_temp, ext_temp, hvac_setpoint, voltage, current, tire_pressure_fl/fr/rl/rr | + | `consumption_daily` | the day, 00:00 UTC | — | km, kwh, hours, socDrop, sohPercent | + | `charging_session` | startedAt | sessionId | endedAt, durationSeconds, energyKwh, gridEnergyKwh, pricePerKwh, totalCost, start/endSocPercent | + | `charging_curve` | point time | sessionId | powerKw, socPercent | + + Same measurement + tags + timestamp overwrites, so the car's retries stay idempotent + (MongoDB used unique indexes for that). +- **New endpoint `POST /v1/telemetry`:** a batch of live samples, ingest-token auth, validated + and bounded like the existing endpoints. +- **ABRP forwarder:** after storing, forward the newest sample to `tlm/send` with `ABRP_API_KEY` and + `ABRP_USER_TOKEN` from the environment. Rate-limited; a failed forward is logged but not + retried, since stale live data is useless to ABRP. Off when the token is unset. +- **Existing endpoints stay:** `PUT /v1/consumption/daily`, `PUT /v1/charging-sessions/:id`, + `GET /v1/consumption/history/:id`, the dashboard and `/v1/health`. +- **Self-hosting:** drop the Vercel assumptions, `output: "standalone"`, a `Dockerfile`, and + `ensureIndexes()` replaced by bucket checks at startup. + +### Car app + +- Restore the live telemetry payload and upload cadence from before `ea8032a` (`TelemetryPayload`, + `UploadCadence`, location access), sending to the server instead of ABRP. +- Server URL and ingest token: open question, see below. +- Generate our own `CONSUMPTION_INSTALLATION_ID`. + +### Image and deployment + +- Image: `git.stinnesbeck.com/nils/mg4-server:`, pushed to the forge's registry + (needs a registry login on the build machine). +- `k8s/` with plain manifests: Namespace, InfluxDB StatefulSet + PVC + Service (cluster-internal), + server Deployment + Service + Ingress for `car.stinnesbeck.com` (TLS), and Secret *templates* + with placeholder values only. +- **Nothing is ever applied to the cluster by us.** Nils applies the manifests. + +### Open questions + +- [ ] Run InfluxDB inside the cluster from our manifests (assumed), or use an existing instance? +- [ ] Ingress class and TLS setup (e.g. cert-manager `ClusterIssuer` name), or an existing wildcard + certificate Secret? +- [ ] Car config: bake the server URL and ingest token into the APK at build time (as upstream + does), or enter them in the app, which restores the settings tab with the config-file import? + In the app keeps the token out of the APK. +- [ ] ABRP API key: the open-source default key from upstream, or our own? + ## To do - [ ] **About dialog link and QR code → https://git.stinnesbeck.com/nils/mg4.**