2026-08-13 18:44:15 +02:00
2026-08-13 17:41:04 +02:00
2026-08-13 18:44:15 +02:00
2026-08-13 17:19:05 +02:00
2026-08-13 18:19:32 +02:00
2026-08-13 17:41:04 +02:00

vw-eu-data-act-prometheus-exporter

A Prometheus exporter for vehicle data from the VW Group EU Data Act Portal (Volkswagen; not supported for Audi/Skoda/SEAT/CUPRA without adjustments).

For each configured VIN, a dedicated background thread logs into the portal, downloads the latest available dataset, and derives Prometheus metrics from it - following the classic multi-target-exporter pattern via a vin label on a shared /metrics endpoint (no Docker, plain systemd deployment).

Features

  • Multiple vehicles (VINs) under one VW account, each with its own scrape-interval timing in the background
  • No persistent state by default: no ZIPs, no JSON, no values are written to disk - everything lives in process memory and is empty again after a restart. Optionally, the JSON extracted from every downloaded dataset - including "_no_content_found.zip" placeholders, if they carry a JSON payload - can be persisted to disk via config.persist_raw_json (see Configuration). ZIP files themselves are never written to disk
  • Fields are only updated when they are present in the current dataset - if a field is missing, the last known value is kept
  • The health metric cleanly distinguishes between "portal ok, but no new data (yet)" (not a failure) and actual failures (login, HTTP, timeout, or parse errors)

Metrics

All metrics carry the vin label; all names carry the configurable prefix (default: vw_eu_data_act_exporter_).

Metric Type Description
mileage_km Gauge Odometer reading
hvsoc_percent Gauge HV battery state of charge in %
driver_present Gauge (bool) Driver detected in vehicle
cruising_range_km Gauge Remaining range in km
hvbattery_temperature_max_celsius Gauge Max. HV battery temperature
hvbattery_temperature_min_celsius Gauge Min. HV battery temperature
charging_state Enum chargingStatus.currentChargeState
charge_power_kw Gauge Current charging power in kW
plug_connection_state Enum Plug connection status
target_soc_percent Gauge Charge target in %
position_longitude / position_latitude Gauge Last known position (only set when both coordinates were present in the same dataset)
position_created_timestamp_seconds Gauge Unix timestamp of the last known position
locked Gauge (bool) Combined lock status of all doors, trunk and hood (only unlocked if at least one component actively reports UNLOCKED)
is_parked Gauge (bool) Vehicle parked
parking_brake_engaged Gauge (bool) Parking brake engaged
driving_mode Enum Active driving mode
next_service_type Enum Next due service type
service_due_in_days Gauge Remaining days until the next service
last_vehicle_signal_timestamp_seconds Gauge Timestamp of the last vehicle signal (carCapturedUTCTimestamp)
uptime_seconds Gauge Uptime of the exporter process
last_successful_scrape_timestamp_seconds Gauge Last scrape with new data
health Gauge (bool) 0 initially and after a failure, 1 once new data has been received at least once
http_requests_total Counter Total number of HTTP requests made to the portal (login + API calls)

Note on enum metrics: The state space (e.g. possible values of drivingMode or chargingStatus.currentChargeState) is compiled best-effort from the sample dataset and comparable projects, and each one includes an UNKNOWN fallback. If an unknown raw value shows up, it is exported as UNKNOWN and additionally logged as WARNING - the state list in vw-eu-data-act-exporter.py (the *_STATES constants) can then be extended.

Installation (systemd)

# 1. Create directory + user (the "prometheus" system user is typically
#    already present if Prometheus itself is installed on this host)
sudo mkdir -p /opt/vw-eu-data-act-exporter

# 2. Copy files
sudo cp vw-eu-data-act-exporter.py config.py requirements.txt /opt/vw-eu-data-act-exporter/

# 3. Virtualenv + dependencies
sudo python3 -m venv /opt/vw-eu-data-act-exporter/venv
sudo /opt/vw-eu-data-act-exporter/venv/bin/pip install -r /opt/vw-eu-data-act-exporter/requirements.txt

# 4. Adjust config.py (VW account, VINs, interval)
sudo nano /opt/vw-eu-data-act-exporter/config.py

# 5. Permissions (config.py contains the VW account password in plain text)
sudo chown -R prometheus:prometheus /opt/vw-eu-data-act-exporter
sudo chmod 600 /opt/vw-eu-data-act-exporter/config.py

# 6. Install systemd unit
sudo cp vw-eu-data-act-exporter.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vw-eu-data-act-exporter
sudo systemctl status vw-eu-data-act-exporter

Configuration (config.py)

Field Meaning
hostName / serverPort Bind address of the /metrics endpoint
exporter_prefix Prefix for all metric names (only [a-zA-Z0-9_:], e.g. vw_eu_data_act_exporter_)
vw_account E-mail + password of the VW account under which all configured VINs are registered
vins List of vehicle VINs to scrape
scrape_interval_minutes Poll interval per vehicle. The portal only delivers new datasets for "continuous" data requests roughly every ~15 min anyway - a shorter interval will not yield fresher data, but will increase the login frequency against the account
persist_raw_json False by default. When set to True, the JSON extracted from every downloaded dataset is written to disk (one file per VIN per scrape), including the JSON extracted from _no_content_found.zip placeholders when they carry one. ZIP files are never written to disk, only the extracted JSON - useful while tuning the field mapping in vw-eu-data-act-exporter.py. Not needed for normal operation
persist_raw_json_dir Directory the raw JSON files are written to when persist_raw_json is enabled. Defaults to $STATE_DIRECTORY (set automatically by the systemd unit's StateDirectory=vw-eu-data-act-exporter, i.e. /var/lib/vw-eu-data-act-exporter), falling back to ./raw_json for ad-hoc/local runs outside systemd

Prerequisite in the portal (one-time, in a browser): connect vehicle -> "Get customised data" -> enable continuous, 15-minute frequency (see the docstring in vw-eu-data-act-exporter.py).

Prometheus integration

scrape_configs:
  - job_name: vw-eu-data-act-exporter
    static_configs:
      - targets: ["127.0.0.1:9109"]

Since the exporter itself polls in the background (it does not hit the portal live on every Prometheus scrape), the Prometheus scrape interval can be independent of, and significantly shorter than, scrape_interval_minutes

  • it will simply repeatedly return the same cached value.

Troubleshooting

  • health stays 0 permanently: check journalctl -u vw-eu-data-act-exporter -f - usually a login failure (wrong password) or no datasets available in the portal yet (see prerequisite above).
  • A single metric is missing entirely: the corresponding field has never been present in any dataset fetched so far (e.g. position_longitude/_latitude, if both coordinates were never delivered at the same time).
  • WARNING ... Unknown enum value: a new, not-yet-listed value for an enum metric - the state is exported as UNKNOWN, extend the list in the source code if needed.
  • Service fails immediately with status=226/NAMESPACE / Failed to set up mount namespacing: usually a stale unit file from before StateDirectory= was introduced (e.g. still using ReadWritePaths=.../raw_json pointing at a directory that was never created). Re-copy the current vw-eu-data-act-exporter.service, run sudo systemctl daemon-reload, and restart - StateDirectory= makes systemd create that directory (with correct ownership) itself, no manual mkdir/chown needed.
S
Description
VW EU Data Act Prometheus Exporter
Readme MIT
75 KiB
Languages
Python 100%