VWEUDA: fix TypeError crash in update_result_from_payload() blocking all SoC updates - #3800
Merged
Merged
Conversation
Refactor odometer handling to preserve last known value if no new reading is available.
Collaborator
|
Vielen Dank fürs Finden und Fixen. Sieht gut aus. |
rleidner
approved these changes
Aug 13, 2026
rleidner
left a comment
Collaborator
There was a problem hiding this comment.
Danke fürs Finden und Fixen. Sieht gut aus.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Im
vweuda-Modul (VW EU-Data-Act-Integration) kannupdate_result_from_payload()in
libeuda.pymit einemTypeErrorabstürzen, sobald der zuvor gecachteOdometer-Wert
Noneist und ein neuer, gültiger Payload einen Odometer-Wertals String liefert:
result['odometer']ist einstr(z. B."15255"),euda.result[vin]['odometer']kann
Nonesein (z. B. wenn der allererste erfolgreich verarbeitete Payloadselbst keinen Odometer-Wert enthielt).
str < Nonewirft in Python 3 einenTypeError.Da diese Exception vor der Zeile
euda.result[vin] = resultauftritt, wirddas komplette Update verworfen – inklusive eines eigentlich gültigen, neueren
SOC-Werts und Zeitstempels. Da der gecachte Odometer-Wert dadurch nie auf
einen nicht-
None-Wert aktualisiert wird, tritt der Fehler bei jedemweiteren Zyklus erneut auf. Das Modul bleibt dauerhaft auf dem allerersten
erfolgreich geladenen Datenstand eingefroren – SOC, Reichweite, Kilometerstand
und Zeitstempel aktualisieren sich nie wieder, bis der Prozess neu gestartet
wird (was den Fehler nur temporär "verdeckt", siehe unten).
Sekundäreffekt: Rate-Limiting durch das VW-Portal
Da die Exception vor dem geplanten
await asyncio.sleep(CYCLE_INTERVAL)(600 s) auftritt und im äußerenexcept Exceptionder Schleife landet, gibt es an dieser Stelle keine Pause.Der Thread ruft die VW-API dadurch im Sekundentakt erneut auf, was zu
HTTP 429 (Too Many Requests)führt und den Datenabruf zusätzlich blockiert.Belege aus einem produktiven SoC-Log
Reproduziert auf einer laufenden openWB-Installation (Fahrzeug: VW ID.3,
Modul
vweuda). Auszug aus dem Log:Dieser Ablauf wiederholte sich im vorliegenden Log kontinuierlich zwischen
16:44 Uhr und 22:18 Uhr (>5,5 Stunden), jeweils im Minuten- bis
Sekundentakt gegen Ende.
get_status()lieferte in diesem gesamtenZeitraum konstant denselben, eingefrorenen Stand vom 2026-08-11, 14:46 Uhr:
Kurz danach im Log auch der Rate-Limit-Effekt:
Parallel dazu wurden über die VW-Portal-Weboberfläche ("Mein Datenpaket")
mehrere ZIPs aus demselben Zeitraum heruntergeladen und manuell geprüft:
Die enthaltenen JSON-Payloads lieferten durchgehend einen validen,
aktuelleren SOC (71 %) und Odometer (15255 km) – die Daten kamen also
tatsächlich frisch vom Portal an, wurden aber durch den beschriebenen Bug
nie in
euda.resultübernommen.Fix
update_result_from_payload()verwirft das Update nicht mehr pauschal,wenn kein direkter Vergleich möglich ist:
None, wird der zuletzt bekannte Wertübernommen (statt das gesamte Update zu verwerfen).
None, wird kein Vergleich versucht, der neue Wertwird direkt übernommen.
float(...), um String/Typ-Mismatches abzufangen; ein verbleibender
TypeError/ValueErrorwirdgeloggt statt die Schleife abstürzen zu lassen.
Damit werden SOC und Zeitstempel in jedem Fall aktualisiert, sobald sie
selbst gültig und neuer sind – unabhängig davon, ob für den Odometer in
diesem Zyklus ein verwertbarer Wert vorliegt.