Commit Graph
214 Commits
Author SHA1 Message Date
nilsandClaude Opus 5.5 2879c43e26 App 2.23.1: Retro style also in the accent colour
"Retro (accent colour)" draws the display in the chosen paint colour
and the labels in its light shade; regeneration stays green, a low
battery turns amber. Listed under Retro. Emulator only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 19:51:08 +02:00
nilsandClaude Opus 5.5 d9f6e368cf App 2.23.0: Overview styles Retro and Futuristic; read every 0.2 s
Retro: an 80s vacuum fluorescent cluster with seven-segment digits,
bar graphs and a lit P R N D selector. Futuristic: a hairline HUD with
an animated energy flow between battery and wheel, a turning speed ring
and a power arc. Both show unread values as dashes. The Overview now
reads the car five times a second. Emulator only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 19:32:07 +02:00
nilsandClaude Opus 5.5 c649ff6e28 App 2.22.3: rename the Overview style Dashboard to Gauges
The stored value becomes GAUGES; DASHBOARD still selects it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 19:25:09 +02:00
nilsandClaude Opus 5.5 c6643e7df2 App 2.22.2: gear badge shows P, R, N and D
Codes read on the owner's car with 2.22.1: 1 P, 2 R, 3 N, 4 D. Gear
maps them (unit-tested); other codes show no letter, unread "—". The
temporary gear list on the Logs tab is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 19:10:03 +02:00
nilsandClaude Opus 5.5 16cc2746ef App 2.22.1: gear badge shows only P; Logs list the raw gear codes
The badge said "D" for every gear that was not P, so N and R read as D.
EVHardware now passes on the raw gear code; the badge shows P for 1,
no letter for codes not yet mapped, "—" when unread. The Logs tab lists
each change of the code with time and speed, to match R, N and D on
the car. Emulator only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 16:59:44 +02:00
nilsandClaude Opus 5.5 cd0dfcd612 App 2.22.0: Overview style Cockpit, segmented rings and a power trace
A third Overview style beside Tiles and Dashboard: rings for battery,
power (zero at the top, regeneration anticlockwise in green) with the
speed and gear inside, and 5-minute usage with a tick for the average
since start; below, the power of the last two minutes, the clock,
climate and odometer. Unread values light nothing and show "—"; the
trace leaves gaps (PowerTrace, unit-tested). Emulator only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 16:48:49 +02:00
nilsandClaude Opus 5.5 234a7e1b60 App 2.21.0: Overview style Dashboard, an instrument cluster
Power, speed and battery as gauges and a strip of gear, climate,
clock, usage and battery; Settings picks Tiles or Dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 12:21:58 +02:00
nilsandClaude Opus 5.5 7b557e8372 SPECS: idea, climate energy on the Overview via SAIC's consumption counters
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-24 12:14:14 +02:00
nilsandClaude Opus 5.5 2931b1feed App 2.20.0: lease mileage allowance on the Overview
Vehicle info shows the km allowed by today (40,000 km over four years
from 2023-05-01, evenly per day) and the odometer against it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 22:24:52 +02:00
nilsandClaude Opus 5.5 71aceaa626 App 2.19.9: remove the Foreground apps card from the Logs tab
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 22:20:18 +02:00
nilsandClaude Opus 5.5 e2922e4842 App 2.19.8: charging curve labels clear of each other; Charging tab 35/65
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 22:18:32 +02:00
nilsandClaude Opus 5.5 93e7e4cb63 App 2.19.7: meter AC charging too, while the app runs
A session runs whenever power flows into the pack, AC or DC; gaps the
head unit slept through are dropped as before. Dashboard and server
texts no longer say DC only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 22:07:03 +02:00
nilsandClaude Opus 5.5 e6f8258203 App 2.19.6: remove the CarPlay full-screen switch and the export button
CarPlay's 1920x640 is fixed in Allgo's system app. On start the car
build removes the CarPlay entry from policy_control if the switch was
left on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 22:02:15 +02:00
nilsandClaude Opus 5.5 4c224dcb3b SPECS: CarPlay's 1920x640 is hard-coded in Allgo's system app; ignore dump/
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 21:52:38 +02:00
nilsandClaude Opus 5.5 b6f41079cc App 2.19.5: the installer screen fallback reads the APK
The car refuses the silent session for a non-system app; the fallback
installer screen could not read our FileProvider URI because grants
from the system user are refused. The car build now hands it a file
URI to the verified copy in Downloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 21:48:46 +02:00
nilsandClaude Opus 5.5 66b403acb8 App 2.19.4: Export CarPlay data to the USB stick
Read-only diagnostic for CarPlay's resolution: window, SurfaceFlinger
and display state captured while CarPlay is in front, display-related
properties without identifiers, Allgo's APK and libraries and
CarPlay-named system files, written to the app's folder on the stick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 21:40:08 +02:00
nilsandClaude Opus 5.5 51beea5ed8 App 2.19.3: update log on the Logs tab
Every update and install step, with the platform's own result, kept
across the restart an install causes, so a failed install on the car
can be read off the screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 21:15:44 +02:00
nilsandClaude Opus 5.5 50217aef74 App 2.19.2: Full screen for CarPlay (experiment)
Adds com.allgo.carplay.service to immersive.full in Android 9's
policy_control setting when switched on, removes only that entry when
off. Car build (system user) only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-10-23 20:50:35 +02:00
nilsandClaude Opus 5.5 209a231511 App 2.19.1: Foreground apps diagnostic on the Logs tab
Read-only: recent foreground apps (usage events), open tasks,
policy_control and the status bar height, for finding the CarPlay
package before a full-screen experiment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 20:30:54 +02:00
nilsandClaude Opus 5.5 461f9d5578 k8s/agent-access: a namespace-limited service account and kubeconfig for a coding agent
Read-only by default, optional deploy role; no Secrets, exec,
port-forward or RBAC. Tokens from kubectl create token, time-limited.
Not applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 09:49:20 +02:00
nilsandClaude Opus 5.5 f0f4f57fee App 2.19.0: EVHardware updated from upstream (malys/EVHardware e4e1158)
Three-way merge from b595ccb, the commit Fatih copied, to upstream's
current state; Fatih's vendor reads (tyres, mileage, charge status,
SWI69) stay. LICENSE.md records the base for the next update.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 09:44:00 +02:00
nilsandClaude Opus 5.5 c6e6b3e88e Drop the IntelliJ project files; ignore /.idea/ as a whole
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 09:37:08 +02:00
nilsandClaude Opus 5.5 3d2e63ad22 App 2.18.3: larger Battery value; first-row tiles share one height
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 09:28:39 +02:00
nilsandClaude Opus 5.5 6c89bf587c App 2.18.2: larger values in Overview's Range, Power and Speed tiles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 09:19:45 +02:00
nilsandClaude Opus 5.5 bae56bec2f Server 2.6.1: code field upper-cases and inserts the dash
The phone pages' code field gets one inline script, allowed by its
SHA-256 hash in the CSP; a test checks the served script against the
header. Image pinned by digest in k8s/server.yaml (not applied).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-19 08:19:00 +02:00
nilsandClaude Opus 5.5 31ea4e7d78 README: current tabs, updating, emulator; screenshots of all tabs from 2.18.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 23:42:16 +02:00
nilsandClaude Opus 5.5 496fb821c3 App 2.18.1: every tab fits the car's window without scrolling
Charging and Consumption get two-column wide layouts; Live data and
Settings are tightened (fields beside their buttons, button rows,
16 dp vertical card padding). Checked on the emulator at 1778x640.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 22:11:05 +02:00
nilsandClaude Opus 5.5 dfd8569cfa AGENTS.md, SPECS: work happens on main now
english-translation is merged and deleted, master renamed to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 21:25:27 +02:00
nilsandClaude Opus 5.5 f54e684ae1 Merge english-translation: Nils' MG4 (app 2.18.0, server 2.6.0)
Turns the FatihsMG4 fork into Nils' MG4: an English Android Automotive
app for the MG4 head unit, a Go car server with InfluxDB 2 and Grafana,
Kubernetes manifests, and updates over the air or from a USB stick.
AGENTS.md is the overview, SPECS.md the journal of every change.

App (com.stinnesbeck.nilsmg4, car build .unstable)
- English throughout; all UI text in strings.xml. Renamed with a new
  package ID, NilsMG4-*.apk names, three-part versions; About links to
  git.stinnesbeck.com/nils/mg4 and keeps the upstream credits.
- build-car (Nix flake) signs the car build with the AOSP platform key
  the head unit trusts; nix run .#car-emulator gives a matching Android
  9 emulator.
- Overview, fitting the car's 1778x720 window without scrolling:
  battery, range, range/usage/energy since start, 5-minute averages of
  range, usage, power and speed, vehicle info, tyre pressures in
  bar/kPa/psi. Read every 0.5 s on a background thread; values
  right-aligned with equal-width digits; recuperation as negative usage
  and an infinite range.
- Head unit: full screen (kept with drop-downs and dialogs), voice-key
  double press opens the app, selectable accent colour after the MG4
  paints (Dynamic Red by default), no scroll bars.
- Tabs: Overview, Consumption, Charging, Live data (on/off, ABRP
  credentials, frequency), Server (URL, QR pairing, token, read-only
  installation ID, config import), Settings (display, battery,
  charging price, update check, install from USB, About), Logs.
- Live data to the car server and straight to ABRP; only values within
  the server's ranges; the queue survives restarts; GPS pauses while
  parked and idle.
- Settings can be typed on a phone (QR code, form on the server) or
  imported from a config file, which is deleted afterwards.
- Security: credentials in encrypted storage (moved back after a
  keystore failure), installation ID derived from the head unit.
- Updates: from this repository's pre-releases through the car server,
  or from a USB stick; SHA-256, package and signature checked; the
  installer session ran silently on the emulator.
- Removed: Wi-Fi auto-connect (and its permissions), the floating
  button, upstream's diagnostics.

Server (server/, Go 1.26, replaces upstream's Next.js app)
- Telemetry, consumption chunks and charging sessions in InfluxDB 2;
  idempotent writes; a bad value or time drops only itself.
- Pairing by QR code approved on a phone; paired tokens bound to their
  installation; lockouts and limits per client address.
- Settings from a phone (in memory only, at most 10 minutes, handed out
  once); app releases relayed from the private forge with a read-only
  FORGE_TOKEN. No ABRP forwarding: the car sends to ABRP itself.

Infrastructure (k8s/, plain manifests, applied by hand)
- InfluxDB 2.7.12, the server pinned by digest, Grafana 13.2.3 with
  provisioned Live, Consumption and Charging dashboards (euro),
  Traefik traefik-internal routes.
- Grafana's read-only InfluxDB token is made by an init container at
  each start; the Grafana process never sees the admin token.
- Filled-in secrets only in the gitignored k8s/secrets/secrets.yaml.

Licence
- MIT throughout, like Leon Kernan's ABRP_Uploader (MIT since
  2026-07-29) and the forks in between; LICENSE names every copyright
  holder. EVHardware/ is PolyForm Noncommercial, so the built APK is
  non-commercial. EVProfile's MG4Control lineage is from MG4Control's
  MIT period (checked).

Deploying
1. Fill in k8s/secrets/secrets.yaml from the template (InfluxDB admin,
   ingest token, approval password, read-only FORGE_TOKEN, Grafana
   admin password).
2. kubectl apply -f k8s/namespace.yaml, then
   kubectl apply -f k8s/secrets/secrets.yaml, then kubectl apply -k k8s/
3. Car: install the car build once by hand; after that build-car, then
   publish-car (or copy the APK and .sha256 to a USB stick), then the
   buttons on the Settings tab.

Testing
- App unit tests (stable and car build) and lint pass; server tests
  pass and govulncheck is clean; manifests validate offline.
- End to end in podman: server with InfluxDB (telemetry, pairing, phone
  settings), Grafana with the init-container token; release relay
  against a fake Gitea.
- Emulator (Android 9, 1920x720 and 1778x640): layouts, tabs, accent
  colours, config import, queue restore, USB install.
- On the car: pairing, live values, voice key, full screen, screen
  size. Not yet on the car: direct ABRP sending, Enter on phone, accent
  colours, 0.5 s refresh, over-the-air and USB updates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 21:22:13 +02:00
nilsandClaude Opus 5.5 253c768781 AGENTS.md: an overview for agents; car-emulator in the flake
AGENTS.md still described upstream's EVABRPUploader (GitHub updates,
the old architecture and tabs). It is now the entry point for agents:
what the project is (app, Go server, k8s, EVHardware), the rules
(nothing touches the cluster, secrets, read-only telemetry, null is not
zero, fail closed, honesty), the facts confirmed on the car, the app's
structure and UI conventions, how to build, test, publish and install,
and which document holds what. SPECS.md stays the journal.

The Android 9 test emulator, so far a file under the ignored build/,
is now reproducible: nix run .#car-emulator creates an AVD at
1920x720/160 dpi with the AOSP image that shares the car's platform key
and starts it on port 5560. Checked from scratch: the car build
installs as the system user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 21:12:41 +02:00
nilsandClaude Opus 5.5 69d284f81b App 2.18.0: install from a USB stick
Settings -> App -> "Install from USB stick" (car build only). It looks
in the top folder of every mounted volume (found from the app's own
folder on it, since the head unit has no file picker) for
NilsMG4-unstable-<version>.apk, takes the newest one newer than the
installed version, checks it against its .sha256 sidecar and the
package name, and installs it with the same PackageInstaller session
as the over-the-air update. The stable build gets a stub and no button.

Tested on the emulator: 2.18.0 installed a 2.18.1 from the storage's
top folder without a confirmation, as the system user, so the OTA
install step should not need one either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:59:45 +02:00
nilsandClaude Opus 5.5 0fd024cc2e SPECS: done-log entry for app 2.17.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:53:21 +02:00
nilsandClaude Opus 5.5 5a82fe3dc1 App 2.17.5: Server tab fits; installation ID is read-only
- The "Your private connection" card is gone; its text was out of date
  (the ABRP credentials are no longer on the server).
- Import from file moved next to Save and Test, in one row.
- The installation ID is shown as text instead of an editable field:
  it is derived from the head unit, and changing it by hand only risked
  splitting the history. A config file can still carry an older one
  over, as before.
- The page fits the car's 1778x640 window without scrolling (checked
  on the emulator), and the subtitle no longer says the server passes
  data on to ABRP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:53:05 +02:00
nilsandClaude Opus 5.5 5ead905e5f App 2.17.4: the panel is called "Vehicle info"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:37:16 +02:00
nilsandClaude Opus 5.5 224840bde2 App 2.17.3: "Odometer and climate" instead of "Energy and temperature"
The Overview panel's title came from upstream, where it also showed
pack energy and temperatures. The MG4 publishes none of those, so the
panel only holds the odometer and the climate setpoint; its title now
says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:35:43 +02:00
nilsandClaude Opus 5.5 d4bb502026 App 2.17.2: Wi-Fi auto-connect removed
Upstream kept the head unit on the driver's phone hotspot by re-joining
a saved network every few minutes. This car's head unit has its own
connection and the Wi-Fi is not used, so the feature goes entirely:
WifiAutoConnect, its call on the service tick, the preference key, and
the ACCESS_WIFI_STATE / CHANGE_WIFI_STATE permissions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:34:05 +02:00
nilsandClaude Opus 5.5 851a4a34d4 App 2.17.1: tidier Settings and Logs
- Settings: the Wi-Fi and saved-networks cards are gone, and the rest
  sits in three columns (display and steering wheel | battery |
  charging price and app) instead of one tall column. The background
  Wi-Fi auto-connect stays on, without a switch.
- Logs: only the upload log. The steering-key reports, the car-colour
  probe and the screen line answered their questions and are removed,
  with their code (CarColorProbe, the key-report log) and strings.
- README lists the current tabs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:32:01 +02:00
nilsandClaude Opus 5.5 8d3eb80f66 App 2.17.0: speed average, compact top bar, About in Settings
- "Speed, 5-min average" card under Speed: time-weighted mean speed,
  standing included, from the same samples as the other averages.
- The top bar is one compact line (title and subtitle side by side).
  Version, update check and About moved from it to an App card on the
  Settings tab.
- The Overview no longer scrolls in the car's window: checked on the
  emulator at 1778x640, the layout height the car reports, after
  trimming the page's padding and the tyre card's height.
- The capacity hint says "Overview" instead of "Vehicle tab".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:26:02 +02:00
nilsandClaude Opus 5.5 79bcfa05f6 App 2.16.4: drop-downs that keep full screen
Back to drop-downs for upload frequency, tyre pressure unit and accent
colour, as Material exposed dropdown menus instead of Spinners. A
Spinner's list is a focusable window of its own without the
full-screen flags, so the car showed its bars while it was open; an
exposed dropdown's list leaves the focus with the activity, so the app
stays full screen. Styled like the other input fields, with full-height
rows. Replaces the buttons of 2.16.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:11:25 +02:00
nilsandClaude Opus 5.5 f614ab08be App 2.16.3: full screen stays with drop-downs and dialogs
Opening a drop-down or a dialog brought the car's bars back until it
closed: each is a window of its own, and the system shows the bars when
a window without the full-screen flags takes focus.

- The drop-downs (upload frequency, tyre pressure unit, accent colour)
  are now single-choice buttons on the page: no extra window, one tap
  instead of two, full touch targets, the choice in the accent colour.
- Dialogs (About, update, pairing, phone settings, trip reset, date
  picker) are shown unfocusable, given the activity's full-screen
  flags, and only then allowed focus. None of them takes typing, which
  an unfocusable window would block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 20:05:26 +02:00
nilsandClaude Opus 5.5 98ec3f3fcf Docs: the car's screen is 1920x720 at 160 dpi; no colour property
Read on the car with 2.16.2: panel 1920x720 px at 160 dpi, app window
1778x720 px (the car's own sidebar takes the rest), so EVProfile's
1280x480 (1920x720 at 240 dpi, in dp) does not apply here. The colour
probe found only ro.build.mtk2712.vehicle_type = AS28: the paint colour
is not among the system properties. FIRMWARE.md, mise.toml and
SPECS.md updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:56:57 +02:00
nilsandClaude Opus 5.5 bfa33d51bd App 2.16.2: show the car's screen size; display figures documented
The MG4's display is given as 1920x720 (this project), 1280x480
(EVProfile's README) and a 1778x720 app window (upstream). 1280x480 is
exactly 1920x720 px at 240 dpi expressed in dp, so the figures may
describe one panel at different densities, which this platform lets be
changed per app.

The Logs tab's new SCREEN line shows the panel's pixels and density and
the app window in px and dp, to settle it from the car. FIRMWARE.md
lists the three figures and what the emulator shows at 240 dpi;
mise.toml, README and SPECS.md no longer state 160 dpi as fact for the
car.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:50:24 +02:00
nilsandClaude Opus 5.5 c2c0640672 LICENSE.md: EVProfile's upstream licence is settled
EVHardware's notes call the licence of EVProfile's upstream unresolved.
Checked: malys/EVProfile is MIT, forked from SliDeeN/MG4Control and last
merged from it on 2026-08-02. MG4Control is MIT up to 2.6.5
(2026-08-05) and GPL v3 from 2.6.6 (2026-09-02), with the earlier
versions staying MIT, so the code EVProfile took is from the MIT
period. Recorded with links; not an audit of every EVHardware line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:41:12 +02:00
nilsandClaude Opus 5.5 a293a0fa94 Licence: the original is MIT; EVHardware is noncommercial
Leon Kernan's ABRP_Uploader has carried the MIT Licence since
2026-07-29 (lkernan/ABRP_Uploader commit 75d8f2bc), so the inherited
"no licence upstream, status unresolved" notes no longer hold.

- LICENSE: MIT, now naming every copyright holder in the fork chain
  (Leon Kernan, EVABRPUploader contributors, FatihsMG4 contributors,
  Nils Stinnesbeck).
- LICENSE.md: rewritten. The repository is MIT except EVHardware/,
  which is PolyForm Noncommercial 1.0.0; the app links it into the APK,
  so the built app is non-commercial. EVHardware's own caveat about
  EVProfile stays with it.
- README, AGENTS.md, CONTRIBUTING.md and SPECS.md say the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:38:21 +02:00
nilsandClaude Opus 5.5 c71fa4504e App 2.16.1: Overview values every half second
The Overview read the car every 2 s, on the main thread. It now reads
every 0.5 s on a background thread (one reader; a read still running
makes the next tick skip rather than queue) and shows the values on the
main thread. The consumption and charging trackers stay on the 2-second
tick with the newest reading: they integrate over time, and the
charging tracker writes its session to storage on every sample.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:32:50 +02:00
nilsandClaude Opus 5.5 9226616261 Grafana's read-only InfluxDB token is made automatically
The read-only token for Grafana needed a manual influx command and a
Secret. InfluxDB generates every token but the admin one and ignores a
chosen value (tested on 2.7.12), so it cannot be preset in a Secret.

Instead an init container in the Grafana pod creates it at every start
with the admin token, deletes the one from the previous start, and
writes only the read-only token to a memory-backed volume; the
provisioned datasource reads it with $__file{/run/influx/token}. The
Grafana process never sees the admin token. The grafana-influx Secret
is gone from the template and the README.

Tested in podman: InfluxDB 2.7.12, the script run twice as the Grafana
user (the old token is replaced, not piled up), and Grafana 13.2.3
reporting the datasource healthy with the file-based token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 19:05:58 +02:00
nilsandClaude Opus 5.5 e5549dddb0 App 2.16.0, server 2.6.0: over-the-air updates from our own repository
The car updates itself again, from this fork's own releases, while the
repository stays private:

- publish-car (flake) creates the pre-release car-<version> on the
  forge and attaches the APK and its .sha256. It needs a forge token
  that may write releases, from ~/.config/nilsmg4/forge-token or
  $FORGE_TOKEN; it is sent in a header and never printed.
- The server relays releases and attachments (/v1/app/releases,
  /v1/app/assets/...), read with a read-only FORGE_TOKEN from its
  Secret, GitHub-shaped with download URLs back at itself. Redirects
  away from the forge are not followed; off (404) without a token.
- The app asks its server with its own paired token, allows exactly
  the server's host, downloads the APK itself instead of through the
  DownloadManager (so the token stays in the app), verifies SHA-256 and
  package name, and tries a PackageInstaller session (it may install
  silently as the system user) before falling back to Downloads.

OTA.md is rewritten for this flow; the k8s and server READMEs explain
the new token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 18:08:08 +02:00
nilsandClaude Opus 5.5 f88249427f App 2.15.0: queued live data survives restarts
Unsent live samples were kept in memory only, so a reboot or a killed
process during a dead spot lost them. The queue is now saved to
files/telemetry_queue.json with AtomicFile, at most every 5 minutes and
only after a change (the flash is not written every 15 s), and at once
when the service stops; it is restored, oldest first and within the
2000-sample cap, when the service starts. A damaged file restores
nothing rather than failing. Tested on the emulator across a reboot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 17:56:25 +02:00
nilsandClaude Opus 5.5 f63f48131e App 2.14.4: all UI text in strings.xml
The Charging, Consumption and Settings labels, toasts, the trip-reset
dialog, the charging and Wi-Fi states, the daily summary and the "—"
placeholder move from layouts and code into strings.xml; lint now
reports no hard-coded text. Upload-log entries stay in code, as log
text. No visible change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 17:50:55 +02:00
nilsandClaude Opus 5.5 29064cf8db Translate the remaining French and Turkish
mise.toml, the comments in app/build.gradle (corrected where they no
longer described the build: the car build is signed by build-car, and
the updater reads the version from build-car's file name), OTA.md's
message table (now the updater's current English messages), the Turkish
messages quoted in CHANGELOG.md and OTA.md (glossed in English), two
test assertion messages, an icon comment, and the ignition-state comment
in EVHardware.kt. The vendored EVHardware library still has about 120
half-French comment lines; noted in SPECS.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
2026-10-18 17:45:56 +02:00