Fahrgestellnummer: expliziter "automatisch"-Schalter statt Nur-wenn-leer-Heuristik

- Neues Profilfeld fahrzeug.fin_automatisch (Standard: an).
- identitaet.py: bei "aus" läuft die Ableitung (samt Mehrfach-Sensor-Abgleich)
  gar nicht erst; bei "an" überschreibt der abgeleitete Wert auch einen
  vorher von Hand eingetragenen - der Schalter selbst entscheidet jetzt, statt
  aus einem leeren Feld zu raten.
- dienste.py: profil_schreiben löst die Ableitung jetzt auch aus, damit das
  Umschalten des Schalters selbst sofort wirkt.
- Panel: Schalter "automatisch" zwischen Label und Textfeld in der
  Fahrgestellnummer-Zeile, Feld wird bei "an" deaktiviert.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-28 12:01:10 +02:00
co-authored by Claude Sonnet 5
parent c0acc836f0
commit 6b35de458d
7 changed files with 94 additions and 17 deletions
+29 -14
View File
@@ -9,18 +9,27 @@ Kanal-Konfiguration ebenfalls liefern. Ein eigenes Setup-Feld dafür würde vom
Nutzer verlangen, denselben Wert doppelt zu suchen und zuzuordnen, obwohl die
Information am Gerät der ohnehin schon zugeordneten Sensoren hängt.
Stattdessen wird bei jedem Start und nach jeder Setup-Änderung das
Geräte-Register der AKTUELL zugeordneten Sensoren durchsucht (nicht aller
Entitäten der Instanz - nur was Sensorzuordnung tatsächlich referenziert):
für jede zugeordnete Entity-ID wird ihr Gerät nachgeschlagen und daraus eine
FIN-Kandidatin extrahiert (Geräte-Identifier oder Seriennummer, die wie eine
echte FIN aussieht - 17 Zeichen, ohne die im VIN-Standard verbotenen
Ein Schalter "automatisch" neben dem FIN-Feld ("Fahrzeug einrichten",
`fahrzeug.fin_automatisch` im Profil, Standard an) entscheidet, ob diese
Ableitung überhaupt läuft. An: bei jedem Start, nach jeder Setup-Änderung und
nach jedem Profil-Speichern (also auch direkt beim Umschalten des Schalters
selbst) wird das Geräte-Register der AKTUELL zugeordneten Sensoren durchsucht
(nicht aller Entitäten der Instanz - nur was Sensorzuordnung tatsächlich
referenziert): für jede zugeordnete Entity-ID wird ihr Gerät nachgeschlagen und
daraus eine FIN-Kandidatin extrahiert (Geräte-Identifier oder Seriennummer, die
wie eine echte FIN aussieht - 17 Zeichen, ohne die im VIN-Standard verbotenen
Verwechslungsbuchstaben I/O/Q). Liefern mehrere Geräte je eine Kandidatin,
müssen sie übereinstimmen; weichen sie ab, wird nur gewarnt statt geraten -
dieselbe "kein Vorschlag ist besser als ein falscher" Haltung wie an anderen
Stellen dieser App (siehe z. B. entitaetIdKurz() im Panel). Ist im Profil
bereits eine FIN eingetragen, wird sie nie überschrieben - von Hand
eingetragene Werte haben Vorrang vor einer Ableitung.
Stellen dieser App (siehe z. B. entitaetIdKurz() im Panel). Solange
"automatisch" an ist, gilt der abgeleitete Wert als maßgeblich und wird bei
jedem Lauf aktualisiert (auch über einen vorherigen Wert hinweg) - genau das
ist der Zweck des Schalters, nicht ein "nur einmal beim leeren Feld" wie in
einer früheren Fassung dieses Moduls.
Aus: der Schalter deaktiviert die Ableitung vollständig, einschließlich des
Mehrfach-Sensor-Abgleichs oben - das Feld wird dann nirgends mehr angefasst
und bleibt reine Handeingabe wie jedes andere Profilfeld auch.
"""
from __future__ import annotations
@@ -93,29 +102,35 @@ def fin_kandidaten_ermitteln(hass: HomeAssistant, werte: Sensorzuordnung) -> dic
async def fin_ableiten_und_uebernehmen(
hass: HomeAssistant, zuordnung: Zuordnung, ablage: Ablage
) -> None:
"""Trägt die FIN automatisch ins Profil ein, wenn sie dort noch fehlt und
sich aus den zugeordneten Sensoren eindeutig ableiten lässt."""
"""Hält die FIN im Profil mit den zugeordneten Sensoren synchron, solange
fahrzeug.fin_automatisch nicht ausdrücklich abgeschaltet ist (Standard:
an)."""
profil = await ablage.profil_lesen()
if profil is None:
return
fahrzeug = profil.setdefault("fahrzeug", {})
if fahrzeug.get("fin"):
if not fahrzeug.get("fin_automatisch", True):
return
kandidaten = fin_kandidaten_ermitteln(hass, zuordnung.werte)
eindeutig = set(kandidaten.values())
if not eindeutig:
# Nichts gefunden - einen eventuell schon eingetragenen Wert nicht
# löschen, nur weil gerade kein Kandidat da ist (z. B. Sensoren
# kurzzeitig nicht verfügbar).
return
if len(eindeutig) > 1:
_LOGGER.warning(
"Fahrgestellnummer nicht eindeutig aus den zugeordneten Sensoren "
"ableitbar (gefunden: %s) - bitte in \"Fahrzeug einrichten\" von "
"Hand eintragen.",
"ableitbar (gefunden: %s) - bitte \"automatisch\" in \"Fahrzeug "
"einrichten\" ausschalten und von Hand eintragen.",
", ".join(sorted(eindeutig)),
)
return
fin = eindeutig.pop()
if fahrzeug.get("fin") == fin:
return
fahrzeug["fin"] = fin
await ablage.profil_schreiben(profil)
_LOGGER.info(