Skip to content

Add vehicle BYD - #4085

Merged
LKuemmel merged 7 commits into
openWB:masterfrom
seaspotter:add-byd-vehicle-module
Oct 20, 2026
Merged

LKuemmel merged 7 commits into
openWB:masterfrom
seaspotter:add-byd-vehicle-module

Conversation

@seaspotter

Copy link
Copy Markdown
Collaborator

UI: openWB/openwb-ui-settings#1121

Neues Fahrzeug-(SoC)-Modul byd: liest SoC, Reichweite und Kilometerstand über die BYD-Cloud-API. Protokoll reverse-engineered von pyBYD (MIT) und ioBroker.byd (MIT), synchron mit requests nachgebaut (pyBYD selbst braucht Python ≥3.11, openWB läuft auf 3.9). official=False.

Wichtig: BYD erlaubt nur eine aktive Sitzung pro Account – ein zweiter/geteilter Account ist nötig (Workaround in der UI dokumentiert, siehe separater UI-PR). Ein fehlgeschlagener Login wird daher 1h pausiert, um keine Login-Versuche zu verbrennen. Jeder Account bekommt außerdem einen eigenen, zufälligen Geräte-Fingerprint statt eines global geteilten (wirkte sonst wie ein Bot-Signal).

Live getestet über den normalen Control-Loop: Login, Fingerprint-Generierung, VIN-Auflösung und SoC-Abruf erfolgreich. flake8 sauber, volle Testsuite ohne Regressionen. Hybrid-Fahrzeuge (energy_type) technisch unterstützt, aber nur an einem reinen EV-Account getestet.

_fetch_realtime() checked elecPercent is not None to detect real data,
but the vehicleRealTimeRequest trigger response is a placeholder that
already contains elecPercent=0 (not absent), so it was accepted
immediately instead of waiting for the vehicleRealTimeResult poll.
Confirmed via a clean upstream-pybyd-only test against the affected
account: the backend returns real telemetry fine, so this was a bug
in our own readiness check, not a BYD-side restriction. Ports pyBYD's
own is_ready_raw() heuristic (onlineState/time/tire-pressure/
enduranceMileage) instead of the elecPercent check.
- Bisher hat jede openWB-Installation beim Login denselben hart codierten
  (und ungültig formatierten) Geräte-Fingerprint an BYD geschickt - aus
  Sicht des Backends ein klassisches Bot/Credential-Stuffing-Signal und ein
  plausibler Mitverursacher der beobachteten Login-Sperren. Jeder
  konfigurierte Account bekommt jetzt einen eigenen, zufälligen aber
  plausiblen Android-Fingerprint (gültige IMEI per Luhn-Prüfziffer,
  zufällige MAC, aus einem kleinen Pool echter Geräte), einmalig generiert
  und über den bestehenden retained-MQTT-Mechanismus dauerhaft gespeichert
  (analog zu key_expires_at bei myskoda), damit der Account immer als
  dasselbe Gerät auftritt. Pool/Generator von
  https://github.com/TA2k/ioBroker.byd (MIT) übernommen.
- Ein fehlgeschlagener Login (falsches Passwort, Sperre durch gleichzeitig
  aktive Session, etc.) verbraucht einen von wenigen Versuchen, bevor der
  BYD-Account gesperrt wird. Neuer Cooldown von 1h nach jedem Login-Fehler,
  damit das reguläre Polling (alle 5min während des Ladens) den Account
  nicht einfach weiter verbrennt.
- Veralteten Kommentar korrigiert, der behauptete, der VIN-Cache würde wie
  key_expires_at bei myskoda dauerhaft gespeichert - tut er nicht (kein
  Pub()-Aufruf dafür), nur der Geräte-Fingerprint jetzt tatsächlich.
vehicle ist zwar als int typisiert, wird vom Aufrufer (subdata.py, direkt
aus dem MQTT-Topic geparst) aber tatsächlich als str übergeben - bestätigt
durch einen echten Crash beim ersten Live-Test. Betraf sowohl die neue
Fingerprint-Logzeile in soc.py als auch eine bereits bestehende Logzeile
in api.py (Session-Ablauf-Meldung). Beide auf %s umgestellt.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Authentication recovery, concurrent multi-vehicle accounts, account-scoped fingerprints, VIN ambiguity, and upstream license notices need correction.

7 open findings
What changed in this PR

Adds an unofficial BYD Cloud vehicle module for retrieving SoC, range, and odometer data.

Changes:

  • Implements encrypted BYD API authentication and polling.
  • Adds session caching, login cooldowns, and device fingerprints.
  • Integrates BYD configuration and vehicle-state updates.
File Description
packages/​modules/​vehicles/​byd/​__init__.py Defines the BYD package.
packages/​modules/​vehicles/​byd/​api.py Implements Cloud API communication and state extraction.
packages/​modules/​vehicles/​byd/​bangcle_tables.bin Provides Bangcle cipher lookup tables.
packages/​modules/​vehicles/​byd/​config.py Defines module configuration.
packages/​modules/​vehicles/​byd/​crypto.py Implements encryption, signing, and key derivation.
packages/​modules/​vehicles/​byd/​device_fingerprint.py Generates Android device identities.
packages/​modules/​vehicles/​byd/​soc.py Connects the module to openWB vehicle updates.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/modules/vehicles/byd/api.py Outdated
Comment thread packages/modules/vehicles/byd/api.py Outdated
Comment thread packages/modules/vehicles/byd/api.py
Comment thread packages/modules/vehicles/byd/api.py
Comment thread packages/modules/vehicles/byd/soc.py Outdated
Comment thread packages/modules/vehicles/byd/crypto.py Outdated
Comment thread packages/modules/vehicles/byd/device_fingerprint.py Outdated
@LKuemmel
LKuemmel requested a review from ndrsnhs October 14, 2026 06:12
@LKuemmel LKuemmel added this to the 2.3.0 milestone Oct 19, 2026
@ndrsnhs
ndrsnhs requested a balanced review from Copilot October 19, 2026 11:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Session refresh coordination, telemetry timestamp preservation, and persisted fingerprint selection need correction.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Concurrent session refresh invalidates another vehicle's replacement session

packages/​modules/​vehicles/​byd/​api.py:403

If two vehicles on the same account reject the same expired session, both call _get_session(..., force_relogin=True). The account lock serializes the logins but does not deduplicate them. Under BYD's one-active-session rule, the second login invalidates the first vehicle's replacement session, so its only retry can fail. Pass the rejected session into _get_session and, under the account lock, reuse the cached session if another thread has already replaced it. Add a concurrent refresh test; the existing concurrency test covers only initial login.

Medium severity Older SoC readings bypass stale-data protection

packages/​modules/​vehicles/​byd/​api.py:411

A response with an older positive time can pass _is_realtime_ready, but its timestamp is discarded here. CarState then assigns the current time, bypassing ConfigurableVehicle's stale-data charging fallback and out-of-order check. This can replace a newer SoC with an older reading. Pass the positive measurement timestamp as soc_timestamp; CarState already converts millisecond timestamps to seconds.

7 resolved since last review

Review effort: Balanced

Comment thread packages/modules/vehicles/byd/api.py
@LKuemmel
LKuemmel merged commit b1ad625 into openWB:master Oct 20, 2026
1 check passed
@seaspotter
seaspotter deleted the add-byd-vehicle-module branch October 20, 2026 13:16
LKuemmel pushed a commit that referenced this pull request Oct 22, 2026
* Add BYD vehicle SoC module (community, login blocked on unresolved upstream protocol issue)

* Fix BYD realtime data detection returning placeholder as final data

_fetch_realtime() checked elecPercent is not None to detect real data,
but the vehicleRealTimeRequest trigger response is a placeholder that
already contains elecPercent=0 (not absent), so it was accepted
immediately instead of waiting for the vehicleRealTimeResult poll.
Confirmed via a clean upstream-pybyd-only test against the affected
account: the backend returns real telemetry fine, so this was a bug
in our own readiness check, not a BYD-side restriction. Ports pyBYD's
own is_ready_raw() heuristic (onlineState/time/tire-pressure/
enduranceMileage) instead of the elecPercent check.

* BYD-Fahrzeugmodul: Geräte-Fingerprint pro Account, Login-Cooldown

- Bisher hat jede openWB-Installation beim Login denselben hart codierten
  (und ungültig formatierten) Geräte-Fingerprint an BYD geschickt - aus
  Sicht des Backends ein klassisches Bot/Credential-Stuffing-Signal und ein
  plausibler Mitverursacher der beobachteten Login-Sperren. Jeder
  konfigurierte Account bekommt jetzt einen eigenen, zufälligen aber
  plausiblen Android-Fingerprint (gültige IMEI per Luhn-Prüfziffer,
  zufällige MAC, aus einem kleinen Pool echter Geräte), einmalig generiert
  und über den bestehenden retained-MQTT-Mechanismus dauerhaft gespeichert
  (analog zu key_expires_at bei myskoda), damit der Account immer als
  dasselbe Gerät auftritt. Pool/Generator von
  https://github.com/TA2k/ioBroker.byd (MIT) übernommen.
- Ein fehlgeschlagener Login (falsches Passwort, Sperre durch gleichzeitig
  aktive Session, etc.) verbraucht einen von wenigen Versuchen, bevor der
  BYD-Account gesperrt wird. Neuer Cooldown von 1h nach jedem Login-Fehler,
  damit das reguläre Polling (alle 5min während des Ladens) den Account
  nicht einfach weiter verbrennt.
- Veralteten Kommentar korrigiert, der behauptete, der VIN-Cache würde wie
  key_expires_at bei myskoda dauerhaft gespeichert - tut er nicht (kein
  Pub()-Aufruf dafür), nur der Geräte-Fingerprint jetzt tatsächlich.

* BYD-Fahrzeugmodul: %d-Logging-Crash bei String-Fahrzeug-ID beheben

vehicle ist zwar als int typisiert, wird vom Aufrufer (subdata.py, direkt
aus dem MQTT-Topic geparst) aber tatsächlich als str übergeben - bestätigt
durch einen echten Crash beim ersten Live-Test. Betraf sowohl die neue
Fingerprint-Logzeile in soc.py als auch eine bereits bestehende Logzeile
in api.py (Session-Ablauf-Meldung). Beide auf %s umgestellt.

* BYD-Fahrzeugmodul: Anzeigename auf "BYD" kürzen

* fix copilot findings: require VIN, serialize per-account login, fix poll auth retry

* fix copilot findings: seed account fingerprint cache early, reuse refreshed session, pass real soc_timestamp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants