Fix Consumer: Absturz der Regelung durch defekte/gelöschte Verbraucher-Module verhindern - #3917
Open
seaspotter wants to merge 2 commits into
Open
Fix Consumer: Absturz der Regelung durch defekte/gelöschte Verbraucher-Module verhindern#3917seaspotter wants to merge 2 commits into
seaspotter wants to merge 2 commits into
Conversation
LKuemmel
requested changes
Sep 10, 2026
…assen
Zwei Bugs in der neu gemergten Verbrauchersteuerung behoben:
1. Modul-Erstellung schlägt fehl -> Regelung crasht dauerhaft
- setdata.py erkannte openWB/set/consumer/{id}/module/simulation nicht
als gültiges Topic (Unbekanntes set-Topic-Fehler in jedem Zyklus,
betrifft jeden Verbraucher mit eingebautem Zähler) und löschte das
Zähler-Persistenz-Topic dabei sofort wieder.
- subdata.py interpretierte das gemirrorte .../module/simulation-Topic
wegen fehlendem $-Anker am /module-Pattern als vollständige
Modul-Neukonfiguration und scheiterte an KeyError('vendor').
- Modul-Erstellung in subdata.py schlägt jetzt sichtbar fehl (Log mit
Verbraucher/vendor/type, fault_state/fault_str, Systemmeldung an die
UI) statt module auf None zu belassen.
- loadvars.py überspringt Verbraucher ohne erfolgreich erstelltes Modul
statt bei jedem Zyklus mit AttributeError abzubrechen.
2. Gelöschter Verbraucher bleibt in Prioritätensteuerung -> Regelung
berechnet für KEINEN Ladepunkt mehr Strom (discussions#3908, Kommentar
18370811)
- remove_loadmanagement_prio_item() verglich die id mit ==; kam sie
(z.B. aus einem MQTT-Kommando) als str statt int an, wurde das
Element nicht gefunden, eine IndexError geworfen und dadurch in
removeConsumer()/removeVehicle() der Rest der Aufräumarbeiten
(Publish der korrigierten Prioritätenliste) übersprungen - der
Eintrag blieb dauerhaft im retained Topic, auch über Neustarts
hinweg.
- id-Vergleich jetzt tolerant gegen str/int-Mismatch, "nicht gefunden"
ist eine Warnung statt eine den Aufrufer abbrechende Exception.
- filter_chargepoints.py löst Verbraucher-Referenzen aus der
Prioritätensteuerung defensiv per .get() auf; eine Karteileiche wird
geloggt und übersprungen statt calc_current() für alle Ladepunkte
abzuschießen.
- Tests für beide Fälle (flach und in einer Gruppe, sowie str/int-id).
seaspotter
force-pushed
the
fix-consumer-module-errors
branch
from
September 11, 2026 18:05
967e9ac to
b1e9612
Compare
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 1: Verbraucher-Modul-Erstellung schlägt fehl -> Log-Spam und kaputte Persistenz
Beim Einrichten eines IDM-Wärmepumpen-Verbrauchers zeigte das Log dauerhaft (jeden Regelzyklus) zwei Fehler:
Root Cause:
SimCounterConsumer(modules/common/simcount/_simcounter.py) persistiert seinen Zählerstand nachopenWB/set/consumer/{id}/module/simulation.setdata.py::process_consumer_topickannte dieses Topic nicht (anders als die analogen/get/simulation- bzw..../component/.../simulation-Fälle für Chargepoint/Device) und löschte es sofort wieder als "unbekannt" - jeder Verbraucher mit eingebautem Zähler verliert damit seinen persistierten Zählerstand bei jedem Neustart.subdata.pys/module-Pattern hatte keinen$-Anker und griff dadurch auch bei diesem gemirrorten.../module/simulation-Topic, wo es als vollständige Modul-Neukonfiguration interpretiert wurde ->KeyError: 'vendor', verschluckt als generisches "Fehler im subdata-Modul".consumer.moduledauerhaftNone, unsichtbar für den Nutzer, undloadvars.pycrashte bei jedem Zyklus erneut, statt den Verbraucher einmalig als fehlerhaft zu markieren.Problem 2: Gelöschter Verbraucher blockiert die komplette Ladestromberechnung
Aus discussions#3908 (@Frank-Hoe):
Und im mitgeposteten Log:
Root Cause:
remove_loadmanagement_prio_item()vergleicht dieidmit==. Kommt sie (z. B. aus einem MQTT-Kommando) alsstrstattintan, wird das Element nicht gefunden, eineIndexErrorgeworfen - und dadurch brichtremoveConsumer()/removeVehicle()ab, bevor die korrigierte Prioritätenliste erneut published wird. Der Eintrag bleibt dauerhaft im retained Topic stehen, auch über Neustarts hinweg (deckt sich exakt mit "wird in der Prioritätenliste angezeigt" trotz Löschung).filter_chargepoints.py::_group_loads_by_chargemodelöst so einen Eintrag mit einem ungeschütztendict[...]-Zugriff aufconsumer_dataauf - ungefangen, innerhalb voncalc_current(). Ein einziger Karteileichen-Eintrag reicht damit aus, um die Stromberechnung für alle Ladepunkte in jedem Zyklus abzuschießen.Fix
setdata.pyerkennt.../module/simulationjetzt als gültiges Topic.subdata.py:/module-Pattern mit$-Anker; Modul-Erstellung schlägt jetzt sichtbar fehl (Log mit Verbraucher/vendor/type,fault_state/fault_str, Systemmeldung an die UI) stattmodulestillschweigend aufNonezu belassen.loadvars.pyüberspringt Verbraucher ohne erfolgreich erstelltes Modul, statt bei jedem Zyklus mitAttributeErrorabzubrechen.loadmanagement_prio.py: id-Vergleich tolerant gegen str/int-Mismatch; "nicht gefunden" ist eine Warnung statt einer den Aufrufer abbrechenden Exception.filter_chargepoints.pylöst Verbraucher-Referenzen aus der Prioritätensteuerung defensiv per.get()auf; eine Karteileiche wird geloggt und übersprungen stattcalc_current()für alle Ladepunkte abzuschießen.Bekannte Lücke / Follow-up: inkonsistenter Zustand bei fehlgeschlagenem "add"
Dieser PR macht Fehler bei der Verbraucher-Modul-Erstellung sichtbar und nicht mehr absturzfähig (siehe Problem 1), behebt aber nicht die strukturelle Ursache, warum so ein Zustand überhaupt entstehen kann:
addConsumer()(command.py) legt Hierarchie-Eintrag und Konfiguration synchron an und meldet dem Nutzer sofort "Neues Gerät [...] hinzugefügt" - bevor die eigentliche Modul-Erstellung passiert ist. Diese läuft erst asynchron insubdata.py, wenn das/module-Topic dort verarbeitet wird. Schlägt das fehl, hat der Nutzer bereits eine Erfolgsmeldung gesehen, und es bleibt ein Verbraucher mit Konfiguration, aber ohne funktionierendes Modul zurück - jetzt zumindest mitfault_state/Systemmeldung statt stiller Karteileiche, aber die Karteileiche selbst entsteht weiterhin.Denkbare nächste Schritte (nicht Teil dieses PRs):
addConsumer()erst dann als erfolgreich melden, wenn die Modul-Erstellung bestätigt ist (z. B. über einen Rückkanal/Timeout statt fire-and-forget), oderDas betrifft grundsätzlich den
addConsumer-Ablauf (und potenziell den analogenaddDevice/addVehicle-Flow).