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 <noreply@anthropic.com>
This commit is contained in:
@@ -219,8 +219,14 @@ def registrieren(hass: HomeAssistant, k: Koordinator) -> None:
|
||||
Die Oberfläche hält Profil, Fahrzeugdaten und Einstellungen ohnehin
|
||||
als einen zusammenhängenden Stand im Speicher und schickt ihn nach
|
||||
jeder Änderung komplett zurück - deshalb ein einziger Dienst statt
|
||||
eines eigenen je Feld."""
|
||||
eines eigenen je Feld.
|
||||
|
||||
Danach auch ein Versuch, die Fahrgestellnummer zu synchronisieren
|
||||
(identitaet.py) - unter anderem der Weg, über den das Umschalten von
|
||||
"automatisch" selbst wirkt: dieser Dienst schreibt auch das gerade
|
||||
geänderte fin_automatisch-Flag, bevor die Ableitung es liest."""
|
||||
await k.ablage.profil_schreiben(_objekt(aufruf.data["profil_json"]))
|
||||
await identitaet.fin_ableiten_und_uebernehmen(k.hass, k.zuordnung, k.ablage)
|
||||
await k.profil_veroeffentlichen()
|
||||
|
||||
async def entitaeten_schreiben(aufruf: ServiceCall) -> None:
|
||||
|
||||
@@ -134,6 +134,10 @@ function profilZuCar(p, status) {
|
||||
const reifenSatz = (k) => p.reifen.saetze[k] || {};
|
||||
return {
|
||||
fin: p.fahrzeug.fin,
|
||||
// Default true (auch für Profile von vor dieser Funktion, die das Feld
|
||||
// noch nicht kennen) - deckt sich mit identitaet.py's eigenem
|
||||
// fahrzeug.get("fin_automatisch", True).
|
||||
finAutomatisch: p.fahrzeug.fin_automatisch !== false,
|
||||
details: p.fahrzeug.details,
|
||||
erstzulassung: p.fahrzeug.erstzulassung,
|
||||
hu: p.fahrzeug.hauptuntersuchung_faellig,
|
||||
@@ -198,6 +202,7 @@ function configCarZuProfil(vorherigesProfil) {
|
||||
p.fahrzeug.kennzeichen = CONFIG.kennzeichen;
|
||||
p.fahrzeug.hauptuntersuchung_faellig = CAR.hu;
|
||||
p.fahrzeug.fin = CAR.fin;
|
||||
p.fahrzeug.fin_automatisch = CAR.finAutomatisch;
|
||||
p.fahrzeug.erstzulassung = CAR.erstzulassung;
|
||||
p.fahrzeug.ausfuehrung = CONFIG.ausfuehrung;
|
||||
p.einstellungen.uebersichtsbild = CONFIG.startbild;
|
||||
@@ -2520,7 +2525,14 @@ function vEinst() {
|
||||
<div class="tile"><span class="label">Fahrzeug einrichten</span>
|
||||
${einrichtenOffen ? `
|
||||
<div class="feld" style="margin-top:16px"><label for="einFin">Fahrgestellnummer (FIN)</label>
|
||||
<input id="einFin" value="${esc(CAR.fin || "")}" data-einrichten="fin"></div>
|
||||
<span style="display:flex;align-items:center;gap:10px;min-width:0">
|
||||
<span style="display:flex;align-items:center;gap:6px;flex:0 0 auto">
|
||||
<span class="label" style="margin:0;text-transform:none;letter-spacing:0;font-size:12.5px;color:var(--fg2)">automatisch</span>
|
||||
<label class="switch"><input type="checkbox" data-fin-automatisch ${CAR.finAutomatisch ? "checked" : ""}><span class="track"></span></label>
|
||||
</span>
|
||||
<input id="einFin" value="${esc(CAR.fin || "")}" data-einrichten="fin" ${CAR.finAutomatisch ? "disabled" : ""}
|
||||
title="${CAR.finAutomatisch ? "Wird automatisch aus den im Setup zugeordneten Sensoren ermittelt - \"automatisch\" ausschalten, um von Hand einzutragen." : ""}">
|
||||
</span></div>
|
||||
<div class="feld"><label for="einModell">Modell</label>
|
||||
<select id="einModell" data-einrichten="modell">
|
||||
${(FAHRZEUG_MODELLE.includes(CONFIG.fahrzeugtitel) ? FAHRZEUG_MODELLE : [CONFIG.fahrzeugtitel, ...FAHRZEUG_MODELLE])
|
||||
@@ -5372,6 +5384,7 @@ function ereignisseVerdrahten() {
|
||||
if (e.target.dataset.steuerzeit !== undefined) { CAR.steuer.zeitraum = e.target.value; profilSpeichern(); render(); return; }
|
||||
if (e.target.dataset.steuerfaellig !== undefined) { CAR.steuer.faellig = e.target.value; profilSpeichern(); render(); return; }
|
||||
if (e.target.dataset.steuerlast !== undefined) { CAR.steuer.lastschrift = e.target.checked; profilSpeichern(); render(); return; }
|
||||
if (e.target.dataset.finAutomatisch !== undefined) { CAR.finAutomatisch = e.target.checked; profilSpeichern(); render(); return; }
|
||||
const vteil = e.target.dataset.vteil;
|
||||
if (vteil) {
|
||||
const [i, feld] = vteil.split("|");
|
||||
|
||||
@@ -702,6 +702,10 @@ button.leaf:active { background: var(--tile-2); }
|
||||
appearance: none;
|
||||
}
|
||||
.feld input:focus, .feld select:focus, .notiz:focus { outline: none; border-color: var(--red); }
|
||||
/* z. B. Fahrgestellnummer bei aktivem "automatisch"-Schalter: der Wert kommt
|
||||
aus den zugeordneten Sensoren, Handeingabe ist erst nach dem Ausschalten
|
||||
wieder möglich - das Feld soll das auf den ersten Blick zeigen. */
|
||||
.feld input:disabled { opacity: .5; cursor: not-allowed; }
|
||||
/* Label und Eingabe untereinander statt nebeneinander, die Eingabe über die
|
||||
volle Zeilenbreite - für Felder, deren Wert typischerweise länger ist als
|
||||
ein Kurztext (Kommentar bei Sommer-/Winterrädern, live wie archiviert).
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "audi_dashboard",
|
||||
"name": "Audi Dashboard",
|
||||
"version": "2026.8.28.15",
|
||||
"version": "2026.8.28.16",
|
||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||
"codeowners": ["@paul"],
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
"fahrzeug": {
|
||||
"fin": "",
|
||||
"fin_automatisch": true,
|
||||
"kennzeichen": "",
|
||||
"titel": "RS 4 Avant competition",
|
||||
"zusatz": "Avant competition",
|
||||
|
||||
Reference in New Issue
Block a user