"""Sensor-zu-Entität-Zuordnung fürs Setup-Menü (Einstellungen -> Fahrzeug einrichten -> Setup). audi_dashboard/entitaeten.json enthält nur die vom Nutzer über das Setup-Menü geänderten Zuordnungen, keyed nach den Feldnamen aus einstellungen.py. anwenden() legt sie über die eingebauten Standardwerte. Wichtig ist, dass JEDES bekannte Feld bei jedem Durchlauf gesetzt wird, nicht nur die belegten. Eine frühere Fassung übersprang leere Werte - weil die Zuordnung aber ein dauerhaftes Objekt ist, blieb ein einmal gesetzter Wert danach für immer stehen. "Zurücksetzen" im Setup-Menü hatte bei allen Feldern mit leerem Standardwert (15 von 17) schlicht keine Wirkung, und die Oberfläche zeigte beim nächsten Zeichnen wieder den alten Wert, als sei das Speichern fehlgeschlagen. Umgekehrt wurde eine Liste aus leeren Einträgen gesetzt statt übersprungen, was den Sicherheitscheck mit zwölf "unbekannt"-Zeilen füllte und "Sicher abgestellt" dauerhaft grau werden ließ. Jedes Feld bei jedem Durchlauf zu schreiben ist damit nicht nur korrekt, sondern auch idempotent: der Zustand hängt allein an entitaeten.json, nicht an der Reihenfolge vorheriger Aufrufe. """ from __future__ import annotations from . import einstellungen from .ablage import Ablage from .einstellungen import FELDER, SCHLUESSEL, STANDARDWERTE, Sensorzuordnung def _ist_leer(wert: object) -> bool: """Leer heißt: keine Zuordnung. Auch eine Liste, die nur leere Einträge enthält - das Setup-Menü schickt für unbelegte Positionen ["","",...], und das ist inhaltlich dasselbe wie gar keine Liste.""" if wert in (None, ""): return True if isinstance(wert, list): return not any(eintrag for eintrag in wert) return False class Zuordnung: """Hält die wirksame Sensorzuordnung und pflegt sie aus entitaeten.json.""" def __init__(self, ablage: Ablage) -> None: self._ablage = ablage self.werte = Sensorzuordnung() async def anwenden(self) -> None: """Setzt für jedes bekannte Feld den wirksamen Wert - den Override, wenn einer hinterlegt ist, sonst den eingebauten Standardwert.""" overrides = await self._ablage.zuordnung_lesen() for key in SCHLUESSEL: wert = overrides.get(key) standard = STANDARDWERTE[key] gesetzt = standard if _ist_leer(wert) else wert setattr(self.werte, key, list(gesetzt) if isinstance(gesetzt, list) else gesetzt) async def speichern(self, mapping: dict) -> None: """Schreibt nur bekannte Schlüssel; unbekannte werden stillschweigend verworfen, damit ein späterer Katalog-Umbau keine Datenleichen in entitaeten.json hinterlässt.""" bereinigt = {k: v for k, v in mapping.items() if k in SCHLUESSEL} await self._ablage.zuordnung_schreiben(bereinigt) await self.anwenden() def aktueller_stand(self) -> dict: """Katalog + aktuell wirksamer Wert je Feld, Grundlage für die Entität sensor.audi_dashboard_entitaeten. Die Werte kommen aus dem Zuordnungsobjekt selbst, nicht direkt aus der JSON-Datei - damit zeigt die Oberfläche bereits angewendete Overrides und eingebaute Standardwerte einheitlich.""" werte = {feld["key"]: getattr(self.werte, feld["key"], None) for feld in FELDER} return {"katalog": FELDER, "werte": werte, "standardwerte": STANDARDWERTE} __all__ = ["Zuordnung", "einstellungen"]