ha-vledger
Pre-alpha. Do not install this. It captures a raw log and nothing else yet: no trips, no charging sessions, no consumption, no cost. The log format is decided and will be read by every later version, but the integration has run on exactly one vehicle, the options may change between releases, and there is no support. It is public so that the author can test it through HACS and so that the design can be read. When it is ready for other people, this notice goes away.
A vehicle ledger for Home Assistant. It keeps a raw log of the handful of vehicle states that matter to a ledger — odometer, position, fuel level, state of charge, charging state — and derives from it what the vehicle's own app never tells you reliably: trips, charging sessions, refuellings, consumption and cost. Passively, from whatever integration already exposes the vehicle, without a line of manufacturer-specific code, and without touching anything else the vehicle reports: it is a ledger, not a monitor.
Status: capture works. The integration sets up a vehicle or a charge
point through the UI and writes its raw log — the format, and the
vledger l0 verbs that write, read, validate it and list its gaps, are the
library's. Nothing derives from the log yet: no trips, no sessions, no
metrics, no receipts. Every behaviour described below is the design, held
as requirements in the project's register (ha-vledger-pm); a section is
marked (planned) until it exists.
What it does (planned)
- Captures, losslessly. Every change of a source entity you assign to a role becomes one record in a raw log (L0): JSON Lines, append-only, one stream per vehicle and per charge point, rotated monthly, kept outside the Home Assistant recorder and its retention. Start, stop and heartbeat markers make any capture gap visible; nothing is interpolated across one.
- Derives, deterministically. Trips (between standstills), charging
sessions (from the charging state), refuellings (a fuel rise at unchanged
odometer) and metrics are computed from L0, receipts and configuration
(L1) — the same logic live in Home Assistant and in batch from the
command line, recomputable from scratch at any time. Every derived value
carries a quality flag:
measured,receipt,estimatedorincomplete. - Takes receipts. Price and exact quantity come from you: a refuelling or charging receipt, entered from a notification, a dashboard or an action, matched to the detected event by time. Receipt values beat sensor values; a detected event without a receipt stays visible as unconfirmed.
- Knows your charge points. Home, work, anywhere fixed: position, radius, tariff, optionally a meter. A charge point with a tariff but no meter still yields cost, estimated through a charging loss factor; a tariff of 0 is cost 0. Anything else is a foreign charge and asks for a receipt.
- Reports. Per month, year and rolling period: distance, litres and kWh, fuel and electricity cost, €/100 km per energy carrier, the electric share two ways (energy by heating value, and an estimated distance share), charge cycles and tank-fill equivalents. Fuel consumption is tank-to-tank between any two receipts, corrected by the fuel level sensor, so a tank that is never filled up still gets a figure.
What it is built of
One repository, two packages, one version number (ADR-0002):
src/vledger/ the library and the vledger CLI: all derivation
logic, no Home Assistant, no dependencies;
published to PyPI as `vledger`
custom_components/vledger/ the Home Assistant integration, a shell over the
library: capture, config and options flows,
entities, actions, diagnostics; pins the library
by the same version in manifest.json
tests/ pytest: library tests on L0 fixtures, integration
tests with pytest-homeassistant-custom-component
docs/ design documentation
A vehicle is a config entry; its source entities are assigned to roles
(odometer, position, fuel_level, soc, charging_state, …), and
what the vehicle can do follows from the roles it has. Everything is
configured in the UI; no YAML.
Documentation
| Document | What it is |
|---|---|
| docs/user-guide.md | What a participant types: the vledger command, verb by verb |
| docs/l0-format.md | The raw log's layout, version 1 — the specification a reader of their own files needs |
| docs/glossary.md | The one English spelling of every domain term, and what it means |
| docs/releasing.md | What the person cutting a release does, in order |
Decisions, requirements and the work queue are records in the project's
register, ha-vledger-pm, not prose here.
Installing
Not yet — see the notice at the top. For the author's own test
instances: in HACS, Integrations → ⋮ → Custom repositories, add
https://github.com/michael-lenz/ha-vledger as an Integration, then
install it and restart; or copy custom_components/vledger into the
configuration directory by hand. Either way Home Assistant installs the
library from PyPI (vledger==<version>, pinned in the manifest), so the
version has to be published first — docs/releasing.md.
Then Settings → Devices & services → Add integration → Vehicle Ledger:
the user guide walks the four steps. The library on
its own: pip install vledger, which brings the vledger command.
Developing
pip install -e ".[dev]" # library and CLI
pip install -e ".[dev,ha]" # plus the Home Assistant test stack, for the integration
python -m pytest
ruff check src tests custom_components
The integration's manifest pins a library version that may not be on PyPI yet; Home Assistant skips the install when the package already imports, so a development instance needs the editable install above first.
The ha extra pulls in a full Home Assistant core and its test plugin.
On a Debian or Ubuntu system Python that install can fail to build one of
its transitive dependencies against the distribution's patched
setuptools; a virtual environment (python3 -m venv .venv) does not have
that problem, and is the recommended place for it anyway. Without the
extra, python -m pytest runs the library's tests and leaves tests/ha
out. The library's own tests, the integration's against the oldest and
the newest Home Assistant, and HACS's validation run on every push
(.github/workflows/tests.yml); a tag vX.Y.Z publishes the release
(.github/workflows/release.yml, docs/releasing.md).
Privacy
The position history is personal data. It stays on your instance — nothing is transmitted anywhere — and is redacted from logs and diagnostics, but the default storage path lies under the Home Assistant configuration directory and is therefore part of your backups.
License
BSD-3-Clause — see LICENSE.
Metadata
Release files for vledger 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vledger-0.1.0.tar.gz | 24.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vledger-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.6 kB
Release files / vledger-0.1.0.tar.gz
| Download URL | vledger-0.1.0.tar.gz |
|---|---|
| Size | 24.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e3770b49344bd37b9be9013c50b270fd05b2f87e46e9cabdbe38bd6d2927874
|
|
BLAKE2b-256 checksum How to use checksums |
710170d8e539decf3ee7698ba7eaf3ec426e53f565ee1e6dd8c01a7c2dc8760a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency logRelease files / vledger-0.1.0-py3-none-any.whl
| Download URL | vledger-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8dd79528487a275e72f1a7f056604d65ebe159840db0ed4f4960f4329b42ef0e
|
|
BLAKE2b-256 checksum How to use checksums |
fc5fd96d7992703d23a51c1401b6166af6b51ae3e35fddbf413f4bedcf779579
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency log