A Home Assistant custom integration for the BMW CarData API, providing real-time vehicle telematics data from BMW Group vehicles (BMW, MINI, Rolls-Royce, Toyota Supra).
- Real-time streaming via MQTT (bypasses the 50 requests/day REST API limit)
- OAuth 2.0 Device Code Flow with PKCE for secure authentication
- Automatic token refresh - tokens are managed and refreshed automatically
- Multi-vehicle support - add multiple vehicles from the same BMW account with shared authentication
- Location tracking - device tracker entity for zone-based automations (enter/leave events)
- State persistence - entity values are preserved across Home Assistant restarts
- MQTT debug mode - inspect raw MQTT messages in real time via Home Assistant events
- Diagnostics download - export a full snapshot (connection state, telemetry, last 100 MQTT messages) from the device page
The integration creates a device tracker entity for each vehicle, enabling:
- Vehicle location on the Home Assistant map
- Zone-based automations (e.g., notify when car arrives home)
- Location history tracking
Example automation:
automation:
- alias: "Car arrived home"
trigger:
- platform: zone
entity_id: device_tracker.bmw_location
zone: zone.home
event: enter
action:
- service: notify.mobile_app
data:
message: "Your BMW has arrived home"| Entity | Description | Unit | Electric Only |
|---|---|---|---|
| Odometer | Total distance travelled | km | |
| Total Range | Combined remaining range (fuel + electric) | km | |
| Electric Range | Remaining electric-only range | km | ✓ |
| Battery | Battery charge level | % | ✓ |
| Fuel Level | Fuel tank level | % | |
| Energy to Full Charge | Energy needed to fully charge the battery | kWh | ✓ |
| Front Left Tire Pressure | Tire pressure | kPa | |
| Front Right Tire Pressure | Tire pressure | kPa | |
| Rear Left Tire Pressure | Tire pressure | kPa | |
| Rear Right Tire Pressure | Tire pressure | kPa | |
| Charging Status | Current charging status (nocharging, initialization, chargingactive, chargingpaused, chargingended, chargingerror) | — | ✓ |
| Driver Window | Window status (open, intermediate, closed) | — | |
| Front Passenger Window | Window status (open, intermediate, closed) | — | |
| Rear Left Window | Window status (open, intermediate, closed) | — | |
| Rear Right Window | Window status (open, intermediate, closed) | — |
| Entity | Description | Electric Only |
|---|---|---|
| Charging Climatization | Cabin pre-conditioning active during charging | ✓ |
| Trunk | Trunk open/closed | |
| Trunk Door | Trunk door open/closed | |
| Hood | Hood open/closed | |
| Charging Port | Charging port connected/disconnected | ✓ |
| Driver Door | Driver door open/closed | |
| Front Passenger Door | Front passenger door open/closed | |
| Rear Left Door | Rear left door open/closed | |
| Rear Right Door | Rear right door open/closed |
Note: Entities marked "Electric Only" are only created for PHEV and BEV vehicles. Conventional (CONV) vehicles will not have these entities. All entities include a
last_changedattribute showing when the value was last updated by the vehicle.
- BMW ConnectedDrive account with a mapped vehicle
- BMW CarData Portal access - Register at bmw-cardata.bmwgroup.com
- Client ID - Obtain from the BMW CarData Portal after registration
- VIN Authorization - Each vehicle must be individually authorized in the CarData Portal
- Copy the
custom_components/bmw_cardatadirectory to your Home Assistantconfig/custom_components/directory - Restart Home Assistant
- Go to Settings → Devices & Services → Add Integration
- Search for "BMW CarData"
Coming soon
The integration is configured via the UI:
- Enter Client ID - From your BMW CarData Portal
- Authorize with BMW - Visit the displayed URL and enter the code shown
- Select Vehicle - Choose from your PRIMARY vehicles
Each integration instance supports a single VIN. To monitor multiple vehicles:
- Add the integration for your first vehicle
- Add the integration again for each additional vehicle
- Use the same Client ID - authentication tokens are shared automatically
- Select a different VIN each time
The integration handles token sharing and MQTT connection management automatically, ensuring all vehicles receive updates efficiently through a single connection per account.
The integration uses OAuth 2.0 Device Code Flow with PKCE:
- You enter your Client ID from the BMW CarData Portal
- A verification URL and code are displayed
- You visit the URL on any device and enter the code
- The integration polls for authorization completion
- Tokens are securely stored in Home Assistant's config entry
- Initial load: REST API call to fetch basic vehicle data
- Real-time updates: MQTT streaming connection for telemetry data
- Token refresh: Automatic refresh before expiry (access token: 1hr, refresh token: 2 weeks)
- State persistence: Entity values are restored after Home Assistant restarts
- REST API: 50 requests/day (only used for initial setup and basic data)
- MQTT Streaming: Unlimited real-time updates
- Ensure the VIN is authorized in the BMW CarData Portal (not just in ConnectedDrive)
- Check Home Assistant logs for connection errors
- Data arrives on vehicle events (ignition, trips, charging) - may take time for first update
- Verify your Client ID is correct
- Check that your BMW CarData subscription is active
- Try re-authenticating by removing and re-adding the integration
- You must be the PRIMARY user of the vehicle in BMW ConnectedDrive
- SECONDARY users cannot access CarData API
- This occurs when MQTT is disconnected and no previous data exists
- Once data is received, entities retain their last known value even if MQTT temporarily disconnects
- After a restart, previous values are restored automatically
The integration includes a debug mode that fires Home Assistant events for every received MQTT message, allowing you to inspect raw payloads without polluting HA logs.
- Go to Settings → Devices & Services → BMW CarData → Configure
- Toggle Enable MQTT debug events on
- Click Submit
No restart is required — the toggle takes effect immediately.
- Go to Developer Tools → Events
- Under "Listen to events", enter
bmw_cardata_mqtt_debug - Click Start listening
Each event contains:
| Field | Description |
|---|---|
vin |
Vehicle identification number |
topic |
MQTT topic ({gcid}/{vin}) |
timestamp |
Message timestamp from BMW |
payload |
Full raw MQTT message payload |
Tip: The toggle is per-vehicle, so you can debug a single vehicle without flooding events from all configured vehicles.
The integration supports Home Assistant's built-in diagnostics platform, allowing you to download a full JSON snapshot for troubleshooting or bug reports.
| Section | Contents |
|---|---|
vehicle |
VIN suffix, brand, model, drivetrain |
connection |
MQTT connected status, token expiry times |
options |
Current integration options |
telemetry_snapshot |
All current entity values with timestamps |
mqtt_message_buffer |
Last 100 MQTT messages (ring buffer) |
Sensitive data (full VIN, tokens, GCID) is not included in the export.
- Go to Settings → Devices & Services → BMW CarData
- Click on your vehicle device
- Click the ⋮ (three dots) → Download Diagnostics
The ring buffer captures messages continuously — no need to enable debug mode first.
custom_components/bmw_cardata/
├── __init__.py # Integration setup
├── manifest.json # Integration metadata
├── config_flow.py # Configuration UI flow
├── const.py # Constants and entity definitions
├── coordinator.py # Data coordinator with MQTT and token management
├── diagnostics.py # Diagnostics download support
├── entity.py # Base entity class with state restoration
├── sensor.py # Sensor entities
├── binary_sensor.py # Binary sensor entities
├── device_tracker.py # Location tracking entity
├── strings.json # UI strings
└── translations/
└── en.json # English translations
To add new entities, update KNOWN_SENSORS, KNOWN_BINARY_SENSORS, or KNOWN_ENUM_SENSORS in const.py.
When configuring your container in the BMW CarData Portal, add these technical descriptors to receive data for the built-in entities.
vehicle.vehicle.travelledDistance
vehicle.drivetrain.lastRemainingRange
vehicle.drivetrain.fuelSystem.level
vehicle.chassis.axle.row1.wheel.left.tire.pressure
vehicle.chassis.axle.row1.wheel.right.tire.pressure
vehicle.chassis.axle.row2.wheel.left.tire.pressure
vehicle.chassis.axle.row2.wheel.right.tire.pressure
vehicle.body.trunk.isOpen
vehicle.body.trunk.door.isOpen
vehicle.body.hood.isOpen
vehicle.cabin.door.row1.driver.isOpen
vehicle.cabin.door.row1.passenger.isOpen
vehicle.cabin.door.row2.driver.isOpen
vehicle.cabin.door.row2.passenger.isOpen
vehicle.cabin.window.row1.driver.status
vehicle.cabin.window.row1.passenger.status
vehicle.cabin.window.row2.driver.status
vehicle.cabin.window.row2.passenger.status
vehicle.cabin.infotainment.navigation.currentLocation.latitude
vehicle.cabin.infotainment.navigation.currentLocation.longitude
vehicle.cabin.infotainment.navigation.currentLocation.altitude
vehicle.drivetrain.electricEngine.kombiRemainingElectricRange
vehicle.drivetrain.batteryManagement.header
vehicle.drivetrain.electricEngine.charging.smeEnergyDeltaFullyCharged
vehicle.drivetrain.electricEngine.charging.status
vehicle.drivetrain.electricEngine.charging.profile.climatizationActive
vehicle.body.chargingPort.status
Tip: You can add additional keys from BMW's Telematics Data Catalogue by updating
const.py.
MIT License - see LICENSE for details.