App 2.33.0: set the drive mode from Settings, only in P at a standstill

The owner lifted the read-only rule for the drive mode alone. Settings
has Eco, Normal, Sport, Snow and Custom; the lit button is what the car
reports. A tap reads gear and speed fresh and writes only in P at 0 km/h
(DriveModeWrite, unit-tested; unreadable is a refusal), through a CPM-only
write behind EVHardware's standstill gate, then reads the mode back and
says what the car reports. The wide layout's charging price joined the
battery card so the page still fits. Not tried on the car.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-25 20:02:53 +01:00
co-authored by Claude Opus 5.5
parent 703bdfd2a3
commit ce2ebd7f58
15 changed files with 268 additions and 12 deletions
+8 -4
View File
@@ -35,9 +35,13 @@ Repository: `ssh://git@git.stinnesbeck.com:2222/nils/mg4.git` (remote `origin`),
`secrets.example.yaml` holds `CHANGE-ME` placeholders only. Stage files explicitly, check the
index for changes that are not yours (the owner works in parallel), and scan the staged diff
for secrets before every commit. Never print a token.
3. **Telemetry is read-only.** The app never writes a vehicle setting. The only system setting it
touches is `policy_control`, and only to remove the CarPlay entry the withdrawn full-screen
experiment (2.19.2–2.19.5) may have left.
3. **Telemetry is read-only; the drive mode is the one exception.** The app writes no vehicle
setting except the drive mode (owner's decision, 2026-10-25): from Settings only, a tap by the
driver, only in P at 0 km/h with both read fresh (unreadable means no write), through
EVHardware's standstill gate, and the result shown is what the car reports back
(`DriveModeWrite`). Nothing else gets written, and nothing writes on its own. The only system
setting it touches is `policy_control`, and only to remove the CarPlay entry the withdrawn
full-screen experiment (2.19.2–2.19.5) may have left.
4. **A failed read is not a zero.** Unreadable values are `null`, omitted from payloads and
shown as "—". Sending 0 for SOC tells ABRP the battery is empty.
5. **Fail closed.** Updates (origin, SHA-256, package, signature), credentials, unknown state.
@@ -73,7 +77,7 @@ Repository: `ssh://git@git.stinnesbeck.com:2222/nils/mg4.git` (remote `origin`),
| Consumption / Charging | period totals, daily log, charging sessions and curve |
| Live data | on/off, ABRP API key and user token, upload frequency |
| Server | URL, pairing by QR, ingest token, installation ID (read-only), config import |
| Settings | full screen, voice key, Overview style with the accent colour beside it, the Mascot character (only for that style) (offered only for styles drawn in it, `OverviewStyle.usesAccent`; Retro and Terminal add "Original" for their own palette, `hasOriginal`), tyre unit, battery, charging price, version, update check, install from USB, About |
| Settings | drive mode (Eco, Normal, Sport, Snow, Custom; the lit one is what the car reports; changes only in P at a standstill, `DriveModeWrite`), full screen, voice key, Overview style with the accent colour beside it, the Mascot character (only for that style) (offered only for styles drawn in it, `OverviewStyle.usesAccent`; Retro and Terminal add "Original" for their own palette, `hasOriginal`), tyre unit, battery and charging price (one card on wide screens), version, update check, install from USB, About |
| Logs | signal recorder (`SignalRecorder`/`SignalRecording`: every property and vendor getter via `VendorSurfaceProbe.capture`, again and again for 3 minutes, plus steering-wheel key broadcasts; lists what changed, rarest first; saved to the app and a USB stick; how to find where the car publishes something), update log (every install step, with the platform's words), upload log |
Key classes (`app/src/main/java/com/evsuite/abrp/`): `AbrpUploadService` (foreground service,