Files
audi-app/REVIEW_main_2026-08-13.md
T
Paul Nothaft 12418a3d52 Review des aktuellen Stands und Plan fuer die native HA-Integration
Zwei Dokumente, beide reine Analyse - kein Code geaendert.

REVIEW_main_2026-08-13.md: 15 Befunde aus den Commits c66ed82..d5562c7,
nach Schaden sortiert, jeder mit Datei-Zeile und der Kette vom Ausloeser zur
Auswirkung. Die drei schwersten liegen im neuen Setup-Menue:

1. Speichern, solange der Katalog noch nicht geladen ist, ueberschreibt
   entitaeten.json mit {} und loescht alle Zuordnungen. Faellt erst beim
   naechsten Neustart auf, weil die setattr-Werte im Prozess bestehen
   bleiben - und entitaeten.json wird von backup.py nicht gesichert.
2. "Zuruecksetzen" wirkt bei 15 von 17 Feldern nicht, weil
   overrides_anwenden() leere Werte ueberspringt und der Standardwert bei
   fast allen Feldern leer ist. Isoliert nachgestellt.
3. Alle vier Listenpositionen bekommen denselben Sensor, weil der
   Vorschlag den Index nicht auswertet. Folge: der Sicherheitscheck prueft
   viermal dieselbe Tuer und meldet "Sicher abgestellt", obwohl drei Tueren
   nie geprueft wurden.

Jeder Befund ist als belegt oder plausibel gekennzeichnet.

ha_install.md: Plan fuer die Umstellung von pyscript auf eine eigene
Integration mit Konfigurationsdialog - Einrichtung komplett ueber die
Oberflaeche, kein YAML, Updates als Knopfdruck. Alle genannten
Schnittstellen sind an der laufenden 2026.8.1-Instanz geprueft, inklusive
Signaturen.

Zur Verteilung: HACS kann ausschliesslich GitHub und scheidet fuer das
Gitea-Repository aus. App-Repositories akzeptieren zwar beliebige Git-URLs,
Apps sind aber Docker-Container und damit der falsche Behaelter fuer eine
Integration. Nativ bleibt eine eigene UpdateEntity, deren Logik in
updateverwaltung.py bereits zu grossen Teilen existiert.

Festgehalten ist ausserdem, welche der Review-Befunde die Umstellung
konstruktionsbedingt aufloest - unter anderem alle drei oben genannten sowie
die Token-Datei im Klartext, weil eine Integration den Recorder direkt
abfragen kann statt sich selbst ueber HTTP.
2026-08-13 13:43:25 +02:00

21 KiB
Raw Blame History

Review: Branch main, Commits c66ed82..d5562c7

Datum: 2026-08-13 · Umfang: 18 Commits, 24 Dateien, +2752/259 Zeilen Gegenstand: Setup-Menü zur Sensor-Zuordnung, Umstellung von WLAN/VAG auf FMM003, Standort-Kachel mit Live-Position, iOS-/Großbildschirm-Optikauflage, DuckDNS und Zertifikate.

Geprüft wurde gegen eine Arbeitskopie von origin/main. Die mit [belegt] markierten Befunde sind am Code nachvollzogen oder nachgestellt; [plausibel] heißt: aus dem Code abgeleitet, aber nicht im Browser reproduziert.


Gesamteindruck

Handwerklich stark. Das Setup-Menü ersetzt „vor der Installation einstellungen.py editieren" durch eine Oberfläche mit Live-Wertvorschau, Unavailable-Warnung, Duplikat-Prüfung und einem ehrlichen Neustart-Hinweis für die drei triggergebundenen Felder. Der Kniff dahinter — setattr auf dem laufenden Modul-Objekt, weil alle Leser einstellungen.KM_SENSOR als lebenden Attributzugriff machen — ist elegant und im Kopfkommentar sauber begründet.

Positiv außerdem: Escaping ist im neuen Code durchgängig (kein XSS gefunden), Karten-Ebenen werden vor dem Neuaufbau entfernt, die Haversine-Distanz ist mathematisch korrekt, Listenfelder sind gegen zu kurze Arrays abgesichert, und die Python-Syntax aller acht geänderten pyscript-Dateien ist in Ordnung.

Die Fehler unten liegen fast alle im selben Bereich — dem neuen Setup-Menü — und drei davon werden erst nach einem Neustart sichtbar, also mit maximalem zeitlichem Abstand zur Ursache.

Übersicht

# Befund Wirkung Ort
1 Speichern bei fehlendem Katalog löscht alle Zuordnungen Datenverlust audi-dashboard-app.js:1773, 2031
2 „Zurücksetzen" wirkt bei 15 von 17 Feldern nicht falscher Zustand entitaeten.py:188
3 Alle vier Listenpositionen bekommen denselben Sensor falsche Sicherheitsaussage audi-dashboard-app.js:1976
4 Vorschlagsschwelle akzeptiert beliebige Sensoren falscher Fahrt-Trigger audi-dashboard-app.js:1980
5 Geleerte Listen setzen ["","","",""] Status dauerhaft „unbekannt" entitaeten.py:188
6 Zuordnung wird nirgends gesichert Verlust bei Wiederherstellung backup.py:32
7 Kaputte entitaeten.json legt das Panel lahm Totalausfall entitaeten.py:159
8 Standortabfrage im Dauerfeuer bei abgelehnter Freigabe Akku, Netz audi-dashboard-app.js:553/557
9 Kein Tastaturweg in die Einstellungen unter 860 px Bedienbarkeit audi-dashboard-app.js:3849
10 .navmarke nur in der iOS-Auflage versteckt Tab-Leiste zerfällt audi-dashboard-ios.css:194

Schwerwiegend

1. Speichern bei fehlendem Katalog löscht die gesamte Zuordnung [belegt]

Kette:

  1. ENTITAETEN wird an genau einer Stelle gefüllt (audi-dashboard-app.js:3723), aus hass.states.
  2. Der Nachlade-Pfad nach einem HA-Neustart (:3699-3703) holt Profil, Fahrten, Tankvorgänge, Status und Batterieverlauf nach — nicht aber pyscript.audi_dashboard_entitaeten.
  3. DATEN_GELADEN hängt allein am Profil. Die App gilt also als geladen, während der Katalog fehlt.
  4. Der Knopf „Setup — Sensoren zuordnen" (:1773) ist nur an einrichtenOffen gekoppelt, nicht an den Katalog. setupKatalog() liefert [], das Popup öffnet ohne eine Zeile und ohne Fehlermeldung, setupZuordnung bleibt {}.
  5. „Speichern" schickt "{}" (:2031). overrides_schreiben() ersetzt die Datei vollständig, ohne Zusammenführen (entitaeten.py:166-173).

Auswirkung: data/entitaeten.json enthält danach {}. Weil die setattr-Werte im laufenden Prozess bestehen bleiben, fällt der Verlust erst beim nächsten Neustart auf. Zusammen mit Befund 6 (keine Sicherung) gibt es dann nichts zurückzuholen.

Vorschlag: Setup-Knopf sperren, solange ENTITAETEN null ist, und in setupSpeichernAusfuehren() abbrechen, wenn setupZuordnung leer ist. Zusätzlich die Entität in den Nachlade-Pfad aufnehmen.

2. „Zurücksetzen" wirkt bei 15 von 17 Feldern nicht [belegt, nachgestellt]

entitaeten.py:188 überspringt leere Werte:

if wert in (None, "", []):
    continue

Der Kopfkommentar derselben Datei beschreibt das Problem exakt richtig — setattr verändert das Modul dauerhaft, „Zurücksetzen" muss den Standardwert aktiv zurückschreiben. Das Frontend tut das auch (setupStandardwert). Nur ist der Standardwert bei 15 der 17 Katalogfelder "" oder [] — und genau die werden übersprungen.

Nachgestellt:

nach Zuordnung:     KM_SENSOR = 'sensor.alt_vag_mileage'
nach Zurücksetzen:  KM_SENSOR = 'sensor.alt_vag_mileage'   ← erwartet: ''

Auswirkung: Für den Nutzer sieht es aus, als hätte das Speichern versagt — aktueller_stand() liest aus dem laufenden Modul, das Feld zeigt beim nächsten Zeichnen wieder den alten Wert. Funktioniert nur bei ZUENDUNG_SENSOR, BATTERIE_SENSOR und STANDORT_TRACKER, den drei Feldern mit nicht-leerem Standard.

3. Alle vier Listenpositionen bekommen denselben Sensor [belegt]

audi-dashboard-app.js:1976-1981:

zuordnung[feld.key] = feld.positionen.map((_, i) => {
  const vorhanden = (werte[feld.key] || [])[i];
  if (vorhanden) return vorhanden;
  const vorschlag = entitaetKandidaten(feld.key, "", "")[0];   // i geht nicht ein
  return vorschlag && entitaetScore(feld, vorschlag, "") >= 3 ? vorschlag.id : "";
});

entitaetKandidaten() hängt nicht vom Index ab und schließt bereits vergebene IDs nicht aus — alle vier Positionen bekommen dieselbe Entität. Betrifft TUER_SENSOREN, FENSTER_SENSOREN, TUERSCHLOSS_SENSOREN.

Auswirkung: Bei einer Frischinstallation (genau der Fall, für den das Menü gebaut wurde) prüft _sicherheitscheck() danach viermal dieselbe Tür. „Sicher abgestellt" meldet gesichert, obwohl drei Türen nie geprüft wurden. Die Duplikat-Warnung fängt das beim Speichern ab, ist aber mit „Trotzdem speichern" wegklickbar.

4. Die Vorschlagsschwelle akzeptiert beliebige Sensoren [belegt]

entitaetScore() (:1936) vergibt: Stichwort +5, Domain +3, device_class +3, Einheit +2. Die Schwelle ist >= 3ein Domain-Treffer allein genügt, ohne dass ein einziges Stichwort passt. Verschärfend: setupNurPassend wird zwei Zeilen vorher auf true gesetzt (:1971), wodurch entitaetKandidaten() ohnehin hart auf die Domain filtert. Die Schwelle ist damit immer erfüllt. Die Reihenfolge kommt aus Object.keys(HASS.states), ist also faktisch willkürlich.

Auswirkung: Ohne passenden Zündungssensor wird ZUENDUNG_SENSOR stumm mit dem erstbesten binary_sensor.* vorbelegt — Bewegungsmelder, Fensterkontakt, was zuerst kommt. Das Feld sieht ausgefüllt aus, wird mitgespeichert, und die gesamte Fahrterkennung hängt an einem Zufallssensor. Bei Einzelfeldern greift keine Duplikat-Warnung. Dasselbe für TANK_SENSOR (jeder %-Sensor, etwa Luftfeuchte) und REFRESH_BUTTON (jedes button.*).

Vorschlag: Schwelle auf >= 5 — also mindestens ein Stichworttreffer.

5. Geleerte Listenfelder setzen ["","","",""] [belegt]

Die Skip-Regel aus Befund 2 prüft auf []. Ein Array aus vier leeren Zeichenketten ist das nicht:

["","","",""] in (None, "", [])   # False -> wird per setattr gesetzt

_sicherheitscheck() zippt dann über vier leere Entity-IDs und erzeugt vier „unbekannt"-Zeilen — mal drei Listen sind das zwölf.

Auswirkung: Weil die Gesamtaussage bewusst None wird, sobald eine Prüfung unbekannt ist, steht die Übersicht danach dauerhaft auf „Zustand unbekannt" statt auf grün.

Kurios ist die Kombination mit Befund 2: Bei Einzelfeldern wirkt „Zurücksetzen" gar nicht, bei Listenfeldern zu stark. Beides verschwindet mit demselben Fix — statt leere Werte zu überspringen, immer den Standardwert aus _STANDARDWERTE zurückschreiben:

def overrides_anwenden():
    overrides = overrides_lesen()
    for key in _SCHLUESSEL:
        wert = overrides.get(key)
        leer = wert in (None, "", []) or (isinstance(wert, list) and not any(wert))
        setattr(einstellungen, key, _STANDARDWERTE[key] if leer else wert)

6. Die Sensor-Zuordnung wird nirgends gesichert [belegt]

backup.py:32 sichert fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonlentitaeten.json fehlt. Auch audi_dashboard_backup_wiederherstellen kennt es nicht, update.ps1 fasst data/ bewusst nicht an, und in homeassistant/.gitignore steht es nicht neben den anderen Laufzeitdateien.

Auswirkung: Nach einer Wiederherstellung ist die komplette Sensor-Zuordnung still weg. In Verbindung mit Befund 1 gibt es keinen Rückweg.

7. Eine beschädigte entitaeten.json legt das Panel lahm [belegt]

overrides_lesen() (entitaeten.py:159) ruft json.loads ohne Absicherung. Der Aufruf steht in beim_start() vor alles_veroeffentlichen() — wirft er, wird gar nichts veröffentlicht, das Panel bleibt komplett leer.

Geschrieben wird zwar atomar über .tmp + os.replace, das Risiko ist also gering — der Ausfall wäre aber total. Dieselbe Fehlerklasse, die im Branch umsetzung-datametric360 bei profil_lesen() bereits abgefangen wurde.


Mittel

8. Standortabfrage im Dauerfeuer, Karte bei jedem Render neu [belegt]

USER_POS_TS wird nur im Erfolgs-Callback gesetzt (:553), nicht im Fehlerfall (:557). Die 30-Sekunden-Drossel in standortErfassenFallsNoetig() (:560) greift damit nie, wenn der Nutzer die Standortfreigabe ablehnt oder kein Fix zustande kommt.

Parallel dazu zerstört render() die Vorschaukarte und baut sie neu (:2879-2880), sobald die Route home ist — bei jedem Backend-Update.

Auswirkung: Mit einem GPS-Tracker als Quelle (genau der FMM003-Fall) sind das dutzende getCurrentPosition({enableHighAccuracy:true})-Anfragen pro Stunde plus sichtbares Kachelflackern.

Vorschlag: USER_POS_TS = Date.now() auch im Fehlerpfad; Karte nur bei echtem Ansichtswechsel neu bauen — die Variable gleicheAnsicht gibt es in render() bereits.

9. Kein Tastaturweg in die Einstellungen unter 860 px [belegt]

audi-dashboard-ios.css:81 versteckt .profilbtn — den echten <button aria-label="Einstellungen"> — und holt ihn erst in der Container-Abfrage ab 860 px zurück (:230). Der Ersatz ist ein Klick-Handler auf #marke (:2965), und das ist ein <div class="rings" aria-label="Audi"> (:3849): ohne role, ohne tabindex.

Auswirkung: In Telefonbreite gibt es für Tastatur- und Screenreader-Nutzer keinen Zugang zu den Einstellungen. Ein <div> mit aria-label ohne Rolle wird von den meisten Screenreadern nicht einmal angesagt. Gleiche Fehlerklasse wie das Swipe-Löschen aus AUDIT_2026-08-10.md.

Vorschlag: #marke zu einem <button aria-label="Einstellungen"> machen; dann kann auch pointer-events:auto in audi-dashboard-ios.css:78 entfallen.

10. .navmarke nur in der iOS-Auflage versteckt [belegt]

audi-dashboard-app.js:2956-2963 hängt den Ringklon unbedingt in #tabbar. .navmarke{display:none} steht ausschließlich in audi-dashboard-ios.css:194. .tabbar ist ein display:grid mit repeat(5, 1fr) (audi-dashboard.css:211).

Auswirkung: Lädt /local/audi-dashboard-ios.css nicht (404, Cache), wird der Klon ein sechstes Grid-Element — alle Tabs rutschen eine Spalte weiter, „Tanken" fällt in eine zweite Zeile, die Menüleiste zerfällt. Kein theoretischer Fall: Commit 3548f77 dokumentiert genau dieses Deployment-Loch.

Vorschlag: .navmarke{display:none} gehört in die Basis-CSS, die Sichtbarkeit in die Auflage.

11. Standort-Menü ohne pointercancel [belegt]

standortMenuVerdrahten() (:706-731) setzt smY0 nur in pointerup zurück. Alle drei anderen Zeigergesten der Datei haben einen pointercancel-Handler (:2929, :3055, :3122), diese nicht.

Auswirkung: Übernimmt das System die Berührung (iOS-Randgeste, Multitouch, eingehender Anruf), bleibt smY0 gesetzt. Der pointermove-Handler ruft dann preventDefault() für jede weitere Bewegung — Scrollen ist in der ganzen App blockiert, bis irgendwo ein pointerup kommt, der dann ein dy aus einem veralteten Startpunkt auswertet.

12. Fehlgeschlagenes Reverse-Geocoding wird dauerhaft gecacht [belegt]

:572-586 setzt STANDORT_ADRESSE_KEY auch im catch-Zweig.

Auswirkung: Ein einziger fehlgeschlagener Nominatim-Abruf (Rate-Limit, kurzer Netzausfall) für eine Zelle führt dazu, dass für dieselbe Zelle die gesamte Sitzung lang nur Koordinaten angezeigt werden, auch wenn das Netz längst wieder da ist.

Vorschlag: Key nur im Erfolgsfall setzen.

13. Setup-Popup hält den role="dialog"-Vertrag nicht ein [belegt]

:2774 deklariert role="dialog" aria-modal="true". Es fehlen: Escape zum Schließen (in der Datei gibt es keinen keydown-Handler), eine Fokusfalle (Tab wandert in den überdeckten Hintergrund), und der Schalter „Nur passende Sensoren anzeigen" (:2779) hat keinen zugänglichen Namen — der Beschriftungstext steht im Geschwister-<span> außerhalb des <label>.

Dazu: Die Entitäts-Auswahl öffnet ausschließlich im click-Handler (:3181). Wer per Tab ins Feld springt und tippt, löst zwar den input-Handler aus, der bricht aber ab, weil setupSucheOffen noch null ist — sichtbar passiert nichts. role="combobox", aria-expanded und aria-controls fehlen ebenfalls.

14. Standort-Menü nicht per Tastatur bedienbar [belegt]

Im eingeklappten Zustand steht das Blatt per transform überwiegend außerhalb des Sichtbereichs, bleibt aber vollständig im DOM und im Tab-Fokus — Adresse, Route-Link und Teilen-Knopf sind fokussierbar, ohne sichtbar zu sein (kein inert, kein aria-hidden). Öffnen geht gar nicht per Tastatur: .standortmenu-griffzone ist ein <div> mit reinen Pointer-Handlern. Der Umschalter Straße/Satellit (:773) hat kein aria-pressed, sein Label bleibt in beiden Zuständen gleich.

15. disconnectedCallback() räumt nur eine von drei Karten ab [belegt]

:3815-3817 zerstört MAP, nicht aber SMAP/TMAP. Wird das Panel abgehängt, während Standort- oder Übersichtsseite offen ist, bleibt eine Leaflet-Instanz samt Resize-Listener und Kachel-Abrufen am Leben.


Klein

Ort Befund
audi-dashboard-ios.css:88, 208 main{padding:…} (0,0,1) verliert gegen main#view (1,0,1) in audi-dashboard.css:197. Auf Großbildschirmen bleibt der Seitenrand bei 20 px statt der beabsichtigten 44 px. Achtung: .standort-vollbild{margin:0 -20px} (audi-dashboard.css:704) passt heute genau dazu — beides gehört zusammen angefasst.
audi-dashboard-app.js:3190/3612 „Nur passende Sensoren anzeigen" wirkt nicht, solange ein Dropdown offen ist: Der Klick-Handler ersetzt das Overlay-DOM, bevor das change-Event des Kontrollkästchens ausgeliefert wird. [plausibel]
audi-dashboard-app.js:2966 Theme-Umschalten ruft kein render() — die Leaflet-Kacheln bleiben bis zum nächsten Backend-Update im alten Stil. Durch die neue Dauerkarte auf der Übersicht deutlich sichtbarer als früher.
audi-dashboard-app.js:804 ${de(CAR.tankPct)} % zeigt ohne Tanksensor „0 %“, während direkt daneben korrekt „Reichweite unbekannt“ steht.
audi-dashboard-app.js:496, 518, 117 Toter Code: fahrzeugGlyphPfade() nie aufgerufen, zustand.parkplatz nie gelesen, standortGenauigkeitM/standortZeit gemappt aber ungenutzt. Kommentare behaupten das Gegenteil.
audi-dashboard-app.js:595 Einzige Interpolation im neuen Code, die ohne esc() in ein Attribut geht. Heute nicht ausnutzbar, weil _zu_zahl() im Backend nur Zahlen durchlässt — als Härtung trotzdem sinnvoll, ebenso Number.isFinite in standortBekannt().

Dokumentation

AGENTS.md widerspricht sich an sechs Stellen [belegt]

Die Datei ist auf 427 Zeilen gewachsen; neue Einträge wurden angehängt statt eingearbeitet.

Stelle Aussage Widerspruch
Z. 94 „trip detection via the iPhone WLAN sensor" Z. 249 ff.: läuft über ZUENDUNG_SENSOR, WLAN „fully removed"
Z. 110 „Codec JSON → MQTT/TLS → Mosquitto" Z. 227 ff.: Schwenk auf flespi, „not MQTT at all"
Z. 93 „4 modules" tatsächlich 5 (entitaeten.py neu)
Z. 97 „3.130 lines" tatsächlich 3.873
Z. 100 einstellungen.py — the one file edited before install" genau das ersetzt jetzt das Setup-Menü
Z. 320 STANDORT_TRACKER „left empty" steht auf device_tracker.testzone_fmm003

Dazu veraltete Codeverweise: fakeTrack() liegt bei :421 statt :414, die Statistik-Behauptung in INSTALL.md bei Z. 229 statt Z. 204.

Die Datei verlangt selbst „nicht festhalten, was Code und Git-History schon zeigen" (Z. 47) — Z. 282401 sind 120 Zeilen Changelog-Prosa für fünf Einträge, und Z. 249279 dupliziert inhaltlich Z. 133153.

INSTALL.md [belegt]

  • Zirkuläre Schrittfolge: Schritt 4 verweist auf „siehe Schritt 9 zuerst" (Z. 96), Schritt 7 setzt Schritt 4 voraus (Z. 176). Die Reihenfolge 4→9→7→4 wird nirgends aufgelöst.
  • Ausgelieferte Default-Entities werden verschwiegen: ZUENDUNG_SENSOR, BATTERIE_SENSOR und STANDORT_TRACKER sind mit den testzone_fmm003-Entities der Autoren-Instanz vorbelegt. Bei einer Frischinstallation zeigen sie ins Leere. Z. 108110 behauptet nur für KM/TANK/RANGE „unbelegt".
  • Override-Datei nicht benannt: Z. 104 spricht von „einer Override-Datei" — der Pfad /config/audi_dashboard/entitaeten.json steht nirgends, und ihre fehlende Sicherung (Befund 6) ist nicht erwähnt.
  • Schritt 2 verweist auf fahrzeugprofil.example.json, deren Z. 2 weiterhin den „WLAN-Namen" verlangt, obwohl fahrzeug.wlan_name im selben Branch entfernt wurde.

WLAN-Reste in der übrigen Doku [belegt]

Im Code ist die Entfernung vollständig (keine Fundstelle). In der Doku nicht: SPECIFICATION.md (Z. 16, 147, 181, 196, 217), homeassistant/README.md:106 und die Profilvorlage nennen WLAN-Sensor und TommiG1/HA_VAG-EU-Data-Act weiterhin als aktuellen Stand.

