Entfernt die letzten Verweise auf die abgeloeste TommiG1/HA_VAG-EU-Data-Act-
Integration (Versionstile, Testumgebungs-Fixture) und ersetzt sie durch die
FMM003-Werte. Behebt eine CSS-Spezifitaetskollision, durch die alle iOS-
Toggle-Switches viel zu breit gerendert wurden. Dokumentiert und behebt sieben
Layout-Befunde aus zwei Design-Audit-Runden (Zahnrad-Ueberlauf auf breiten
Bildschirmen, zu kleine Ringe als mobiler Einstellungen-Zugang, zu breite
Popups, Kopfzeilen-Versatz, ueberlappende Kachel-Pfeile, fehlender
Editierbarkeits-Hinweis bei Auswahlfeldern, Haekchen-artige Auf/Zu-Pfeile) -
siehe DESIGN_AUDIT_2026-08-13.md fuer Root-Cause und Beleg je Befund.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zwei unabhaengig vom iOS-Entscheid offene Befunde aus DESIGN_REVIEW_2026-08-13.md
§B behoben:
- .aktion (audi-dashboard-ios.css) fuellte bisher JEDE Aktion rot statt nur
destruktive - jetzt neutrale --ios-fill-Flaeche fuer die Sekundaeraktion,
neue .aktion.primaer-Regel traegt die rote Fuellung als einzige Stelle
(deckt sich mit dem Sekundaer/Primaer/Loeschen-Schema, das die Basis-CSS
schon vorgibt). Gleiche Ursache auch bei Schalter-Ein-Zustand (jetzt --ok
gruen statt rot, echtes iOS-Systemgruen) und aktiver Desktop-Sidebar-
Navigation (Flaeche jetzt neutral, Rot bleibt Text-/Icon-Akzent).
- Zwei Balkensegmente in audi-dashboard-app.js nutzten --red fuer eine
neutrale Kategorie (Arbeitsweg-Fahrten, Versicherungsbeitrag-Aufteilung) -
jetzt wie die Nachbarsegmente auf --fg umgestellt.
- .setup-popup/.standortmenu (audi-dashboard.css) hatten 20px als Literal
statt var(--r-tile) - folgen jetzt dem Token wie alle anderen Kacheln.
Im Docker-Testcontainer verifiziert: Setup-Popup, Einstellungen (mobil und
Desktop-Sidebar), Schalter - korrekte Fuellungen, keine Konsolenfehler.
Bringt die vollstaendig gebaute DataMetric360-App zusammen (React/Vite,
21 Screens, Audi-Assets, PWA + native Capacitor-Huelle, 90+9 Tests) sowie
die profil_lesen()-Haertung gegen fehlende/kaputte Profildatei zusammen.
Konfliktaufloesung:
- AGENTS.md, INSTALL.md, README.md: main-Fassung war jeweils die
chronologisch neuere, uebernommen und um die durch den Merge tatsaechlich
erledigten Punkte ergaenzt (profil_lesen()-Haertung, Audit-Reste-Entscheidung).
- fahrterkennung.py: toten WLAN-Zweig vom Branch verworfen, Zuendungs-
basierte Erkennung von main behalten.
- homeassistant/FMM003_MAPPING.md (MQTT/Mosquitto-Ansatz vom 2026-08-11,
vor der Umstellung auf flespi) bewusst nicht uebernommen - main nutzt seit
2026-08-12 flespi als alleinigen FMM003-Datenweg. UMSETZUNGSPLAN.md Phase 13
entsprechend als ueberholt markiert, verweist auf AGENTS.md als massgeblich.
- REVIEW_main_2026-08-13.md, ha_install.md (add/add): main-Fassung war die
spaetere Revision derselben Dokumente, uebernommen.
Die von REVIEW_main_2026-08-13.md befuerchtete Merge-Falle (profil_lesen()
gibt jetzt None zurueck, main-seitige Aufrufer pruefen das nicht) wurde
verifiziert als bereits entschaerft: alle 5 Aufrufstellen im gemergten Stand
(backup.py x2, fahrterkennung.py, frontend_veroeffentlichung.py,
reifenzaehler.py, tankerkennung.py) sind None-sicher.
installationspaket/ nicht Teil dieses Commits (gitignored, wird bei Bedarf
neu zusammengestellt).
Frontend, kleinere Befunde:
- Das Standort-Menue liess sich nur wischen oder ueber den Kartenmarker
oeffnen. Der Griff ist jetzt ein Knopf mit aria-expanded, damit auch per
Tastatur erreichbar; der Umschalter Strasse/Satellit hat aria-pressed und
ein Label, das den Zustand nennt.
- Der Filterschalter "Nur passende Sensoren anzeigen" wirkte nicht, solange
eine Auswahlliste offen war: der Klick-Handler ersetzte das Overlay-DOM,
bevor das change-Ereignis des Kontrollkaestchens ausgeliefert wurde. Er
wird jetzt vor dem Schliessen der Liste behandelt.
- Der Theme-Wechsel zeichnete nicht neu, die Leaflet-Kacheln blieben bis zum
naechsten Backend-Update im alten Stil - seit der Dauerkarte auf der
Uebersicht deutlich sichtbar.
- Toter Code entfernt (fahrzeugGlyphPfade, .dot.neutral) und zwei Kommentare
berichtigt, die Gegenteiliges behaupteten.
Dokumentation:
- AGENTS.md widersprach sich an sechs Stellen. Berichtigt: Fahrterkennung
laeuft ueber die Zuendung, nicht ueber WLAN; Datenweg ist flespi, nicht
MQTT; Modulzahl und Zeilenzahl stimmen wieder; Entity-IDs werden im
Setup-Menue zugeordnet, nicht in einstellungen.py; STANDORT_TRACKER ist
belegt, nicht leer.
- SPECIFICATION.md beschreibt durchgehend den Stand vor der FMM003-
Umstellung. Statt es zu Teilen umzuschreiben und dabei Ungenauigkeiten zu
riskieren, steht jetzt ein datierter Hinweis am Anfang, der die drei
geaenderten Punkte benennt und auf AGENTS.md verweist. Alles Uebrige des
Dokuments gilt unveraendert weiter.
- INSTALL.md: Die zirkulaere Schrittfolge (Schritt 4 verweist auf 9, Schritt
7 auf 4) ist als solche benannt und aufgeloest. Die Override-Datei ist mit
Pfad genannt, samt dem Hinweis, dass sie gesichert wird. Und die drei mit
Test-Entitaeten der Entwicklungsinstanz vorbelegten Rollen sind erwaehnt -
auf einer frischen Installation zeigen sie ins Leere.
- README, Profilvorlage: WLAN-Reste entfernt, zwei Falschaussagen aus dem
ersten Review nachgezogen (Statistik rechnet echt, die
97-Prozent-Volltankungsregel wurde entfernt), Dateiuebersicht um die
fuenf fehlenden pyscript-Dateien und entitaeten.py ergaenzt.
- update.ps1 liefert jetzt auch shell_beleg_parser.py aus. Die Datei liegt in
data/, ist aber Code - Aenderungen am Belegleser, dem einzigen getesteten
Teil des Projekts, kamen bisher auf keiner Instanz an.
- design/README: Zwei Dateien der Inhaltstabelle liegen gar nicht in dem
Ordner, weshalb das Board aus der Repo-Kopie heraus leer bleibt - jetzt
vermerkt. Ausserdem die Behauptung berichtigt, die Auflage ruehre
audi-dashboard-app.js nicht an: der Stylesheet-Loader wurde dort ergaenzt.
Geprueft: Panel laedt, alle neun pyscript-Entitaeten werden veroeffentlicht,
Zuordnen und Zuruecksetzen funktionieren, keine neuen Fehler im Protokoll.
Befund 9: In Telefonbreite blendet die iOS-Auflage das Zahnrad aus, die Ringe
waren dort der einzige Zugang zu den Einstellungen - als div mit
pointer-events:none aber weder fokussierbar noch fuer Sprachausgabe
erreichbar. Sie sind jetzt ein echter Knopf mit aria-label, in jeder Breite
bedienbar und unabhaengig davon, ob die Auflage geladen wurde.
Befund 10: .navmarke{display:none} stand nur in der iOS-Auflage. Ohne sie
waere der Markenklon ein sechstes Element im fuenfspaltigen Raster und die
Menueleiste zerfiele. Die Regel steht jetzt in der Basis-CSS, die
Sichtbarkeit in der Auflage - genau andersherum als bisher.
Befund 13: Das Setup-Fenster deklariert role=dialog aria-modal=true, hielt den
Vertrag aber nicht ein. Escape schliesst jetzt (Reihenfolge: Auswahlliste,
dann Fenster), der Tabulator wandert im Fenster im Kreis statt in den
verdeckten Hintergrund, und der Filterschalter hat einen zugaenglichen Namen.
CSS-Spezifitaet: main{padding} in der Auflage verlor gegen main#view in der
Basis - auf grossen Bildschirmen blieb der Seitenrand bei 20px statt 44px.
Der Rand liegt jetzt in einer Variablen, die auch der negative Rand der
randlosen Standortkarte benutzt; sonst haette deren Ausgleich nach dem Fix
nicht mehr gepasst.
Drei Anzeigefehler, im Browser gegen die Testinstanz gefunden und behoben:
ein unlesbares Datum ergab NaN/N statt eines Strichs (das Profil wird laut
INSTALL.md von Hand gepflegt, ein ISO-Datum genuegt), ein fehlender
Tanksensor ergab 0 Prozent statt unbekannt, und neben dem Typenschild stand
die Ausfuehrung doppelt, wenn sie schon im Modellnamen steckt.
Alles im echten Panel geprueft: #marke ist ein BUTTON mit aria-label, der
Markenklon ist ohne die Auflage versteckt, der Seitenrand folgt der
Variablen, und die drei Anzeigen zeigen jetzt Striche statt Rechenreste.
Befund 8: USER_POS_TS wurde nur im Erfolgsfall gesetzt. Lehnt der Nutzer die
Standortfreigabe ab, griff die 30-Sekunden-Drossel damit nie - bei einem
GPS-Tracker als Quelle waren das dutzende Hochgenauigkeits-Abfragen pro
Stunde. Der Fehlschlag zaehlt jetzt als Versuch, und die Drossel prueft auf
den Zeitstempel statt auf ein Ergebnis.
Befund 11: Das Standort-Menue hatte als einzige der vier Zeigergesten keinen
pointercancel-Handler. Uebernimmt das System die Beruehrung, blieb der
Startpunkt gesetzt und preventDefault() blockierte das Scrollen in der
ganzen App. Zuruecksetzen jetzt gemeinsam fuer pointerup und pointercancel.
Befund 12: Ein fehlgeschlagener Adressabruf setzte trotzdem den
Cache-Schluessel - fuer diese Zelle blieb es danach die ganze Sitzung bei den
blossen Koordinaten, auch wenn das Netz laengst wieder da war.
Befund 15: disconnectedCallback raeumte nur eine von drei Karten ab.
Nicht umgesetzt, mit Begruendung im Code: die Karte nur bei echtem
Ansichtswechsel neu aufzubauen. Ich hatte das zunaechst geaendert und wieder
zurueckgenommen - render() ersetzt den Inhalt per innerHTML, eine
ueberlebende Leaflet-Instanz zeigte danach auf ein abgehaengtes Element und
bliebe leer. Der Neuaufbau haengt am 20-Sekunden-Takt des Backends; das
liesse sich nur durch einen Umbau der Render-Architektur aendern.
Befund 1 (Datenverlust): Solange pyscript.audi_dashboard_entitaeten nicht
veroeffentlicht ist, liefert setupKatalog() eine leere Liste. Das Fenster ging
trotzdem auf - ohne eine Zeile, ohne Meldung - und ein Klick auf Speichern
schrieb {}. Weil overrides_schreiben() die Datei vollstaendig ersetzt, waren
damit alle Zuordnungen weg, sichtbar erst beim naechsten Neustart. Jetzt drei
Riegel: das Setup laesst sich ohne Katalog gar nicht oeffnen, Speichern bricht
bei leerer Zuordnung ab, und die Entitaet wird im Nachlade-Pfad mitgeholt -
der sie bisher als einzige der sechs ausliess.
Befund 3 (gleiche Sensoren): Der Vorschlag haengt nicht vom Index ab, also
bekamen alle vier Positionen einer Liste denselben Sensor. Der
Sicherheitscheck haette danach viermal dieselbe Tuer geprueft und Sicher
abgestellt gemeldet, obwohl drei Tueren nie geprueft wurden. Vergebene IDs
werden jetzt mitgefuehrt und uebersprungen.
Befund 4 (beliebige Sensoren): entitaetScore vergibt fuer einen reinen
Domain-Treffer bereits 3 Punkte - die Schwelle 3 war damit immer erfuellt und
belegte jedes leere Feld mit dem erstbesten Sensor der Domain, in willkuer-
licher Reihenfolge. Schwelle jetzt 5, also mindestens ein Stichworttreffer.
Geprueft mit den echten Funktionen aus der Datei: vier Tuerpositionen
erhalten vier verschiedene Sensoren, ein Bewegungsmelder wird der Zuendung
nicht mehr zugeordnet, ein Sensor mit passendem Namen dagegen schon.
Ausserdem wird die Sensor-Zuordnung jetzt im Browser-Backup mitgesichert und
beim Import wieder eingespielt.
Drei Befunde aus REVIEW_main_2026-08-13.md, alle an der Testinstanz geprueft.
Zuruecksetzen (Befund 2 und 5): overrides_anwenden() uebersprang leere Werte
und setzte nur belegte. Weil setattr das Modul-Attribut dauerhaft veraendert,
blieb ein einmal gesetzter Wert danach fuer immer stehen - bei 15 von 17
Feldern hatte Zuruecksetzen keine Wirkung, und die Oberflaeche zeigte wieder
den alten Wert, als sei das Speichern fehlgeschlagen. Umgekehrt wurde eine
Liste aus leeren Eintraegen gesetzt statt uebersprungen, was den
Sicherheitscheck mit zwoelf unbekannt-Zeilen fuellte. Jetzt wird fuer jedes
bekannte Feld geschrieben: der Override, wenn belegt, sonst der eingebaute
Standardwert. Damit ist der Vorgang zugleich wiederholbar.
Sicherung (Befund 6): entitaeten.json war weder in backup.py noch in der
Wiederherstellung noch im Browser-Export enthalten - die gesamte Zuordnung
waere nach einem Rueckspielen still weg gewesen. Jetzt ueberall dabei; fehlt
der Abschnitt in aelteren Sicherungen, bleibt die aktuelle Zuordnung stehen.
Absicherung (Befund 7): overrides_lesen() fing kaputtes JSON nicht ab. Der
Aufruf steht in beim_start() vor alles_veroeffentlichen() - eine unlesbare
Zeile liess das Panel komplett leer bleiben. Geprueft: es folgt jetzt eine
verstaendliche Meldung, alle sechs Entitaeten werden trotzdem veroeffentlicht.
Dabei ein pyscript-Fallstrick gefunden und im Code vermerkt: Generator-
ausdruecke sind nicht implementiert (not implemented ast ast_generatorexp),
Mengen-, Listen- und Dict-Comprehensions dagegen schon.
Fünf Erweiterungen des bestehenden Setup-Popups: Live-Wert neben jedem
Such-Kandidaten, Warnhinweis bei unavailable/unknown/fehlender Entität,
Duplikat-Check mit Bestätigung vor dem Speichern, Zurücksetzen-Button je
Feld (Standardwerte-Snapshot in entitaeten.py, vor jedem Override
genommen), und ein bestätigter "Jetzt neu starten"-Knopf nach dem
Speichern, falls sich eines der drei trigger-gebundenen Felder geändert
hat (neuer Service audi_dashboard_neustart). Im Docker-Testcontainer
Feld für Feld verifiziert.
Setup-Menü (Einstellungen -> Fahrzeug einrichten -> Setup): ordnet alle von
der App genutzten Sensor-Rollen echten HA-Entitäten zu, statt sie in
einstellungen.py von Hand einzutragen - durchsuchbares Dropdown je Feld,
Vorauswahl aus vorhandenen Entitäten, Schalter für "nur passende Sensoren".
Neues Modul entitaeten.py (Katalog + JSON-Override, zur Laufzeit über
setattr() auf einstellungen angewendet, kein Neustart nötig außer für die
drei trigger-gebundenen Felder).
Zusätzlich: Fahrzeug-WLAN-Erkennung und alle Entity-IDs der nicht mehr
genutzten TommiG1/HA_VAG-EU-Data-Act-Integration entfernt. Fahrterkennung
läuft jetzt über den Zündungs-/ACC-Status des neu angebundenen Teltonika
FMM003 (ersetzt die WLAN-Verbindungserkennung); Standort und 12V-
Batteriespannung kommen ebenfalls vom FMM003. Kilometerstand, Tankfüllstand,
Reichweite, Türen/Fenster/Schlösser sowie Ölwechsel-/Inspektionsdaten haben
dadurch vorerst keine Quelle mehr und zeigen "unbekannt" - die Funktionen
selbst bleiben erhalten und lassen sich über das neue Setup-Menü jederzeit
neu zuordnen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Übernimmt den in Claude Design überarbeiteten Stand der Standort-Funktion
(echte Audi-CI-Icons statt Platzhalter-SVGs, robustere Abstands-/Adress-
Anzeige, dynamisch gemessene Menü-Zugweg-Höhe) und ergänzt lokal den
Layer-Knopf so, dass er wie gewünscht zwischen Satellit (Esri World
Imagery, kostenlos ohne Key) und Straßenkarte umschaltet statt zwischen
Tag/Nacht-Theme.
Neue Kachel oberhalb von "Zuletzt" mit echter Leaflet-Mini-Karte,
öffnet per Klick eine Vollbild-Standortansicht (Kartendarstellung
wählen, auf Fahrzeug/User zentrieren, beide zeigen) mit einem
ausziehbaren myAudi-Stil-Menü: Distanz zum Gerät, Adresse (Reverse-
Geocoding via Nominatim), fährt/steht/Letzter-Parkplatz-Status,
Tankfüllstand/Reichweite, Route- und Teilen-Aktionen.
Backend: STANDORT_TRACKER-Einstellung (device_tracker-Entity) plus
_standort()-Veröffentlichung, bewusst leer gelassen bis eine echte
GPS-Quelle (FMM003/flespi) angebunden ist - Kachel zeigt bis dahin
"kein GPS-Signal". Verifiziert in audi_ha_test mit einer manuell
gesetzten Test-Position.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
audi-dashboard-app.js laedt jetzt zusaetzlich audi-dashboard-ios.css in
den Shadow-Root (zweiter <link>, rein additiv neben audi-dashboard.css).
Im Docker-Testcontainer bei 375px (Tab-Leiste unten) und 1280px (Grid mit
264px-Seitennavigation) verifiziert.
Zwei Fixes an audi-dashboard-ios.css waren dafuer noetig:
- :host-Selektoren werden von diesem Browser innerhalb von @container
verworfen (kein Fehler, die Regel fehlt einfach im CSSOM) - die alte
412px-Zentrierung aus audi-dashboard.css wird deshalb unbedingt statt
nur ab 860px aufgehoben.
- audi-dashboard-version.json hochgezaehlt, sonst liefert der Browser die
alte Datei aus dem HTTP-Cache trotz neuem Serverstand.
design/README.md dokumentiert beide Fixes fuer kuenftige Aenderungen an
dieser Datei.
Doku-Drift behoben: die Statistik-Seite rechnet laengst echt (Behauptung
stand an drei Stellen), INSTALL.md nannte in Schritt 4 vier Variablennamen,
die es nie gab, README erwaehnte die entfernte 97-Prozent-Volltankungsregel
und liess fuenf pyscript-Dateien in der Uebersicht aus. Obsoleter
TODO-Kommentar in belegverarbeitung.py entfernt.
profil_lesen() gibt bei fehlender oder beschaedigter Profildatei None
zurueck statt zu werfen; alle sieben Aufrufstellen fangen den Fall ab.
An der Testinstanz geprueft: Datei entfernt, es folgt eine verstaendliche
Fehlermeldung mit Verweis auf INSTALL.md statt eines Tracebacks pro
Trigger-Durchlauf, Home Assistant laeuft normal weiter.
Drei zusammengehörige Teile in einem Repository:
- homeassistant/ Das fertige, im Einsatz befindliche Home-Assistant-Panel
(panel_custom Custom Element + pyscript-Backend). Echte Fahrzeug- und
Personendaten (fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl,
Tankbelege) bleiben per .gitignore außen vor; die anonymisierte Vorlage
fahrzeugprofil.example.json ist mit dabei.
- design-system/ Eigenständige React-Komponentenbibliothek (@audi-dash/ui),
die die visuelle Sprache des Panels nachbildet - ohne Audi-Markenzeichen
und ohne die lizenzierte Hausschrift. Dient als Grundlage für Claude
Design. War bis hierher ein eigenes Repository und ist in dieses
eingeschmolzen worden.
- companion-app/ Datenschicht der neuen App DataMetric360 (iOS/Android via
Capacitor, zusätzlich als Iframe im HA-Dashboard). Noch ohne Oberfläche:
REST- und WebSocket-Zugriff auf Home Assistant plus Warteschlange für
Änderungen ohne Netz. Ersetzt das eingespritzte hass-Objekt, das nur
innerhalb des HA-Frontends existiert.
Dazu die Projektdokumentation: SPECIFICATION.md (Ist-Stand des Panels),
COMPANION_APP_ARCHITECTURE.md (Architekturentscheidungen der neuen App),
AUDIT_2026-08-10.md, DESIGN_BRIEF_DATAMETRIC360.md und der ursprüngliche
Bauauftrag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>