Skip to content

JustChr/BavarianData

Repository files navigation

BavarianData logo

BavarianData: Connect Home Assistant to BMW CarData

Bring your BMW's live data into Home Assistant — straight from BMW CarData, no third-party cloud in between.


BMW CarData is BMW's own telematics service: an MQTT stream that pushes vehicle data in real time and a REST API for on-demand snapshots. This integration talks to both directly, using your personal BMW client ID. There is no intermediate server and no MyBMW screen-scraping — Home Assistant is the only client.

Every descriptor BMW sends becomes a native entity. A parked charging session, a door left open, tyre pressures, the 12 V battery — each surfaces as a sensor or binary sensor with a proper device class, unit, and (where BMW provides one) a set of translated states. The integration also ships a Lovelace card and a cached vehicle image so a usable dashboard exists out of the box.

Bundled Lovelace card showing a BMW i5 eDrive40 with charge level, range, charging status and odometer

Security & closures card with a top-down car diagram, anti-theft alarm armed and all closures closed    Tyre pressure card showing all four tyres at 290 kPa on a top-down car diagram

Status — experimental. This is a spare-time project, verified against a limited number of vehicles and Home Assistant versions. Expect rough edges and avoid wiring it into safety-critical automations. Track main; other branches may be broken at any time.

How it works

  • Streaming — the integration holds one MQTT connection to BMW's CarData broker and refreshes your OAuth tokens on its own. Whatever descriptors you enable in the BMW portal arrive as they change; each maps to an entity.
  • REST snapshots — some data (basic vehicle info, charging history, tyre diagnosis, the vehicle image, …) isn't streamed, so the integration fetches it on demand or on a schedule.
  • Quota-aware — BMW caps the REST API at 50 requests per 24 h. The integration tracks and enforces this itself, and every manual service call counts against it.

Requirements

  • A BMW account with a vehicle that supports CarData.
  • CarData API and CarData Streaming subscribed in the BMW portal, and a client ID generated for this integration.
  • Home Assistant 2024.6 or newer.

It helps to skim BMW's CarData documentation once before starting — the portal steps below mirror it.

Step 1 — Set up BMW CarData in the portal

Do this before adding the integration. The CarData portal isn't offered in every market, but the client ID it produces is account-wide, so you can complete the setup from any supported region and use it everywhere.

Open the vehicle overview and pick CarData:

English German Austrian
BMW vehicle overview Fahrzeugübersicht Fahrzeugübersicht
Mini vehicle overview Fahrzeugübersicht Fahrzeugübersicht
  1. Select your vehicle and open BMW CarData / Mini CarData.
  2. Generate a client ID.
  3. Give the client both scopes — cardata:api:read and cardata:streaming:read — and authorize it. If the portal throws a scope error, reload, add one scope, wait ~30 s, then add the second.

That's all you need here. Don't tick anything under Data Selection yet — which descriptors to stream is chosen from inside Home Assistant after install (Step 4), which generates a snippet tailored to the clusters you pick. The client ID is account-wide, so it covers every vehicle on the account.

Step 2 — Install

Via HACS as a custom repository:

  1. HACS → Custom repositories → add this repo, category Integration.
  2. Install BavarianData: Connect Home Assistant to BMW CarData.
  3. Restart Home Assistant.

Step 3 — Add the integration

  1. Settings → Devices & Services → Add Integration → BavarianData: Connect Home Assistant to BMW CarData.
  2. The first screen recaps the portal setup and asks for your client ID.
  3. Home Assistant shows a link and a code. Open the link, sign in, and approve the device on BMW's site. When BMW accepts the approval, the dialog continues on its own — nothing to click in HA. If the code times out, press Submit for a fresh one and try again. BMW's authorization backend is sometimes flaky and can report "access denied" even though your login clearly worked; if that happens, follow Onboarding fails with "access denied" in Troubleshooting — it's a known BMW-side quirk with a reliable workaround.
  4. Choose which data to stream. The moment authorization succeeds, setup moves straight to the cluster picker (see Step 4) — no separate trip to Configure. Until you finish it, no descriptors are selected in the portal, so no MQTT data will arrive.

If BMW later invalidates the token, run Configure → Re-authorize with BMW. Removing and re-adding the integration with the same client ID also works — the previous entry is cleaned up automatically.

Step 4 — Choose which data to stream

BMW only streams the descriptors you tick under Data Selection in the portal, and it offers no API to set that selection — it is portal-only. Rather than hand-picking hundreds of technical fields, the integration builds the selection for you. These screens appear automatically at the end of Step 3:

  1. Pick the clusters you want (Electric vehicle, Vehicle status, Tire data, …). The defaults are a sensible starting set; the choice is remembered and the picker re-opens pre-filled next time.
  2. The next screen shows a browser-console snippet generated for exactly those clusters. Copy it.
  3. In the portal, open Data Selection (Datenauswahl ändern) and click Load more until every field is listed. Open the browser console (F12 → Console), paste the snippet, and press Enter. It ticks only the checkboxes belonging to your chosen clusters — leaving any other selections untouched — and logs how many it matched.
  4. Save the selection in the portal, then press Submit in Home Assistant to finish. Repeat the portal step for each vehicle.
  5. Trigger something in the MyBMW app (lock/unlock) to nudge the car into sending its first update.

Re-run this any time from Configure → Choose streamed data to widen or narrow the stream. Requesting per-descriptor streaming scopes instead of a portal selection is rejected by BMW — see docs/reference/stream-scope-investigation.md. The full field-per-cluster breakdown lives in docs/reference/telematics-fields.md.

Extrapolated state-of-charge helpers need the Electric vehicle cluster in the stream — specifically the descriptors vehicle.drivetrain.batteryManagement.header, vehicle.drivetrain.batteryManagement.maxEnergy, vehicle.powertrain.electric.battery.charging.power, and vehicle.drivetrain.electricEngine.charging.status.

Entities

  • Each VIN becomes its own device.
  • Streamed descriptors become sensors and binary sensors, named from a curated English title set (tools/curated_titles.json, baked into the catalogue and the HA translations). German names ship too; open an issue or PR if a name looks off.
  • Numeric fields get sensible device classes; distances use device_class: distance, and odometer/mileage uses state_class: total_increasing so long-term statistics work.
  • Every entity exposes its source timestamp plus its catalogue cluster and category as attributes — the Lovelace card uses these to group values regardless of the user's HA language.
  • Each VIN also gets an image entity holding BMW's rendered picture of the car. It's cached and survives restarts, so it doesn't burn quota on every boot; refresh it manually with bavariandata.fetch_vehicle_image.

Lovelace card

A custom BMW CarData Card is bundled and registered automatically — no dashboard resource to add by hand. Pick it from the card gallery to open a visual editor, or write YAML directly.

Overview — the vehicle render, a state-of-charge ring (blue while charging), remaining range, charging status, and a grid of key metrics. With the integration installed, the minimal config auto-discovers the car:

type: custom:bmw-cardata-card

Pin a specific vehicle with device: (device id) or vin:. Optional entity overrides: title, image, soc, range, charging, target_soc, time_to_full, odometer, plug.

Single cluster — set cluster: to list every value in one catalogue cluster. Use one card per cluster:

type: custom:bmw-cardata-card
cluster: electric   # electric · status · tire · usage · events · basic · contract · metadata · other

Tire pressurescluster: tire draws a top-down car with each tire coloured by pressure vs. its target (green OK, amber high, red low) and the readings beside each wheel:

type: custom:bmw-cardata-card
cluster: tire

Security & closurescluster: closures shows doors, windows, hood, trunk, sunroof, the central lock and the anti-theft alarm on the same car. Open doors highlight red, open windows/sunroof amber, and a central padlock reflects the lock state; a badge summarises the worst-case status and every part taps through to the underlying entity. Parts the vehicle doesn't report are simply omitted:

type: custom:bmw-cardata-card
cluster: closures

If the card doesn't show up after an update, hard-refresh the browser.

Services

Each service is available in Developer Tools and as a button in the integration's Configure menu. Every call spends one of your 50 requests / 24 h.

Service What it fetches
bavariandata.fetch_telematic_data Current contents of a VIN's telematics container.
bavariandata.fetch_vehicle_mappings Vehicles linked to the account and their PRIMARY/SECONDARY status.
bavariandata.fetch_basic_data Static vehicle metadata (model, series, …).
bavariandata.fetch_charging_history Charging sessions (paginated; optional from / to).
bavariandata.fetch_tyre_diagnosis Smart-maintenance tyre diagnosis.
bavariandata.fetch_location_charging_settings Location-based charging settings (paginated).
bavariandata.fetch_vehicle_image Vehicle render (updates the image entity).

Troubleshooting

  • Onboarding fails with "access denied" / "declined" even though BMW confirmed your login? This is flakiness in BMW's device-authorization backend, not the integration — the flow can return access_denied ("The user has declined authorization") even though you never saw a consent page and the login clearly worked. It can take a few attempts; this sequence has worked reliably (multiple times) for others:

    1. Open a fresh incognito/private browser window.
    2. Go to the My BMW / CarData portal manually — do not use the pre-filled complete link, and strip any ?user_code=… from the URL.
    3. Sign in, open Authenticate device ("Gerät authentifizieren"), then type the user code by hand (make sure no "incorrect code" banner appears) and approve.
    4. Back in Home Assistant, if the code timed out meanwhile, press Submit for a fresh code and repeat.
    5. Still failing after several tries? Delete the client in the BMW portal, create a new one (tick both subscriptions), and redo auth with the new client ID.

    BMW support for persistent cases: bmwcardata-b2c-support@bmwgroup.com

  • Debug logging is off by default. Turn it on in Configure → options (debug_log) and reload. It's verbose and can include vehicle data such as GPS and VIN, so leave it off unless you're chasing a problem.

  • No data arriving? Make sure you completed Step 4 — descriptors must be ticked and saved in the portal's Data Selection — then trigger a lock/unlock in the MyBMW app to prompt an update.

  • Only one stream per account (GCID) — BMW allows a single concurrent streaming client, so no other tool can be connected at the same time.

  • Read-only — CarData cannot send commands, so this integration can't lock, precondition, or otherwise control the car.

Contributing & support

  • Bugs in the integration → Issues.
  • BMW-side registration trouble, setup help, or general questions → Discussions.

The descriptor catalogue, metadata, translations, and reference docs are all generated from BMW's exports by the pipeline in tools/ — see tools/README.md before hand-editing any generated file.

Credits & license

Released under the MIT License. This integration began as a continuation of the public-domain bmw-cardata-ha by JjyKsi; that project carried no licensing restrictions, and the original author is credited in NOTICE out of respect for their work.

"BMW", "Mini", "Rolls-Royce", and "CarData" are trademarks of their respective owners. This is an independent, community-built integration and is not affiliated with, endorsed by, or sponsored by BMW Group. Use at your own risk; see the warranty disclaimer in the LICENSE.

About

A Home Assistant integration that connects directly to BMW CarData — MQTT stream + REST API — turning your BMW's data into native entities.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages