Skip to content

feat(statistics): efficiency in kWh/100 km, period energy and efficiency - #569

Open
joszz wants to merge 5 commits into
mainfrom
feat/energy-efficiency
Open

joszz wants to merge 5 commits into
mainfrom
feat/energy-efficiency

Conversation

@joszz

@joszz joszz commented Nov 7, 2026 •

Copy link
Copy Markdown
Owner

Contains the commit from #556 (the day counter check), so the test-build preview from this PR has both the day counter check and the clearer statistics. #556 is closed in favour of this PR, and nothing merges until the tester on #551 confirms.

Why

The reporter on #551 found the statistics hard to read: "Electric usage per day" with no way to relate it to distance, efficiency only in Wh/km, and a "Since charge" card that shows a distance. Demo mode showed the same problem: its distance came from the trips (186 km in 30 days) and its energy from an unrelated history (about 300 kWh), which reads as 1.6 kWh/km.

What changes

Units

  • Energy per distance is shown as kWh/100 km, or kWh/100 mi in miles, instead of Wh/km and Wh/mi. The API still sends Wh/km.

Statistics

  • DailyStat.DistanceKm: each day's distance off the car's distance-of-the-day counter, read the same way as the energy counter (a finished day's peak, today's rise). No database change.
  • New insights: Energy used (fuel used on a hybrid) and Efficiency (consumption on a hybrid) for the period.
  • Distance in period and the month table's distance now come from the car's own count, falling back to the trips for a car that reports none. Trips are drawn from fixes minutes apart and come out short, and the energy figures pair with the car's count.
  • The energy chart gets an efficiency line on a right-hand axis. A point with less than 5 km of driving gets no efficiency value: the ZS EV counts whole kilometres, so short distances are mostly rounding.
  • The month table gets an Efficiency column.
  • Efficiency pairs only days that report both counters. Parked days count at 0 km, so standby losses are part of the figure.

Dashboard

  • New Efficiency since charge card, off the since-last-charge counters (the pair that held up on the ZS EV in Electric usage per day and Wh/km about 100x too high on MG ZS EV #551). It is on by default for plug-ins and for layouts saved before it existed.
  • "Since charge" is now "Dist. since charge", and "Efficiency" is now "Efficiency today" ("Consumption today" on a hybrid).

Wording (English and Dutch)

  • The chart is now "Energy Used per Day (kWh)", described as what the car's own counter reports, standby losses included, without "Estimated".

Demo

  • DemoHistory builds the history in one pass over a single list of drives: the demo trips for the last five weeks, a generated commute before that. The odometer, day counters, since-last-charge counters, state of charge and overnight charges all come from that pass, so the demo statistics agree with each other and with the trip log's odometer. The live snapshot continues from where the history ends.
  • Demo trips start at a time of day rather than relative to when the server started, which put the "peak drive time" at 02:00. Today is now part of the history. Morning preconditioning fills the "Remote preconditioning" insight.

Checks

  • dotnet test: 1583 total, 0 failed. dotnet format --verify-no-changes is clean.
  • Frontend: vue-tsc --build, 1308 unit tests, oxlint/eslint/stylelint, prettier all pass.
  • Demo mode in Playwright at 1440 px and 390 px: no horizontal overflow, the month table fits at 390 px, and the figures agree (30 days: 196.9 km, 41.2 kWh, 20.9 kWh/100 km; 90 days: 2,070 km, 375.9 kWh, 18.2 kWh/100 km).

Refs #551

🤖 Generated with Claude Code

@joszz joszz added the test-build Publish pr-<number> preview images for testers label Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Preview build pr-569

Images for this pull request are published, built from ad72315 (version 0.15.1-preview.0.12.pr.569, shown in the footer).
Every push here replaces them. Closing the pull request or removing the test-build label deletes them.

Important

Update to the latest release (0.15.0) first if you run an older version, as a normal update. The preview is built on top of it, the database warning on this comment compares with it, and going back means going back to it.
Switch where you always run GarageStack: the same folder, Portainer stack or Unraid container. Compose names the database volume after the folder or stack, so starting from anywhere else runs on a new, empty database.
Don't use docker compose down -v or docker volume prune while testing. A backup first never hurts.

All-in-one or Unraid: change the image to

ghcr.io/joszz/garagestack:pr-569

Docker Compose with the published images (your own compose file with garagestack-api, garagestack-worker and garagestack-frontend): change the tag of those three images to pr-569, then

docker compose pull
docker compose up -d

Docker Compose from a clone of this repository, in the clone's folder on main:

git pull
PREVIEW_TAG=pr-569 docker compose -f docker-compose.yml -f docker-compose.preview.yml up -d

With the bundled database, put --profile bundled-postgres after docker compose, as you do for a normal start.

To pin this exact build rather than follow the pull request, use pr-569-ad72315 as the tag.

Going back: change the image back to the latest release, 0.15.0. latest works too, but it follows main, so it can hold changes that are not released yet, database ones included. From a clone, run docker compose up -d --build in the same folder.

Step by step: Testing a preview build.

joszz and others added 5 commits November 9, 2026 14:13
An MG ZS EV (issue #551) adds 33 to 35 kWh to drivetrain/powerUsageOfDay at
some polls while parked, so a 4 km day read 134 kWh and 47040 Wh/km. Its
powerUsageSinceLastCharge comes out of the same charge status message and
matches the state of charge drop to the hundredth, so it is the reference.

- DailyStatsBuilder compares the two counters per day: their rises within
  runs without a reset, and on a day without a charge the day total against
  what had left the battery since the last charge. DailyStat gains
  SinceChargeTotal (the day off the since-last-charge counter, starting from
  the last reading before the day) and CounterUnbacked.
- utils/energy picks the figure: a plug-in day the API flags falls back to
  the since-last-charge total; a hybrid stays on its day counter.
- The live kWh-today and Wh/km cards hide a day counter that holds more
  than left the battery since a charge that was not today.

Refs #551

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Show energy per distance as kWh/100 km (kWh/100 mi in miles) instead of Wh/km.
- DailyStat carries the day's distance off the car's distance-of-the-day
  counter, read like the energy counter, so the two pair up.
- Statistics: new Energy used and Efficiency insights, an efficiency line on
  the energy chart (right-hand axis), an efficiency column in the month
  table. Distance in period and the month distance come from the car's own
  count, falling back to trips for a car that reports none.
- Dashboard: Efficiency since charge card off the since-last-charge
  counters; Since charge and Efficiency renamed to say what they show.
- Clearer chart and table wording in English and Dutch.
- Demo: one walk over the demo trips (and a generated commute before them)
  drives the odometer, day counters, since-last-charge counters and state
  of charge, so the demo statistics agree with each other; trips start at
  a time of day; today is in the history.

Refs #551

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A test that turns colourful maps on saves the settings store 300 ms later.
On a slow runner that save lands after the next test's localStorage.clear(),
and the next test's store starts with colourful maps on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The branch was rebased onto main after the Spanish locale landed (#568), and es.json lacked the
keys this PR adds, which broke the type-check and the pr-569 image build. Also follows the
renamed English labels (Energy used, Efficiency today, kWh/100 km).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stics

A ZS EV that charged during an 82 km day showed 118.1 kWh and 144.1 kWh/100 km on the
dashboard, while the statistics page showed 17.9 kWh and 21.8 kWh/100 km. The dashboard's own
check on the live counter stands aside for 24 hours after a charge, because the
since-last-charge counter then no longer covers the whole day.

The dashboard now also loads today's statistics row, refreshed with every new status, and takes
its verdict: when the API found the day counter rising past the since-last-charge counter, the
energy today and efficiency today cards show that day's since-last-charge total, as the
statistics do. The live check stays as a fallback until the row arrives and for a reading the
row does not cover yet. Only plug-in cars load it.

Refs #551

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@joszz
joszz force-pushed the feat/energy-efficiency branch from 99fd106 to ad72315 Compare November 9, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test-build Publish pr-<number> preview images for testers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant