Skip to content

Commit 01863e7

Browse files
malysclaude
andcommitted
docs(readme): align with EVSuite README standard
Add Unstable badge, include_prereleases on Release badge, warning callout, suite section, Part-of-EVSuite and contents; Layout moved under Building; documents as table. Fix scrambled paragraphs in How it works / Configuration and a wrong MIT mention (licence is PolyForm Noncommercial). analysis/CP-040: drop decompiled-sources/apks wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 6aa8fd5 commit 01863e7

2 files changed

Lines changed: 101 additions & 73 deletions

File tree

‎README.md‎

Lines changed: 99 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,63 @@
22

33
[![Tests](https://github.com/malys/EVChargePilot/actions/workflows/tests.yml/badge.svg)](https://github.com/malys/EVChargePilot/actions/workflows/tests.yml)
44
[![Security](https://github.com/malys/EVChargePilot/actions/workflows/security.yml/badge.svg)](https://github.com/malys/EVChargePilot/actions/workflows/security.yml)
5-
[![Release](https://img.shields.io/github/v/release/malys/EVChargePilot?sort=semver)](https://github.com/malys/EVChargePilot/releases)
5+
[![Unstable](https://github.com/malys/EVChargePilot/actions/workflows/unstable.yml/badge.svg)](https://github.com/malys/EVChargePilot/actions/workflows/unstable.yml)
6+
[![Release](https://img.shields.io/github/v/release/malys/EVChargePilot?include_prereleases&sort=semver)](https://github.com/malys/EVChargePilot/releases)
67
[![License: PolyForm Noncommercial](https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue.svg)](LICENSE)
8+
[![Part of EVSuite](https://img.shields.io/badge/part%20of-EVSuite-2f81f7)](https://malys.github.io/EVSuite/)
9+
10+
> ⚠️ **This app is a read-only dashboard, but it is used on a car: never operate it while driving, and
11+
> never rely on it alone for a range or charging decision.** Telemetry may be wrong, delayed or
12+
> unavailable. Read [DISCLAIMER.md](DISCLAIMER.md) before installing. No warranty, no liability.
13+
> MG and MG4 are third-party marks used only to identify compatibility; this independent
14+
> project is not affiliated with or approved by SAIC Motor or MG Motor.
715
816
Read-only live energy dashboard and local trip analyser for the SAIC MG4 head unit.
917

10-
<p align="center">
11-
<img src="artifacts/dashboard-dark-1920x720.png" width="49%" alt="Dashboard, dark">
12-
<img src="artifacts/dashboard-light-1920x720.png" width="49%" alt="Dashboard, light">
13-
</p>
18+
EVChargePilot is **independent**. It reads the vehicle through the shared
19+
[EVHardware](https://github.com/malys/EVHardware) layer and needs no other EVSuite app installed.
20+
21+
## Part of EVSuite
22+
23+
EVChargePilot is one app of [**EVSuite**](https://malys.github.io/EVSuite/), a family of independent,
24+
offline-first apps for the MG4 head unit (Android Automotive OS 9). Each app installs on its
25+
own — pick only what you need. User guides and install instructions:
26+
<https://malys.github.io/EVSuite/>.
27+
28+
Discover the rest of the suite:
1429

15-
> ⚠️ **No warranty, no liability.** Telemetry may be wrong, delayed or unavailable. Never
16-
> use this app as the sole basis for a range or charging decision. See [DISCLAIMER.md](DISCLAIMER.md).
30+
[![EVProfile](https://img.shields.io/badge/EVProfile-settings%20%26%20drive%20profiles-2f81f7?logo=github)](https://github.com/malys/EVProfile)
31+
[![EVTasker](https://img.shields.io/badge/EVTasker-rule%20automation-2f81f7?logo=github)](https://github.com/malys/EVTasker)
32+
[![EVABRPUploader](https://img.shields.io/badge/EVABRPUploader-ABRP%20telemetry-2f81f7?logo=github)](https://github.com/malys/EVABRPUploader)
33+
[![EVLauncher](https://img.shields.io/badge/EVLauncher-home%20launcher-2f81f7?logo=github)](https://github.com/malys/EVLauncher)
34+
[![EVSwipe](https://img.shields.io/badge/EVSwipe-swipe%20shortcuts-2f81f7?logo=github)](https://github.com/malys/EVSwipe)
35+
[![EVHardware](https://img.shields.io/badge/EVHardware-shared%20vehicle%20library-2f81f7?logo=github)](https://github.com/malys/EVHardware)
36+
37+
---
1738

1839
## Contents
1940

41+
- [Screenshots](#screenshots)
2042
- [Overview](#overview)
21-
- [Features](#features)
22-
- [Requirements](#requirements)
2343
- [How it works](#how-it-works)
44+
- [Requirements](#requirements)
45+
- [Features](#features)
2446
- [Trip export formats](#trip-export-formats)
25-
- [Install](#install)
2647
- [Configuration](#configuration)
48+
- [Install](#install)
2749
- [Building](#building)
28-
- [Project layout](#project-layout)
2950
- [Project documents](#project-documents)
3051
- [Security](#security)
3152
- [Contributing](#contributing)
3253
- [Legal](#legal)
3354

55+
## Screenshots
56+
57+
<p align="center">
58+
<img src="artifacts/dashboard-dark-1920x720.png" width="49%" alt="Dashboard, dark">
59+
<img src="artifacts/dashboard-light-1920x720.png" width="49%" alt="Dashboard, light">
60+
</p>
61+
3462
## Overview
3563

3664
EVChargePilot is an EVSuite application for Android Automotive OS 9. It reads typed,
@@ -40,42 +68,6 @@ diagnostic screen works with no network at all; the route planner is the one fea
4068
uses one, with a key the driver supplies, and it carries a route and never vehicle data
4169
(see [SECURITY.md](SECURITY.md) and `analysis/CP-043_network_and_location.md`).
4270

43-
## Features
44-
45-
- Vehicle-reported SOC and range.
46-
- A grouped thermal/climate state block: outside, cabin and evidence-gated battery
47-
temperatures; HVAC, AC, auto, econ and recirculation states; fan level/maximum; and
48-
driver/passenger targets when each signal is available.
49-
- Automatic trip detection plus parked-only manual controls and configuration.
50-
- Distance and duration calculated locally.
51-
- Evidence-gated signed battery power with a static traction/regeneration scale.
52-
- Pack temperature and charging state when exposed by the current firmware.
53-
- Energy and regeneration integration from the shared EVHardware power convention.
54-
- Parked-only, bounded diagnostic/evidence ZIP to an explicitly chosen removable USB volume.
55-
- Atomic, app-private trip history and in-app crash diagnostics.
56-
- Charge on arrival from the head unit's own guidance, with no network and no key.
57-
- A parked-only charging-stop plan: type a destination, and the app answers whether the trip
58-
needs a charging stop and in how many kilometres. It needs an OpenRouteService key you supply
59-
(see [Configuration](#configuration)); without one, every other screen still works.
60-
- On that same plan: what slowing down would change. Where the road ahead is fast, the app
61-
shows what 130, 120, 110, 100 and 90 km/h would save in charge and cost in minutes, and
62-
names the mildest slowdown that removes the charging stop. A second road comes back with the
63-
same request and is compared on distance, time and charge. It never recommends a speed.
64-
- A battery page: the pack's state of health measured rather than declared, how long since its
65-
charge gauge last had a full charge to anchor itself on, what the pack has been subjected to,
66-
and what the last charge cost — points gained, duration, and approximate energy and mean power
67-
where this app watched the whole session. Read-only, like every other screen: no charge limit,
68-
no schedule, no preheat.
69-
70-
Every signal remains best-effort: unsupported or unreadable properties are displayed as `—`,
71-
never zero. Charger data and energy-source attribution remain outside this initial milestone.
72-
73-
## Requirements
74-
75-
- SAIC MG4 head unit running Android Automotive OS 9 or a compatible test device.
76-
- Android API 28 or newer.
77-
- Platform signing for privileged car-property permissions where required by the firmware.
78-
7971
## How it works
8072

8173
EVHardware's `EnergyTelemetryReader` produces one coherent nullable snapshot per second.
@@ -103,12 +95,10 @@ unique temporary file and atomic rename.
10395
Automatic detection is enabled by default. A foreground service owns the sampler so detection
10496
and recording continue when the driver opens another app. On firmware where speed stays
10597
unavailable, ten consecutive misses suspend idle background polling; opening the dashboard
106-
performs a bounded retry. Active trips remain fail-closed and under manual control. The unstable
107-
The unstable build keeps every automatically detected trip with a positive trustworthy
98+
performs a bounded retry. Active trips remain fail-closed and under manual control. The unstable build keeps every automatically detected trip with a positive trustworthy
10899
distance. The shared store still caps history at 200 trips and 2 MiB, discarding oldest
109100
sample tracks before oldest summaries. Each successful save refreshes the local model.
110-
Manual recordings are always kept.
111-
trip's reported duration is the time actually covered by usable samples, not wall clock: a suspended
101+
Manual recordings are always kept. A trip's reported duration is the time actually covered by usable samples, not wall clock: a suspended
112102
sampler adds nothing to duration, distance or energy, so consumption averages compare values
113103
measured over the same interval.
114104

@@ -123,6 +113,42 @@ fresh readable speed at or below 0.1 km/h, runs off the main thread, caps the te
123113
128 KiB, each evidence file at 64 KiB and the ZIP at 768 KiB, then atomically renames a synced
124114
temporary file on USB. No archive copy accumulates on AAOS.
125115

116+
## Requirements
117+
118+
- SAIC MG4 head unit running Android Automotive OS 9 or a compatible test device.
119+
- Android API 28 or newer.
120+
- Platform signing for privileged car-property permissions where required by the firmware.
121+
122+
## Features
123+
124+
- Vehicle-reported SOC and range.
125+
- A grouped thermal/climate state block: outside, cabin and evidence-gated battery
126+
temperatures; HVAC, AC, auto, econ and recirculation states; fan level/maximum; and
127+
driver/passenger targets when each signal is available.
128+
- Automatic trip detection plus parked-only manual controls and configuration.
129+
- Distance and duration calculated locally.
130+
- Evidence-gated signed battery power with a static traction/regeneration scale.
131+
- Pack temperature and charging state when exposed by the current firmware.
132+
- Energy and regeneration integration from the shared EVHardware power convention.
133+
- Parked-only, bounded diagnostic/evidence ZIP to an explicitly chosen removable USB volume.
134+
- Atomic, app-private trip history and in-app crash diagnostics.
135+
- Charge on arrival from the head unit's own guidance, with no network and no key.
136+
- A parked-only charging-stop plan: type a destination, and the app answers whether the trip
137+
needs a charging stop and in how many kilometres. It needs an OpenRouteService key you supply
138+
(see [Configuration](#configuration)); without one, every other screen still works.
139+
- On that same plan: what slowing down would change. Where the road ahead is fast, the app
140+
shows what 130, 120, 110, 100 and 90 km/h would save in charge and cost in minutes, and
141+
names the mildest slowdown that removes the charging stop. A second road comes back with the
142+
same request and is compared on distance, time and charge. It never recommends a speed.
143+
- A battery page: the pack's state of health measured rather than declared, how long since its
144+
charge gauge last had a full charge to anchor itself on, what the pack has been subjected to,
145+
and what the last charge cost — points gained, duration, and approximate energy and mean power
146+
where this app watched the whole session. Read-only, like every other screen: no charge limit,
147+
no schedule, no preheat.
148+
149+
Every signal remains best-effort: unsupported or unreadable properties are displayed as `—`,
150+
never zero. Charger data and energy-source attribution remain outside this initial milestone.
151+
126152
## Trip export formats
127153

128154
The trip history can export one trip or the full bounded ledger without network or storage
@@ -148,19 +174,14 @@ readings are likewise explicit `null`.
148174
Both formats are limited to the history ceiling of 200 trips and 2 MiB per export. The export
149175
directory retains the eight newest generated files so repeated exports cannot grow without bound.
150176

151-
## Install
152-
153-
Install only a signed APK you trust, while the vehicle is parked. Stable releases do not
154-
self-update.
155-
156177
## Configuration
157178

158179
Automatic trip detection is enabled by default. Its switch, and the manual start/stop action,
180+
can be changed only while the vehicle reports zero speed. If speed is unavailable, the controls
181+
fail closed and the dashboard explains why.
159182

160183
Unstable shows the live eco-advice line by default so a fresh install starts learning without a
161184
setup step. Stable keeps that line opt-in. Spoken advice remains opt-in in both channels.
162-
can be changed only while the vehicle reports zero speed. If speed is unavailable, the controls
163-
fail closed and the dashboard explains why.
164185

165186
### Routing key
166187

@@ -240,9 +261,14 @@ Charger records are shown with their data provider and the date the record was l
240261
because a charger dataset is out of date the day it is published and hiding that turns a
241262
suggestion into a promise. User-contributed Open Charge Map data is CC BY 4.0; imported records
242263
keep their original provider's licence, which is why the provider is named on screen next to
243-
each charger. Both licences permit use in this MIT-licensed app as long as the attribution is
264+
each charger. Both licences permit use in this app as long as the attribution is
244265
displayed, and it is.
245266

267+
## Install
268+
269+
Install only a signed APK you trust, while the vehicle is parked. Stable releases do not
270+
self-update.
271+
246272
## Building
247273

248274
With [mise](https://mise.jdx.dev/):
@@ -254,6 +280,12 @@ mise run test
254280
mise run build
255281
```
256282

283+
### Layout
284+
285+
- `app/src/main/` — driver dashboard, lifecycle, presentation and diagnostics.
286+
- `app/src/main/res/` — EVSuite driver interface.
287+
- `EVHardware/` — shared vehicle abstraction, telemetry model, trip maths and storage.
288+
257289
### Emulator profiles
258290

259291
Android has no Automotive API 28 system image, so local validation uses two complementary
@@ -274,19 +306,15 @@ telemetry is the expected fail-safe behaviour, not simulated vehicle data.
274306
Release signing reads `EV_KEYSTORE`, `EV_KEYSTORE_PASSWORD`, `EV_KEY_ALIAS` and
275307
`EV_KEY_PASSWORD`, or their local `gradle.properties` equivalents. Never commit credentials.
276308

277-
## Project layout
278-
279-
- `app/src/main/` — driver dashboard, lifecycle, presentation and diagnostics.
280-
- `app/src/main/res/` — EVSuite driver interface.
281-
- `EVHardware/` — shared vehicle abstraction, telemetry model, trip maths and storage.
282-
283309
## Project documents
284310

285-
- [DESIGN.md](DESIGN.md) — normative EVSuite interface rules.
286-
- [SECURITY.md](SECURITY.md) — capability boundary and disclosure.
287-
- [CONTRIBUTING.md](CONTRIBUTING.md) — development expectations.
288-
- [DISCLAIMER.md](DISCLAIMER.md) — vehicle-safety disclaimer.
289-
- [CHANGELOG.md](CHANGELOG.md) — release history.
311+
| Document | What it covers |
312+
| --- | --- |
313+
| [DESIGN.md](DESIGN.md) | Normative EVSuite interface rules |
314+
| [SECURITY.md](SECURITY.md) | Capability boundary and disclosure |
315+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Development expectations |
316+
| [DISCLAIMER.md](DISCLAIMER.md) | Vehicle-safety disclaimer |
317+
| [CHANGELOG.md](CHANGELOG.md) | Release history |
290318

291319
## Security
292320

@@ -306,4 +334,4 @@ JVM tests for decisions, and on-vehicle confirmation before release.
306334
## Legal
307335

308336
Source-available under the PolyForm Noncommercial License 1.0.0. Commercial use is not
309-
permitted. Not affiliated with, endorsed by or supported by SAIC Motor or MG Motor.
337+
permitted. See [LICENSE](LICENSE) and [LICENSE.md](LICENSE.md).

‎analysis/CP-040_route_source.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ Date: 2026-09-02
55
Decision: **build on the OEM adapter's guidance**, proven on the vehicle 2026-09-04. The
66
network question at the end of this document is a separate one and remains the owner's.
77

8-
Firmware examined: `saicadapterservice_overseas_eh32` (R69 EH32), decompiled sources under
9-
workspace `apks/`.
8+
Interface examined: `saicadapterservice_overseas_eh32` (R69 EH32) runtime service, as observed on
9+
the head unit.
1010

1111
## Verdict in one line
1212

0 commit comments

Comments
 (0)