Gemessen statt geschaut: eine Pruefroutine lief auf jedem Bildschirm und
pruefte Ueberlauf, Tippziele, abgeschnittenen Text, Bilder ohne Quelle und
WCAG-Kontrast fuer jeden Textknoten. Dazu die Live-App mit echten Daten, die
Musterseite fuer Leerzustaende und das Panel zum Abgleich.
1. Deutsche Datumsangaben wurden falsch gelesen. new Date("01.03.2025")
liest amerikanisch: Tage bis 12 wurden still vertauscht, ab Tag 13 fiel
der Wert ganz weg. Die Erstzulassung stand auf zwei Bildschirmen
unterschiedlich da. alsZeitpunkt() erkennt jetzt ISO, TT.MM.JJJJ und
MM/JJJJ, weist unmoegliche Daten ab und fuehrt die Genauigkeit mit -
aus "08/2026" wird "August 2026", kein erfundener Erster.
2. Die Hauptuntersuchung war in beiden Oberflaechen unerreichbar. Das Panel
leitete sie aus der Erstzulassung ab, aber nur bei MM/JJJJ, und benutzte
den eingetragenen Wert gar nicht. Jetzt beide: eingetragene Faelligkeit
vor Servicebuch vor Erstzulassung + 24 Monate.
3. Die Tankstellenmarke stand zweimal da, wenn der Name kein Komma hat
("Shell München Ost"). ohneMarkeVorn() nimmt sie vorn ab.
4. Bilder wurden geholt, obwohl beide wussten, dass es sie nicht gibt -
fuenf 404 fuer dieselbe Datei in einem Ladevorgang. Jetzt gar keine
Adresse bei Stand 0; nachgemessen 4 Anfragen, alle 200.
5. Ein Bildelement ohne Quelle zeigte das kaputte Bildsymbol, und onerror
greift dort nicht: ohne src gibt es keinen Ladeversuch.
Dazu: leere Klammern beim Steuersatz, leere graue Kachel bei leerer
Leistungsgruppe, Umbruch auf dem Einrichtungsbildschirm, drei
Leerdarstellungen in einer Kachel, fehlende Grundschrift.
Apple HIG: Kontrast war an einer Stelle 3,18 statt 4,5, weisse Schrift auf
der Loeschflaeche 3,41/3,55. Rot als Schrift und Rot als Flaeche sind jetzt
getrennte Token (--bad / --bad-flaeche), beide Apples systemRed fuer
erhoehten Kontrast. Tippziele: unsichtbares 44x44-Overlay, wo die sichtbare
Groesse Teil des Bildes ist, echte Mindesthoehe, wo das Element Flaeche ist -
Formulare werden dadurch sichtbar hoeher.
Neu auf Wunsch: Wischen in der Bildergalerie (beide Richtungen) und die
HIG-konforme Loeschgeste - ein voller Wisch loescht ohne zweiten Tipp, ab
55 % der Zeilenbreite, mit wachsender roter Flaeche und erhaltener
Rueckfrage. Dabei fiel auf, dass der Zugwert aus dem React-Zustand gelesen
wurde und ein schneller Wisch dadurch verlorenging; er liegt jetzt in einer
Referenz.
Paritaet: alle 26 Routen und Titel decken sich, Fahrzeugstatus zeilengleich,
zwei ungeplante Abweichungen (Datumsformatierung, Herkunft der
Hauptuntersuchung) geschlossen.
tsc sauber, 271 Tests, vite build sauber, Design-System gebaut, Panel als
Modul geparst, audi_ha_test auf 2026.9.4.23 ohne Traceback. Live nachgemessen:
Datum auf beiden Bildschirmen gleich, keine 404 mehr, Zurueck-Pfeil sichtbar
34x34 und treffbar 44x44, Galerie wischt in beide Richtungen, voller Wisch
loest die Rueckfrage aus, keine Kontrast-Unterschreitung mehr.
companion-app — DataMetric360
Private Fahrzeug-App für einen Audi RS 4 Avant competition. Läuft als Web-App im Browser, als PWA auf dem Homescreen, später über Capacitor nativ auf iOS/Android und eingebettet als Iframe im Home-Assistant-Dashboard.
Kein eigenes Backend. Die App spricht direkt mit der REST- und
WebSocket-Schnittstelle von Home Assistant und ruft dieselben
pyscript.audi_dashboard_*-Dienste auf wie das bestehende Panel. Alle Daten
liegen auf dem eigenen Server; das Gerät hält nur den Zugangstoken und einen
Zwischenspeicher für die Offline-Anzeige.
Architektur: ../COMPANION_APP_ARCHITECTURE.md · Umsetzungsschritte:
../UMSETZUNGSPLAN.md · Projektstand: ../AGENTS.md
Loslegen
npm install # im Repo-Wurzelverzeichnis, nicht hier (npm-Workspace)
npm run build:ds # Design-System bauen, die App importiert aus dessen dist/
npm run dev --workspace datametric360
Beim ersten Start fragt die App nach Server-Adresse und Zugangstoken. Für die
Entwicklung setzt ../testumgebung/aufsetzen.sh eine vollständige
Home-Assistant-Instanz mit dem echten Backend auf.
Aufbau
| Ordner | Inhalt |
|---|---|
src/api/ |
Datenschicht: REST, WebSocket mit Wiederverbindung, Offline-Warteschlange, Zugangsdaten |
src/daten/ |
Fachlogik: Profil-Umrechnung, Statistik, Service-Prognose, Datenkontext |
src/screens/ |
Die 21 Seiten der App |
src/stile/ |
Layout, Bildschirmbausteine, Audi-Schrift |
src/assets/audi/ |
Schrift, Vier-Ringe, Typenschilder — lizenzpflichtig, siehe unten |
src/tests/ |
Testaufbau und Beispieldaten |
Gestaltung kommt vollständig aus @audi-dash/ui (../design-system/). Neue
Komponenten entstehen dort, nicht hier.
Prüfen
npm run typecheck # TypeScript, sehr streng (exactOptionalPropertyTypes u. a.)
npm run test # 90 Tests: Rechenlogik, Layoutwechsel, alle Seiten gerendert
npm run smoke # Adressbildung und Endpunkte, ohne Token
npm run smoke:auth # gegen die laufende Testinstanz, mit Token
npm run build # Produktionsbündel
smoke:auth liest Adresse und Token aus .env.local (schreibt
../testumgebung/aufsetzen.sh, gitignored). Ohne die Datei überspringt der
Test sich selbst, statt fehlzuschlagen.
Die Rendertests decken alle 21 Seiten in beiden Layouts ab — schmal mit Tab-Leiste, breit mit Seitenleiste.
Rechtlicher Hinweis
src/assets/audi/ enthält die Hausschrift Audi Type, das Vier-Ringe-Zeichen
und die Modell-Typenschilder. Diese sind lizenz- beziehungsweise
markenrechtlich geschützt und ausschließlich für diese eine private,
unveröffentlichte Installation freigegeben (../bauauftrag.md §8/§12).
Daraus folgt: Die App wird nur seitlich installiert, nie in einem App Store
veröffentlicht, und dieses Repository bleibt privat. ../design-system/
kommt bewusst ohne diese Dateien aus, weil es nach außen hochgeladen wird —
dort niemals Markendateien ablegen.
Die signierte App
auslieferung/App.ipa ist der fertige, Ad-hoc signierte Stand (Team
RMACS9VLS4, Profil gültig bis 29.08.2027, nur für das eingetragene iPhone).
Neu bauen: bash scripts/ios-signieren.sh - baut Webbündel, synchronisiert die
Hülle, signiert und legt die .ipa wieder hier ab.
Beim ersten Signieren fragt der Schlüsselbund um Erlaubnis. Dort „Immer
erlauben" wählen, sonst hängt xcodebuild wortlos und endet nach Minuten mit
errSecInternalComponent.
Noch offen
- Native Hülle selbst:
ios//android/(vonnpx cap adderzeugt, absichtlich gitignored) existieren in keinem Checkout dauerhaft und müssen auf einem Mac (für iOS zwingend, Xcode) neu erzeugt werden - die sichere Tokenablage (Keychain/Keystore) ist dagegen bereits vollständig angebunden (src/api/ablageNativ.ts, vonmain.tsxaktiviert) und wird automatisch aktiv, sobald die Hülle existiert - Übertragung über die Luft:
scripts/ios-luftweg.sh https://<host>erzeugt Manifest und Installationsseite; es fehlt nur noch ein Host, der den Ordner über HTTPS mit gültigem Zertifikat ausliefert (tailscale serveangedacht, dieser Mac ist dort noch abgemeldet) - QR-Einrichtung als Alternative zum Einfügen des Tokens
- Live-Ansicht der laufenden Fahrt: gebaut, aber über
src/funktionen.tsabgeschaltet, bis der FMM003 echte Werte liefert