Files
SolarManager/wattpilot_bruecke.py
T
adminandClaude Opus 5 acb443e27a Wattpilot-Bruecke verwirft keine Messwerte mehr
Die Wallbox schickt 34 Statusfelder, die die API-Beschreibung von
wattpilot 0.2 nicht kennt. Die Bibliothek schlug jedes Feld ungeprueft
nach und lief in einen KeyError, der die restliche Schleife mitriss -
alle Werte hinter dem unbekannten Feld derselben Nachricht kamen nie
beim MQTT-Broker an. Im Dauerbetrieb traf es alle 15 Sekunden fhz, lps
und tpcm, nach einem Verbindungsaufbau deutlich mehr; sichtbar war es
nur als Fehlerpaar 'clea' im Log, rund ein MB am Tag.

wattpilot_bruecke.py ersetzt die betroffene Funktion zur Laufzeit und
ueberspringt unbekannte Felder, jedes einmal mit einer Warnung. Die
Reparatur steht hier und nicht in site-packages, weil eine
Neuinstallation sie dort spurlos zurueckdrehen wuerde und wattpilot 0.2
seit Mai 2022 die letzte Veroeffentlichung ist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 19:53:53 +02:00

95 lines
3.4 KiB
Python
Executable File

#!/usr/local/bin/python3.10
"""Startet die wattpilotshell, aber mit einer Reparatur an der MQTT-Bruecke.
Das Problem
-----------
Die Wallbox schickt in ihren Statusnachrichten Felder, die die
API-Beschreibung der Bibliothek (wattpilot 0.2, Stand 2022) nicht kennt -
gemessen 34 Stueck, darunter 'clea', 'cle', 'opad' und die ganze
'ocpp*'-Familie. Die Bibliothek schlaegt jedes Feld ungeprueft in ihrem
Verzeichnis nach:
for prop_name, value in msg_dict["status"].items():
pd = wpdef["properties"][prop_name] # KeyError bei 'clea'
mqtt_publish_property(wp, mqtt_client, pd, value)
Der KeyError reisst die restliche Schleife mit. Alles, was in derselben
Nachricht *hinter* dem unbekannten Feld steht, wird nie veroeffentlicht -
beim Verbindungsaufbau trifft das unter anderem 'amp', 'car', 'ust', 'err',
'cbl', 'pha' und 'wh'. Sichtbar wurde das nur als Fehlerpaar im Log, etwa
alle 16 Sekunden:
ERROR:wattpilot:Error received from WebSocketApp: 'clea'
ERROR:websocket:error from callback ... Wattpilot.__on_message ...: 'clea'
Die Reparatur
-------------
Unbekannte Felder werden uebersprungen statt zu werfen, jedes einmal mit
einer Warnung im Log. Alle bekannten Felder derselben Nachricht kommen
dadurch durch.
Warum hier und nicht in der Bibliothek
--------------------------------------
Die Bibliothek liegt unter ~/.local/lib/python3.10/site-packages und damit
ausserhalb dieses Repositorys; eine Neuinstallation wuerde eine Aenderung
dort spurlos zurueckdrehen. wattpilot 0.2 ist seit Mai 2022 die letzte
Veroeffentlichung, ein Update behebt es also nicht. Deshalb steht die
Reparatur hier, unter Versionskontrolle, und ersetzt die Funktion zur
Laufzeit. mqtt_setup() schlaegt den Namen erst beim Registrieren nach, so
dass unsere Fassung greift.
"""
import json
import logging
import sys
from wattpilot import wattpilotshell as shell
_LOG = logging.getLogger("wattpilot.bruecke")
# Jedes unbekannte Feld soll genau einmal auffallen, nicht bei jeder Nachricht.
_gemeldet = set()
def mqtt_publish_message(event, message):
"""Ersatz fuer wattpilotshell.mqtt_publish_message - siehe Modulkopf."""
wp = event["wp"]
if shell.mqtt_client is None:
return
nachricht = json.loads(message)
typ = nachricht["type"]
if shell.MQTT_PUBLISH_MESSAGES == "true" and (
shell.MQTT_MESSAGES in ([], [""]) or typ in shell.MQTT_MESSAGES):
thema = shell.mqtt_subst_topic(shell.MQTT_TOPIC_MESSAGES, {
"baseTopic": shell.MQTT_TOPIC_BASE,
"serialNumber": wp.serial,
"messageType": typ,
})
shell.mqtt_client.publish(thema, message)
if shell.MQTT_PUBLISH_PROPERTIES != "true" or typ not in ("fullStatus", "deltaStatus"):
return
eigenschaften = shell.wpdef["properties"]
for name, wert in nachricht["status"].items():
beschreibung = eigenschaften.get(name)
if beschreibung is None:
if name not in _gemeldet:
_gemeldet.add(name)
_LOG.warning(
"Feld '%s' steht nicht in der API-Beschreibung der "
"Bibliothek - wird uebersprungen (Wert: %.80s)", name, repr(wert))
continue
shell.mqtt_publish_property(wp, shell.mqtt_client, beschreibung, wert)
shell.mqtt_publish_message = mqtt_publish_message
if __name__ == "__main__":
try:
sys.exit(shell.main())
except KeyboardInterrupt:
sys.exit(0)