Add BMW CarData vehicle module (SoC, range, charging status)#3251
Add BMW CarData vehicle module (SoC, range, charging status)#3251GERDerDennis wants to merge 40 commits intoopenWB:masterfrom
Conversation
Add BMW CarData SoC module - auth wrapper scripts Add auth_start.py and auth_status.py as wrapper scripts for the BMW CarData authentication flow.
|
Seit dem initialen Commit wurde das Modul erheblich weiterentwickelt und auf einer eigenen openWB-Testinstallation (Proxmox VM, Debian 11, openWB 2.1.9-Patch.2) getestet. Natives openWB SoC-Modul vollständig implementiert Getestete Fahrzeuge: BMW iX M60 (2023) – vollständig funktionsfähig Weitere Fahrzeuge noch nicht getestet. Feedback willkommen. |
|
Update zum aktuellen Stand: Die bisherige PHP-Bridge mit sudoers-Regel wurde vollständig ersetzt. Auth-Architektur (neu):
Weitere Verbesserungen:
Getestete Fahrzeuge:
Noch offen:
|
Fix auth UI: show user_code regardless of connection state, simplify auth button
Add odometer support via vehicle.vehicle.travelledDistance
|
Update 29.03.2026 Wird über vehicle.vehicle.travelledDistance abgerufen Auth-UI Fixes: User-Code und Verification-URL werden jetzt auch angezeigt wenn bereits eine Verbindung besteht Aktueller Stand: SoC, Reichweite, Ladestatus und Kilometerstand werden korrekt abgerufen ✅ |
|
Update: Feedback eingearbeitet urllib → req.get_http_session() Testmodus entfernt Auth-Status im Broker statt Datei Unit Tests aktualisiert |
There was a problem hiding this comment.
Pull request overview
This PR introduces an initial BMW CarData vehicle integration, including backend telemetry retrieval (SoC/range) plus a UI-driven device-code OAuth flow to obtain and refresh BMW API tokens.
Changes:
- Added PHP endpoints to start BMW Device Code + PKCE auth and to poll token status.
- Added a new Python vehicle module to fetch SoC/range (and handle token refresh + CarData container discovery/creation).
- Added a UI settings component to configure BMW CarData vehicles and perform the coupling flow.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
web/bmw_cardata/bmw_cardata_auth_start.php |
Starts BMW Device Code flow and returns verifier/device_code metadata to the UI. |
web/bmw_cardata/bmw_cardata_auth_status.php |
Polls the BMW token endpoint and returns access/refresh tokens when authorized. |
packages/modules/vehicles/bmw_cardata/config.py |
Adds dataclass-based configuration/setup for BMW CarData vehicles. |
packages/modules/vehicles/bmw_cardata/soc.py |
Implements token validation/refresh, container detection/creation, and telematic data extraction (SoC/range/odometer). |
packages/modules/vehicles/bmw_cardata/soc_test.py |
Adds unit tests for basic extraction/error handling paths. |
packages/modules/vehicles/bmw_cardata/__init__.py |
Initializes the new vehicle module package. |
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue |
Adds UI configuration and coupling flow with polling for token retrieval. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try: | ||
| raw = session.get(url).json() | ||
| except Exception as e: | ||
| msg = str(e) | ||
| if "404" in msg or "400" in msg: | ||
| log.warning("BMW CarData: Container ungültig, ermittle neu...") | ||
| cfg.container_id = "" | ||
| cid = get_container_id(cfg, token) | ||
| raw = session.get( | ||
| f"{BMW_API_URL}/customers/vehicles/{cfg.vin}/telematicData?containerId={cid}" | ||
| ).json() | ||
| else: | ||
| raise |
There was a problem hiding this comment.
Die Erkennung eines ungültigen Containers basiert auf String-Suche nach "404"/"400" in str(e). Das ist fragil (Format kann variieren) und kann dazu führen, dass Container-Refresh nicht ausgelöst wird. Besser: gezielt requests.exceptions.HTTPError abfangen (kommt durch raise_for_status() Hook) und e.response.status_code prüfen.
| soc_raw = val(FIELD_SOC) or val(FIELD_SOC_ALT) | ||
| rng_raw = val(FIELD_RANGE) | ||
| status = val(FIELD_STATUS) | ||
| odo_raw = val(FIELD_ODOMETER) | ||
|
|
||
| soc = int(float(soc_raw)) if soc_raw is not None else None | ||
| rng = int(float(rng_raw)) if rng_raw is not None else None | ||
| odo = int(float(odo_raw)) if odo_raw is not None else None | ||
|
|
||
| if soc is None: | ||
| raise Exception("BMW CarData: Kein SoC-Wert in API-Antwort gefunden!") | ||
|
|
||
| log.info("BMW CarData: SoC=%s%%, Reichweite=%s km, Status=%s, Odometer=%s km", | ||
| soc, rng, status, odo) | ||
| return CarState(soc=soc, range=rng, odometer=odo) | ||
|
|
There was a problem hiding this comment.
Es wird zwar charging.status ausgelesen und geloggt, aber nicht im CarState zurückgegeben oder anderweitig publiziert. Damit wird der im PR-Text erwähnte "charging status" aktuell nicht für openWB nutzbar. Entweder Status in ein passendes Datenfeld/Topic übernehmen oder die Feature-Behauptung/Logs entsprechend anpassen.
There was a problem hiding this comment.
Der Ladestatus wird über den Ladecontroller ausgewertet. Im Fahrzeug-Modul ist er nicht nötig..
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
LKuemmel
left a comment
There was a problem hiding this comment.
Bitte auch die Kommentare von Copilot beachten und die vue-Datei als PR für das settings-Repo einreichen.
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
| soc_raw = val(FIELD_SOC) or val(FIELD_SOC_ALT) | ||
| rng_raw = val(FIELD_RANGE) | ||
| status = val(FIELD_STATUS) | ||
| odo_raw = val(FIELD_ODOMETER) | ||
|
|
||
| soc = int(float(soc_raw)) if soc_raw is not None else None | ||
| rng = int(float(rng_raw)) if rng_raw is not None else None | ||
| odo = int(float(odo_raw)) if odo_raw is not None else None | ||
|
|
||
| if soc is None: | ||
| raise Exception("BMW CarData: Kein SoC-Wert in API-Antwort gefunden!") | ||
|
|
||
| log.info("BMW CarData: SoC=%s%%, Reichweite=%s km, Status=%s, Odometer=%s km", | ||
| soc, rng, status, odo) | ||
| return CarState(soc=soc, range=rng, odometer=odo) | ||
|
|
There was a problem hiding this comment.
Der Ladestatus wird über den Ladecontroller ausgewertet. Im Fahrzeug-Modul ist er nicht nötig..
benderl
left a comment
There was a problem hiding this comment.
Wie Lena schon geschrieben hat, bitte die Vue-Datei in einen PR gegen das Settings-Repo packen. Die beiden PHP-Dateien gehören auch dort hin. Im Pfad public/modules/vehicles/ findest Du schon vergleichbare Dateien für die Tesla und Mercedeseq SoC-Module.
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
openwb-ui-settings/src/components/vehicles/bmw_cardata/vehicle.vue
Outdated
Show resolved
Hide resolved
|
Danke für das ausführliche Feedback! Ein Großteil der angesprochenen Punkte ist bereits im aktuellen Stand umgesetzt:
Zusätzlich werde ich:
Einige vorgeschlagene Änderungen beziehen sich auf ältere Code-Stände und sind im aktuellen Branch bereits angepasst. Falls ich etwas übersehen habe, gerne nochmal kurz Bescheid geben 🙂 |
…ponse.status_code
|
Die vehicle.vue wurde in einen separaten openwb-ui-settings PR verschoben: |
This PR adds an initial BMW CarData integration for openWB vehicles.
Features
Background
BMW CarData often returns an empty container list even with valid authentication and vehicle mapping.
This implementation detects that condition and automatically creates a minimal container, allowing telematic data retrieval without manual intervention.
UI
Notes
Status
Work in progress. Further improvements planned:
Feedback is very welcome.