Mehrere Messwerte auf einem Topic auseinanderhalten
Der go-eCharger schickt sechzehn Zahlen als JSON-Feld auf einem einzigen
Topic, die Wechselrichter und die WLAN-Felder machen es aehnlich. Welcher
Teil der Nutzlast gemeint ist, steht im value_template der
Home-Assistant-Discovery - das Modul las es bisher nur, um den Datentyp zu
raten, und warf es dann weg. Alle sechzehn Messwerte bekamen denselben
Rohtext.
actor_states hat jetzt eine Spalte value_path: ein Pfad in die Nutzlast, in
derselben Schreibweise, die WLED schon benutzt ("[4]", "ssid",
"seg[0].col[0]"). NULL heisst weiterhin: die ganze Nutzlast.
Gelesen wird aus dem Template nur der einfache Fall - ein Zugriff auf
value_json und was danach an Punkten und Klammern folgt. Von den 40
Vorlagen, die hier auf dem Broker liegen, sind 28 genau das. Die uebrigen
zwoelf sind entweder die ganze Nutzlast (dann ist NULL richtig) oder
Werttabellen wie ['Idle','Charging'][value_json|int] - das ist kein Pfad,
sondern eine Uebersetzung von Zahl nach Text, und dort bleibt es beim
bisherigen Verhalten. Kein einziger Fehltreffer: die Werttabellen liefern
sauber None statt eines erfundenen Pfades.
Die Pfad-Auswertung stand schon im WLED-Transport; sie ist jetzt eine
gemeinsame Funktion, die sich beide teilen. MQTT wertet die Nutzlast einmal
je Nachricht aus und verteilt sie danach an alle Messwerte des Topics.
Nachgemessen: die sechzehn nrg-Werte liefern jetzt sechzehn eigene Zahlen
statt sechzehnmal dasselbe, die Leseabdeckung bleibt bei 440 von 441, und
ein weiterer Discovery-Lauf aendert keine Zeile.
Die restlichen geteilten Topics sind kein Fehler: bei den Wechselrichtern
lesen "Limit Persistent" und "Limit NonPersistent" wirklich denselben Wert
und unterscheiden sich nur im Kommando-Topic, und beim Thermostat liest die
Klima-Entity dieselbe Temperatur wie der Sensor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ Erweitert das Tahoma Script um MQTT-Geräte via Home Assistant Discovery
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from typing import Dict, List, Optional
|
||||
import logging
|
||||
@@ -506,6 +507,48 @@ class MQTTDeviceConverter:
|
||||
|
||||
return command_entry
|
||||
|
||||
@staticmethod
|
||||
def _value_path(config: Dict) -> Optional[str]:
|
||||
"""
|
||||
Liest aus dem value_template heraus, welcher Teil der Nutzlast gemeint
|
||||
ist.
|
||||
|
||||
Mehrere Messwerte teilen sich oft ein Topic: der go-eCharger schickt
|
||||
sechzehn Zahlen als JSON-Feld auf "nrg", und erst das value_template
|
||||
sagt, dass "Strom L1" das vierte Element ist. Ohne diese Angabe
|
||||
bekaemen alle sechzehn denselben Rohtext.
|
||||
|
||||
Zurueck kommt ein Pfad in derselben Schreibweise, die auch WLED
|
||||
benutzt: "[3]", "ssid", "foo[0].bar". None heisst: die ganze Nutzlast.
|
||||
|
||||
Home Assistant erlaubt in value_template beliebiges Jinja. Hier wird
|
||||
nur der einfache Fall gelesen - ein Zugriff auf value_json und was
|
||||
danach an Punkten und Klammern folgt. Bei allem anderen (Werttabellen
|
||||
wie ['Idle','Charging'][value_json|int], Bedingungen) bleibt es beim
|
||||
Rohtext, also beim bisherigen Verhalten.
|
||||
"""
|
||||
vorlage = config.get('value_template') or config.get('val_tpl')
|
||||
if not vorlage:
|
||||
return None
|
||||
treffer = re.search(
|
||||
r"value_json((?:\s*(?:\.\w+|\[\s*'[^']*'\s*\]|\[\s*\"[^\"]*\"\s*\]|\[\s*\d+\s*\]))*)",
|
||||
vorlage)
|
||||
if not treffer or not treffer.group(1).strip():
|
||||
return None
|
||||
teile = []
|
||||
for stueck in re.finditer(
|
||||
r"\.(\w+)|\[\s*'([^']*)'\s*\]|\[\s*\"([^\"]*)\"\s*\]|\[\s*(\d+)\s*\]",
|
||||
treffer.group(1)):
|
||||
name = stueck.group(1) or stueck.group(2) or stueck.group(3)
|
||||
teile.append(name if name else "[%s]" % stueck.group(4))
|
||||
if not teile:
|
||||
return None
|
||||
# "[3]" haengt sich ohne Punkt an, Namen mit Punkt.
|
||||
pfad = ""
|
||||
for teil in teile:
|
||||
pfad += teil if teil.startswith("[") else (("." + teil) if pfad else teil)
|
||||
return pfad[:120]
|
||||
|
||||
@staticmethod
|
||||
def _entity_to_states(component: str, object_id: str, config: Dict) -> List[Dict]:
|
||||
"""
|
||||
@@ -539,7 +582,8 @@ class MQTTDeviceConverter:
|
||||
state_entry = {
|
||||
'name': object_id,
|
||||
'type': 'string',
|
||||
'url': state_topic
|
||||
'url': state_topic,
|
||||
'value_path': MQTTDeviceConverter._value_path(config)
|
||||
}
|
||||
|
||||
# Unit hinzufügen - verschiedene mögliche Feldnamen
|
||||
|
||||
Reference in New Issue
Block a user