Zahlencodes als Klartext
Manche Geraete schicken eine Zahl und meinen einen Zustand - der
go-eCharger etwa 2 fuer "Charging". Welche Zahl welchen Namen hat, steht im
value_template der Home-Assistant-Discovery als Werttabelle:
{{ ['Unknown','Idle','Charging','WaitCar','Complete','Error'][value_json|int] }}
Das ist kein Pfad in die Nutzlast, sondern eine Uebersetzung, und sie wurde
bisher verworfen. Jetzt landet sie in possible_values - in derselben
Schreibweise, die WLED fuer seine Effektliste schon benutzt, naemlich einer
Liste aus {Wert: Bezeichnung}. Damit versteht der Editor sie ohne
Zusatzarbeit und macht eine Auswahlliste daraus. Ein Versatz im Ausdruck
wandert in die Schluessel: aus [value_json|int-3] wird {"3":"Default"}.
Der Runner uebersetzt beim Lesen, eine Bedingung vergleicht also den
Klartext. Steht die Zahl nicht in der Tabelle, bleibt sie stehen - ein
erfundener Name waere schlimmer als ein roher Wert.
Dabei ist ein Folgefehler aufgefallen: Auswahlwerte in dieser Schreibweise
kamen im Editor als "[object Object]" an. Die alte addOptions kannte die
Form, der neue Modell-Aufbau nicht - aufgefallen ist es nie, weil WLED beim
Umbau abgeschaltet war. Der Katalog liefert Auswahlwerte jetzt einheitlich
als {value, label}, und zwar seitenrichtig:
Messwert angezeigt Charging, gespeichert Charging
(der Runner hat schon uebersetzt)
Parameter angezeigt Blink, gespeichert 1
(das Geraet will die Zahl)
Die Uebersicht loest die Bezeichnung ebenfalls auf: "Effekt (Blink)" statt
"Effekt (1)".
Nachgemessen: alle fuenf Werttabellen auf dem Broker richtig erkannt,
einschliesslich des Versatzes, kein Fehltreffer unter den 35 uebrigen
Vorlagen. Live liefert der go-eCharger jetzt Idle, Neutral, Auto, Eco und
None statt 1, 0, 0, 4, 0. Ein weiterer Discovery-Lauf aendert keine Zeile.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -549,6 +549,40 @@ class MQTTDeviceConverter:
|
||||
pfad += teil if teil.startswith("[") else (("." + teil) if pfad else teil)
|
||||
return pfad[:120]
|
||||
|
||||
@staticmethod
|
||||
def _value_map(config: Dict) -> Optional[List[Dict]]:
|
||||
"""
|
||||
Liest eine Werttabelle aus dem value_template.
|
||||
|
||||
Manche Geraete schicken eine Zahl und meinen einen Zustand:
|
||||
|
||||
{{ ['Unknown','Idle','Charging','WaitCar','Complete','Error'][value_json|int ]}}
|
||||
{{ ['Default','Eco','NextTrip'][value_json|int-3]}}
|
||||
|
||||
Das ist kein Pfad in die Nutzlast, sondern eine Uebersetzung von Zahl
|
||||
nach Text. Zurueck kommt sie in der Schreibweise, die WLED fuer seine
|
||||
Effektliste schon benutzt - eine Liste aus {Wert: Bezeichnung} -,
|
||||
denn die versteht der Editor bereits und macht eine Auswahlliste
|
||||
daraus.
|
||||
|
||||
Der Versatz im Ausdruck wandert dabei in die Schluessel: bei
|
||||
"value_json|int-3" gehoert der erste Eintrag zur gesendeten 3.
|
||||
"""
|
||||
vorlage = config.get('value_template') or config.get('val_tpl')
|
||||
if not vorlage:
|
||||
return None
|
||||
treffer = re.search(
|
||||
r"\[\s*((?:'[^']*'|\"[^\"]*\")(?:\s*,\s*(?:'[^']*'|\"[^\"]*\"))*)\s*\]"
|
||||
r"\s*\[\s*value_json\s*\|\s*int\s*([+-]\s*\d+)?\s*\]",
|
||||
vorlage)
|
||||
if not treffer:
|
||||
return None
|
||||
bezeichnungen = [t[1:-1] for t in
|
||||
re.findall(r"'[^']*'|\"[^\"]*\"", treffer.group(1))]
|
||||
versatz = int(treffer.group(2).replace(' ', '')) if treffer.group(2) else 0
|
||||
# index = wert + versatz -> wert = index - versatz
|
||||
return [{str(i - versatz): name} for i, name in enumerate(bezeichnungen)]
|
||||
|
||||
@staticmethod
|
||||
def _entity_to_states(component: str, object_id: str, config: Dict) -> List[Dict]:
|
||||
"""
|
||||
@@ -585,6 +619,9 @@ class MQTTDeviceConverter:
|
||||
'url': state_topic,
|
||||
'value_path': MQTTDeviceConverter._value_path(config)
|
||||
}
|
||||
wertetabelle = MQTTDeviceConverter._value_map(config)
|
||||
if wertetabelle:
|
||||
state_entry['values'] = wertetabelle
|
||||
|
||||
# Unit hinzufügen - verschiedene mögliche Feldnamen
|
||||
unit = (
|
||||
@@ -610,6 +647,11 @@ class MQTTDeviceConverter:
|
||||
elif component == 'sensor':
|
||||
# Bei Sensor den Typ aus value_template ableiten oder number annehmen
|
||||
state_entry['type'] = 'number' # Default für Sensoren
|
||||
|
||||
# Eine Werttabelle schlaegt den geratenen Typ: was beim Geraet als
|
||||
# Zahl ankommt, ist fuer den Benutzer ein Zustandsname.
|
||||
if 'values' in state_entry:
|
||||
state_entry['type'] = 'string'
|
||||
|
||||
states.append(state_entry)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user