update.ps1 [belegt]

Für www/ ist das Skript nach dem Fix vollständigaudi-dashboard-ios.css und badges/ sind ergänzt, Cache-Busting greift auch für die neue CSS-Datei.

Verbleibende Lücke: homeassistant/data/shell_beleg_parser.py ist Code, kein Datenbestand — belegverarbeitung.py:41 lädt ihn aus /config/audi_dashboard/. update.ps1 schließt data/ pauschal aus, INSTALL.md behandelt ihn als Einmal-Kopie. Änderungen am Beleg-Parser, dem einzigen getesteten Teil des Repos, kämen auf keiner Instanz an.

design/ [belegt]

dm360-host.html lädt audi-dashboard-app.js (Z. 12) und audi-dashboard-ios.css (Z. 33) — beide existieren in design/ nicht. Aus der Repo-Kopie ist das Board funktionslos; es läuft nur im Claude-Design-Projekt. Nirgends dokumentiert.

design/README.md:19 führt audi-dashboard-ios.css in der Inhaltstabelle des Ordners (die Datei liegt in homeassistant/www/) und behauptet, die Auflage „rührt audi-dashboard-app.js nicht an" — Z. 5759 derselben Datei beschreibt, dass genau dort der Stylesheet-Loader ergänzt wurde.

Markenassets: Der Diff fügt keine neuen Binärdateien hinzu. DataMetric360 Board.dc.html verwendet die vorhandenen Audi-Type-Dateien per @font-face — das Lizenzrisiko bleibt unverändert, nicht erhöht.

.gitignore [belegt]

installationspaket/ ist korrekt ergänzt und schließt nichts Getracktes aus. Es fehlt data/entitaeten.json neben den anderen drei Laufzeitdateien — heute harmlos, weil die Datei nur unter /config/audi_dashboard/ entsteht, aber inkonsistent zum eigenen Grundsatz der Datei.


Was den Branch umsetzung-datametric360 betrifft

Der flespi-Schwenk macht homeassistant/FMM003_MAPPING.md überholt. Das Dokument beschreibt Codec JSON über MQTT/TLS mit eigener CA und einem mosquitto_sub-Mitschnitt. Mit flespi läuft es über den nativen Codec8/TCP-Kanal mit IMEI-Authentifizierung, ohne Zertifikate und ohne eingehenden Port; die Feldzuordnung entstünde aus der flespi-REST-API. Beim Zusammenführen anpassen oder ersetzen.

Das CORS-Rätsel ist damit auch erklärt. Die Notiz auf main, der http:-Block sei aus der configuration.yaml entfernt worden, „nachdem HA angefangen hat, ihn zu migrieren beziehungsweise zu ignorieren", erklärt, warum cors_allowed_origins in HA 2026.8 wirkungslos blieb — auch bei gleichem Ursprung. Gehört in homeassistant/REVERSE_PROXY.md nachgetragen.

Die Falle beim Zusammenführen steht bereits in AGENTS.md dieses Branches: profil_lesen() gibt hier bei fehlender Profildatei None zurück, profil.py ist auf main unverändert und geht konfliktfrei durch — die dortigen Aufrufstellen prüfen das aber nicht.


Empfehlung

Reihenfolge nach Schaden:

  1. Befund 1 (Datenverlust) — zwei Riegel, wenige Zeilen.
  2. Befunde 2 und 5 (Zurücksetzen) — ein gemeinsamer Fix in overrides_anwenden().
  3. Befunde 3 und 4 (falsche Vorbelegung) — Index in den Vorschlag einbeziehen, Schwelle auf 5.
  4. Befund 6 (Sicherung) — eine Zeile in backup.py, plus Wiederherstellung.
  5. Befund 7 (Absicherung beim Lesen), 8 (Akku), 9/10 (Bedienbarkeit, Robustheit).

Die Punkte 1 bis 4 betreffen alle das neue Setup-Menü und lassen sich in einem Zug erledigen.