Elf von dreizehn Phasen sind erledigt oder vorbereitet. AGENTS.md haelt
zusaetzlich die drei Fehler fest, die erst der Betrieb gegen eine echte
Home-Assistant-Instanz zutage brachte - und den verworfenen selbstgebauten
QR-Erzeuger, damit niemand den Versuch wiederholt.
PWA laeuft: Manifest, Symbole in allen noetigen Groessen und die
iOS-Angaben, die Apple statt des Manifests auswertet. Das Startsymbol ist
bewusst neutral - die Vier Ringe auf einem Homescreen waeren nach aussen
sichtbar und fielen nicht mehr unter die private Nutzung.
Vorbereitet, aber nicht ausgefuehrt: Capacitor-Konfiguration, ein
Ablage-Adapter fuer Schluesselbund und Keystore (greift defensiv auf die
Laufzeit zu, damit die App ohne das Plugin unveraendert weiterlaeuft), die
Pfad-Freigabeliste fuer den Reverse Proxy und das Geruest der
FMM003-Zuordnungstabelle.
Die QR-Seite fuer die Einrichtung war zunaechst ein Fehlgriff: Ich hatte den
QR-Erzeuger selbst geschrieben. Der Vergleich gegen eine erprobte
Implementierung zeigte 1239 abweichende Module von 3249 - der Code waere
unlesbar gewesen. Jetzt liegt eine bewaehrte Bibliothek (MIT, 57 KB) neben
der Seite im eigenen Home Assistant. Das erfuellt die eigentliche
Anforderung genauso: kein Netzzugriff, der Token verlaesst das eigene Netz
nicht. Geprueft ueber einen Umlauf - 233 Zeichen hinein, identisch wieder
heraus.
41 weitere Tests fuer Statistik, Service-Prognose und Formatierung. Die
Faelle sind entlang der Regeln gewaehlt, die beim Portieren wichtig waren:
Wochenbeginn Montag, Nachtspanne ueber Mitternacht, mengengewichteter
Durchschnittspreis statt Mittel der Einzelpreise, Plausibilitaetsfenster beim
Langzeitverbrauch, Neustart der Oelprognose ab dem letzten Wechsel samt
Zeitlimit-Deckelung, BOM und Semikolon in der CSV-Ausgabe.
Ein Test war zunaechst falsch: er verglich das UTC-Datum gegen eine
Ortszeit-Erwartung. Der Code rechnet bewusst lokal - sonst begaenne der
Monat in unserer Zeitzone einen Tag zu frueh.
companion-app/README.md auf den erreichten Stand gebracht.
Gesamt: 90 Unit- und Rendertests plus 9 Pruefungen gegen die laufende
Home-Assistant-Instanz.
Die drei Schriftschnitte stammen aus dem Panel, wo sie als base64 im
Stylesheet lagen - als eigene woff2-Dateien sind sie zwischenspeicherbar
statt bei jedem Laden erneut uebertragen zu werden. Typenschilder und Ringe
wechseln mit dem Erscheinungsbild.
Lizenzgrenze eingehalten und geprueft: design-system bleibt unveraendert und
enthaelt keine Markendateien, weil es nach aussen hochgeladen wird. Die App
darf sie nutzen, weil sie nur seitlich installiert wird.
Dabei noch eine Typungenauigkeit korrigiert: technik und ausstattung im
Profil sind Listen von Gruppen, waren aber wie die uebrigen Abschnitte als
Objekt deklariert.
Fahrzeugdaten, Batterieverlauf, Service mit Werkstatt und Servicebuch,
Reifen, die ganze Versicherungs- und Steuergruppe, Einstellungen in voller
Tiefe und die Live-Ansicht.
Portiert dazu: die eigene Oelwechsel-Prognose (rechnet ab dem letzten
Wechsel im Servicebuch neu, weil der Langzeitschnitt dafuer zu traege ist),
Kalenderdateien fuer Termine und die CSV-Ausgabe im deutschen Format.
Die Live-Ansicht ist gebaut, aber ueber einen Schalter abgeschaltet: die
Werte dafuer liefert erst der FMM003. Ein Menuepunkt mit lauter Nullen waere
schlechter als keiner.
Zwei Stellen, an denen die App bewusst zurueckhaltend ist: ein unbekannter
Pruefpunkt erscheint als hohler Ring statt als geratenes Gruen, und der
Reifen-Kilometerstand wird nie zurueckgeschrieben, weil ihn der Server
fortschreibt.
49 Tests, darunter ein Rendertest ueber alle 21 Seiten in beiden Layouts
mit Beispieldaten in der Form, die das Backend wirklich liefert.
Listen mit Jahr-Monat-Aufklappung, Detailseiten, manuelles Eintragen und
Beleg-Upload. Statistik rechnet ueber die portierten Regeln.
Zwei offene Audit-Befunde des alten Panels sind hier gleich mit erledigt:
1. Loeschen war ausschliesslich per Wischgeste erreichbar. Wer mit
Sprachausgabe oder Schaltersteuerung bedient, wischt nicht - Fahrten und
Tankvorgaenge waren fuer diese Nutzer gar nicht loeschbar. Jede Zeile hat
jetzt zusaetzlich ein sichtbares Menue, ein richtiger Knopf mit Tastatur.
2. Leaflet kam per CDN und blieb auf einem Handy ohne eigenen Internetzugang
still leer. Es liegt jetzt im Buendel (eigener Abschnitt, erst bei Bedarf
geladen).
Bewusst NICHT uebernommen: fakeTrack() aus dem alten Panel, das eine
erfundene Linie zwischen zwei Punkten zeichnete, wenn keine Route vorlag.
Solange das Fahrzeug keine Positionen liefert, sagt die Seite das - statt
eine glaubwuerdig aussehende Erfindung zu zeigen.
Erste drei Screens auf der fertigen Datenschicht. Uebersicht mit Fahrzeugbild,
Sicherungsstatus, Reichweite und Tankfuellstand, Kilometerstand samt
Service-Faelligkeit und Vorschau auf letzte Fahrt und Tankung. Fahrzeugstatus
zeigt die 16 Einzelpruefungen, wobei ein unbekannter Sensor als hohler Ring
erscheint statt als gruen geratener Punkt - dieselbe Vorsicht, die schon das
Backend walten laesst. Mein Audi buendelt Fotogalerie und Wege zu den
Unterseiten.
Dazu die geteilte Rechenlogik der Statistik portiert (Zeitraeume,
Langzeitverbrauch mit Plausibilitaetsfenster, Gruppierung nach Jahr und
Monat) und Formatierung im deutschen Format.
Bild-Komponente kapselt eine Reibung zwischen App und Bibliothek: die App
laeuft mit exactOptionalPropertyTypes, ein undefined an einem optionalen Prop
waere sonst an jeder Aufrufstelle einzeln zu behandeln.
Die App spricht jetzt echt mit Home Assistant. Ein Datenkontext buendelt die
vier Datentoepfe, haengt sich an den WebSocket-Ereignisstrom und reicht
Verbindungszustand und Warteschlange nach aussen; die Screens kennen weder
REST noch WebSocket. Ersteinrichtung prueft die Zugangsdaten, bevor sie sie
speichert, und unterscheidet in der Fehlermeldung zwischen abgelehntem Token
und nicht erreichbarem Server - zwei Faelle, die voellig verschiedene
Reaktionen verlangen.
Zwei echte Fehler, die erst der Test gegen die laufende Instanz zutage
brachte:
1. Die Typen der Datenschicht deklarierten tank_prozent, sicher_abgestellt
und sicherheit. Das Backend schreibt tankprozent, gesichert und
sicherheitscheck - die Oberflaeche haette still ueberall undefined
gelesen, ohne dass irgendetwas fehlgeschlagen waere.
2. Der Profil-Adapter reichte lebende Verweise ins Rohprofil durch. Ein
Formular haette damit den Rohstand mitveraendert und die Zusage gebrochen,
den vom Backend fortgeschriebenen Reifen-Kilometerstand nie zu
ueberschreiben. Abschnitte werden jetzt kopiert.
Ausserdem zwei Parameter-Eigenschaften in der Datenschicht aufgeloest, weil
Node sie im Strip-Modus nicht uebersetzt und genau darueber die Rauchtests
laufen.
Belegt durch neun Pruefungen gegen die laufende Instanz (Lesen, Dienstaufruf,
vollstaendiger Warteschlangenumlauf, WebSocket-Anmeldung) und 21 Unit-Tests.
Zwei Layouts aus derselben Zusammensetzung: unter 1000px Tab-Leiste unten,
darueber Seitenleiste links mit Brotkrume statt Zurueck-Pfeil. Navigation
ist wie im alten Panel ein flacher Zustand mit fester ZURUECK-Tabelle statt
eines Router-Pakets - die Verschachtelung ist hoechstens dreistufig.
Theme und Tab-Beschriftung ueberleben einen Neustart (localStorage,
abgesichert fuer den Privatmodus), Startwert folgt der Systemeinstellung.
Symbole aus dem alten Panel uebernommen, damit App und Panel gleich aussehen.
Neun Rendertests belegen die Abnahmekriterien: Layoutwechsel in beide
Richtungen, Zurueck-Ziel ueber die Tabelle, Zahnrad statt Tab-Leiste fuer
die Einstellungen, Theme-Persistenz.
npm-Workspace im Repo-Root verbindet companion-app mit @audi-dash/ui, so
dass die App die Komponentenbibliothek als echte Abhaengigkeit nutzt statt
nur in der Doku. Dazu Vite, React 18, Einstiegsdateien und eine schlanke
Grundlage-CSS, die nur enthaelt was eine App braucht und eine Bibliothek
nicht mitbringt: Vollbild, sichere Bereiche, Scrollverhalten.
Zwei Audit-Befunde des alten Panels sind hier von Anfang an beruecksichtigt:
Formularfelder mit 16px (sonst zoomt iOS Safari beim Fokus) und ein
globaler :focus-visible-Ring.
Nebenbei im design-system den Kontrastwert --fg3 nachgezogen: dort stand
noch #657081 mit 3,0:1 auf --tile, das Panel hatte den Wert laengst auf
#8a94a3 korrigiert. Ohne das haette die neue App den bereits behobenen
WCAG-Verstoss geerbt.
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.
Die urspruengliche Wegwerf-Testinstanz war verloren, weil sie nur als
Anleitung existierte. testumgebung/aufsetzen.sh baut sie jetzt vollstaendig
neu auf: Container, Nutzer, langlebiges Token, pyscript als Custom Component,
Projektdateien und nachgebildete Fahrzeugsensoren als Template-Entitaeten,
die ueber Helfer zur Laufzeit steuerbar sind.
Verifiziert: pyscript veroeffentlicht alle acht Entitaeten, Fahrzeugsensoren
liefern Werte, beide Smoke-Tests gruen.
Schrittweiser Plan fuer alle offenen Punkte inkl. Abnahmekriterien je
Schritt, Nachschlagereferenz und Definition of Done. Ergaenzt die
Entscheidungen vom 2026-08-11: kein Electron (Capacitor bzw. PWA) und
kein eigenes Backend (HA-API direkt).
Englischsprachiger Einstiegspunkt für Agent-Sessions: Statusübersicht der
drei Teilprojekte, Review-Befunde vom 2026-08-11, offene Punkte als
Checklisten, Karpathy-Regeln und Claude-Code-Praktiken als verbindlicher
Standard, plus Pflicht zur Aktualisierung bei Änderungen. CLAUDE.md
importiert die Datei per @AGENTS.md (Claude Code liest AGENTS.md nicht
nativ).
Bei all-inkl angelegt, ohne Webseite und ohne Postfach darauf. Geplante
Adresse der App: https://datametric360.app
Offen bleibt der eigentliche Schritt: die Nameserver muessen bei all-inkl
auf Cloudflare umgestellt werden, sonst kann der Tunnel darunter keinen
Hostnamen veroeffentlichen. Die Alternative, die DNS bei all-inkl zu
belassen, gibt es nur im Business-Tarif fuer 200 USD/Monat. Da auf der
Domain nichts liegt, ist die Umstellung folgenlos.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der FMM003 beherrscht Codec JSON - damit entfällt der einzige Grund, aus
dem Traccar überhaupt vorgesehen war: das Entschlüsseln des binären
Codec8-Protokolls.
Recherchiert und bestätigt: Codec JSON ist ein Datenprotokoll, kein
Transportweg; der zugehörige Transport ist MQTT, nicht ein HTTP-Webhook.
Ein eigener Broker ist vorgesehen (IP, Port, optional Anmeldung), TLS ist
dabei Pflicht. Home Assistant bringt beides von Haus aus mit: das
Mosquitto-Add-on und die MQTT-Integration samt json_attributes_topic.
Damit entfallen ersatzlos: das Traccar-Add-on, dessen H2-Datenbank samt
Sicherung, das Position Forwarding an einen HA-Webhook, der offene rohe
TCP-Port und die Alternative eines selbst geschriebenen Codec8-Decoders.
Übrig bleibt FMM003 -> MQTT/TLS -> Mosquitto -> MQTT-Integration.
Neu zu klären und in §5 aufgenommen: wie das Fahrzeug den Broker von außen
erreicht (Portfreigabe 8883 oder VPS-Broker mit Mosquitto-Bridge - Cloudflare
Tunnel hilft hier nicht, der ist auf HTTP zugeschnitten), sowie die
TLS-Zertifikate. Die Zuordnungstabelle der Fahrzeugwerte kann erst nach dem
Mitschnitt einer echten MQTT-Nachricht entstehen - die Feldnamen werden nicht
geraten.
Der bisherige Traccar-Abschnitt bleibt als Entscheidungsprotokoll stehen,
deutlich als überholt markiert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Export des Projekts "DataMetric360 App Design" nach design/ - 80 Dateien:
die beiden .dc.html-Entwurfsdateien, support.js, die verwendeten Icons,
Logos, Typenschilder und Schriften sowie das kompilierte Bündel des
Design-Systems, damit der Entwurf für sich allein darstellbar ist.
Bewusst ein Zwischenstand, nicht der Endstand: dieser Export zeigt noch
"Audi RS 6 Avant" statt des tatsächlichen RS 4 Avant competition und
enthält erst die Hauptbildschirme. Die 16 fehlenden Seiten (Fahrzeugstatus,
Batterieverlauf, Service, Reifen, Versicherung/Steuer und weitere, siehe
SPECIFICATION.md §3) sind im Design-Projekt bereits nachbeauftragt. Beides
ist in design/README.md festgehalten, damit der Stand nachvollziehbar
bleibt; der Ordner wird beim nächsten Export ersetzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>