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>
This commit is contained in:
@@ -264,6 +264,19 @@ arbeitet die Rotation mit `copytruncate` — deshalb leiten die Startskripte mit
|
|||||||
`>>` um und nicht mehr mit `&>`. Wer das zurückdreht, bekommt nach der
|
`>>` um und nicht mehr mit `&>`. Wer das zurückdreht, bekommt nach der
|
||||||
nächsten Rotation eine Logdatei, die vorn aus Nullbytes besteht.
|
nächsten Rotation eine Logdatei, die vorn aus Nullbytes besteht.
|
||||||
|
|
||||||
|
Die lauteste dieser Dateien war `wattpilotshell.log`, rund ein MB am Tag. Die
|
||||||
|
Wallbox schickt in ihren Statusnachrichten 34 Felder, die die
|
||||||
|
API-Beschreibung der Bibliothek nicht kennt (`clea`, `cle`, `opad`, die ganze
|
||||||
|
`ocpp*`-Familie) — wattpilot 0.2 ist seit Mai 2022 die letzte
|
||||||
|
Veröffentlichung, ein Update behebt das also nicht. Die Bibliothek schlug
|
||||||
|
jedes Feld ungeprüft nach und lief in einen `KeyError`, der die restliche
|
||||||
|
Schleife mitriss: alles, was in derselben Nachricht dahinter stand, wurde nie
|
||||||
|
veröffentlicht — im Dauerbetrieb alle 15 Sekunden `fhz`, `lps` und `tpcm`,
|
||||||
|
nach einem Verbindungsaufbau deutlich mehr. `wattpilot_bruecke.py` ersetzt
|
||||||
|
die betroffene Funktion zur Laufzeit und überspringt unbekannte Felder, jedes
|
||||||
|
einmal mit einer Warnung im Log. `startWattpilotMQTT.sh` startet seither die
|
||||||
|
Brücke statt der `wattpilotshell` direkt.
|
||||||
|
|
||||||
`fetch_calendar.py` gehört einmal jährlich in den Cron:
|
`fetch_calendar.py` gehört einmal jährlich in den Cron:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+10
-3
@@ -27,11 +27,13 @@ fi
|
|||||||
|
|
||||||
echo "Starting..."
|
echo "Starting..."
|
||||||
# Change the name of the script here
|
# Change the name of the script here
|
||||||
SCRIPT_NAME="wattpilotshell"
|
# Deckt auch den alten Aufruf ab, damit beim Umstieg keine zweite
|
||||||
|
# Instanz stehen bleibt.
|
||||||
|
SCRIPT_NAME="wattpilot_bruecke.py|wattpilotshell"
|
||||||
LOG_FILE="wattpilotshell.log"
|
LOG_FILE="wattpilotshell.log"
|
||||||
|
|
||||||
# Find the process ID of any running instance of the script
|
# Find the process ID of any running instance of the script
|
||||||
PID=$(ps aux | grep "$SCRIPT_NAME" | grep -v grep | awk '{print $2}')
|
PID=$(ps aux | grep -E "$SCRIPT_NAME" | grep -v grep | awk '{print $2}')
|
||||||
|
|
||||||
# If a running instance was found, kill it
|
# If a running instance was found, kill it
|
||||||
if [[ -n "$PID" ]]; then
|
if [[ -n "$PID" ]]; then
|
||||||
@@ -48,4 +50,9 @@ cd "$BASIS"
|
|||||||
# Loch aus Nullbytes in der Groesse des bisherigen Inhalts. Bei dieser Datei
|
# Loch aus Nullbytes in der Groesse des bisherigen Inhalts. Bei dieser Datei
|
||||||
# faellt das besonders ins Gewicht - die wattpilotshell meldet einen
|
# faellt das besonders ins Gewicht - die wattpilotshell meldet einen
|
||||||
# Verbindungsfehler im Sekundentakt und hatte es so auf 329 MB gebracht.
|
# Verbindungsfehler im Sekundentakt und hatte es so auf 329 MB gebracht.
|
||||||
/var/services/homes/wagner/.local/bin/wattpilotshell server >> "$LOG_FILE" 2>&1 &
|
# Nicht mehr die wattpilotshell direkt: wattpilot_bruecke.py startet sie
|
||||||
|
# ueber eine reparierte MQTT-Bruecke. Die Bibliothek stolpert sonst ueber
|
||||||
|
# Statusfelder, die ihre API-Beschreibung von 2022 nicht kennt, und
|
||||||
|
# verwirft dabei alle Werte, die in derselben Nachricht dahinter stehen.
|
||||||
|
# Begruendung im Kopf von wattpilot_bruecke.py.
|
||||||
|
/usr/local/bin/python3.10 "$BASIS/wattpilot_bruecke.py" server >> "$LOG_FILE" 2>&1 &
|
||||||
|
|||||||
Executable
+94
@@ -0,0 +1,94 @@
|
|||||||
|
#!/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)
|
||||||
Reference in New Issue
Block a user