Die zusammengefuehrte Kachel war zerlegt: ich hatte den Wrapper
.dm-abschnitt genannt, den Namen gibt es aber schon - als Flex-Zeile mit
space-between (bausteine/FahrtDetail/TankDetail). Der Kachelinhalt lag dadurch
nebeneinander statt untereinander, der Knopf lief aus der Kachel. Der neue
Wrapper heisst .dm-kachelabschnitt, die bestehende Klasse bleibt unberuehrt.
Gefunden hat es der Eigentuemer, nicht ich: ich hatte nach dem Umbau die
Abstaende der eingesetzten Probe gemessen, aber nie die Kachel selbst
angesehen.
Dazu auf seine Vorgabe: statt "Integration ist aktuell (Zeitpunkt)." steht
jetzt ein gruenes "aktuell" direkt unter dem installierten Stand, der
Zeitpunkt gedaempft daneben. Wurde NIE geprueft, steht dort gar nichts mehr -
gruen "aktuell" waere ohne Pruefung eine Behauptung ohne Grundlage, und der
Knopf "Auf Update pruefen" sagt den Zustand ohnehin. In beiden Codebasen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ohne feste Breite bemisst sich jedes Feld nach seinem eigenen Inhalt, die
rechte Kante steht fest, und die linken Kanten fransen aus: gemessen
216/202/195/206 in der App und 220/209/203/213 im Panel.
Jetzt 180px in beiden. Der Wert ist die engste Grenze beider Oberflaechen -
das laengste Label ("Erstzulassung") laesst in der App nur 183px fuers Feld,
im Panel 196px.
Vorbehalt: von elf Modell-Eintraegen ist einer laenger als der verbleibende
Textplatz ("RS 6 Avant performance", 182px gegen 142px) und wird ausgewaehlt
abgeschnitten. In der aufgeklappten Liste steht er vollstaendig.
Nachgemessen in beiden: vier Felder je 180px, gleiche linke Kante, kein Label
bricht um.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Abstand zwischen Kachelueberschrift und erster Inhaltszeile war 0, 10 oder
12px, je nachdem ob das folgende Element einen eigenen oberen Rand mitbrachte.
Bei 0 klebte die Ueberschrift an der Zeile und las sich als deren Beischrift.
Jetzt einheitlich 14px, gesetzt am Kopf selbst - benachbarte Raender fallen
zusammen, vorhandene 10/12 werden also angehoben statt addiert, und absolut
gesetzte Nachbarn wie das Zahnrad bleiben unberuehrt. Nur die erste
Beschriftung einer Kachel: .label/.ads-eyebrow tragen auch Inhaltszeilen wie
die Anschrift des Autohauses, die bleiben unveraendert.
Der urspruengliche Auftrag lautete "Panel wie App setzen" und beruhte auf einer
Falschaussage von mir: ich hatte die 10px-Grossschrift aus dem Design-System
gelesen statt die App zu messen. Die App ueberschreibt sie dort absichtlich auf
den Panel-Wert; beide waren laengst identisch.
Dazu: _profil_aufraeumen() entfernt ausgemusterte Profilfelder einmalig beim
Start, Anlass ist fahrzeug.hauptuntersuchung_faellig. Ohne das bliebe der tote
Schluessel fuer immer stehen, weil beide Oberflaechen das Profil vollstaendig
zurueckschreiben. An der Testinstanz geprueft, einschliesslich zweitem Start
ohne Schreibvorgang.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Musterseite entfernt (companion-app/muster, vite.muster.config.ts,
/config/www/dmmuster). Ansage des Eigentuemers: sie fuehrt nur zu neuen
Fehlerquellen. Ausloeser war ein Befund, den ich als App-Fehler gemeldet hatte
- Ringe und Typenschild schwarz auf schwarz - und der nur dort bestand.
Behoben:
* Das Zahnrad im Autohaus-Kasten hatte seine Ecke verlassen (58/288 statt
8/8). Ursache war mein HIG-Durchgang von gestern: .zahnrad kam in die
Gruppe fuer die 44x44-Trefferflaeche und bekam damit position:relative,
was das absolute aus dem Basisblatt ueberschrieb. Die Auflage war
ueberfluessig - .zahnrad ist dort schon 44x44.
* Das Fotomenue hing mit position:absolute an der Kachel statt am
Bildschirm und lag bei der hohen Raeder-Kachel ausserhalb des Sichtfelds;
einen Abbrechen-Knopf hatte es nie. Das Panel benutzt jetzt dasselbe
Aktionsblatt wie die App. .bildmenu ist samt Zustand, Markup, totem
Handler und CSS entfernt.
* Der Blattkopf las sich als dritte Auswahl (linksbuendig, 15px, --fg).
Jetzt zentriert, 13px, gedaempft - Apples Muster, in beiden Codebasen.
* "Anstehende Termine" stand 5px ueber "Oelwechsel" und wirkte als dessen
Beischrift. Entfernt.
* Wartungsplan-Formular: Art nach oben, Datum 124px statt Browser-Vorgabe,
Werkstatt ueber die volle Zeile (218 -> 306px), Kosten 116px. Zwei
Erklaertexte entfernt.
* Thema folgt jetzt einer Systemumstellung im laufenden Betrieb. Vorher las
es prefers-color-scheme genau einmal beim Laden. Drei Tests, die ohne die
Behebung nachweislich fallen.
Geprueft: 295 App-Tests, Panel node --check, 0 Tracebacks, alle Aenderungen
live an der Testinstanz gemessen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Der Kasten "Kein GPS-Signal vom Fahrzeug" liegt auf Leaflets eigenem
Hellgrau, und das ist in beiden Themen hell. --tile ist im Nachtmodus ein
durchscheinender weisser Schleier - er macht die Flaeche dort noch heller,
waehrend der Text der Nacht-Palette folgt: gemessene 2,45:1, deutlich
unter den 4,5:1 dieses Projekts.
Deckender Kasten plus Zweitfarbe, in beiden Codebasen. Live nachgemessen,
identische Werte: 9,86:1 nachts, 10,94:1 tags.
Kein Gleichlauf-Befund, sondern eine gemeinsame Schwaeche - deshalb auf
Nachfrage vorgelegt und erst nach Freigabe geaendert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Scanner liest den QR jetzt auch aus einer gespeicherten Bilddatei -
in der Testumgebung ohne Kamera der einzige Weg, auf dem Telefon der
kuerzere (der Token entsteht am Rechner, das Bildschirmfoto liegt ohnehin
auf dem Geraet). Gleicher Leser, gleiche Deutung, nur eine andere Quelle;
ohne Kamera entfaellt das schwarze Quadrat.
Dabei ein echter Fehler in der ersten Fassung, gefunden an der
Musterseite: img.decode() loest bei einem GIF in Chromium nie auf - das
Blatt haette ohne Meldung ewig gewartet. Jetzt createImageBitmap, als
Rueckfall bewusst das load-Ereignis statt decode().
Debug-Mode ist nur noch ein stiller Textknopf am Seitenende, ohne Kachel
und ohne Erlaeuterung; der Zugang zu Home Assistant steht als Akkordeon in
der Kachel "Zugaenge" darin. Beides auf Vorgabe des Eigentuemers.
Die Musterseite kann jetzt auch die Ersteinrichtung (?seite=einrichtung) -
damit ist der ganze Weg ohne echten Token nachgewiesen: selbst erzeugter
QR mit Token-Text landet zeichengleich im Feld, einer mit http-Adresse im
Adressfeld, ein Bild ohne Code meldet das sauber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Debug-Mode: Zugaenge und Dongle stehen nicht mehr verstreut oben in den
Einstellungen, sondern zusammen hinter einem Schalter am Seitenende - dazu
neu der letzte Datensatz des Dongles (geraet.py). "Letzter Datensatz" heisst
dabei: alle Entitaeten des Geraets, deren Aktualisierung hoechstens zwei
Sekunden nach der juengsten liegt - die flespi-Integration setzt einen
Datensatz in Millisekunden. Angezeigt mit Ankunft, Geraetezeit und dem
Rueckstand zwischen beiden.
Beim Verifizieren gefunden: app_version_veroeffentlichen() lief nur beim
Start und nach einer Aktion, und beim Start haben die Entitaeten des Geraets
noch keinen Zustand - die Kachel waere dauerhaft leer geblieben. Laeuft
jetzt im Minutentakt mit, ohne Netzaufruf.
Ausserdem:
- "Version" und "Integration-Update" sind eine Kachel
- Speichern/Verwerfen als zwei gleich breite Knoepfe, der bestaetigende
gefuellt und rechts; "Verwerfen" war in der App blosser Text
- Bilder werden nach dem ersten Zeichnen in der Leerlaufzeit vorgeladen UND
dekodiert. Die Verzoegerung beim Seitenwechsel kam nicht vom Netz (31 Tage
Cache), sondern vom asynchronen Dekodieren eines frisch erzeugten <img>.
214/214 Tests, Panel als Modul geparst, live gegen audi_ha_test geprueft.
Sieben Meldungen des Eigentuemers, beide Codebasen.
Karte im Einzelbeleg: "Position laedt nicht" und "der Button funktioniert
nicht" waren dieselbe Stelle - ohne aufloesbaren Ort malte das Panel einen
beliebigen Ausschnitt und liess den Zentrieren-Knopf fuer immer disabled.
Beide zeigen jetzt die Auskunft statt einer Karte und unterscheiden dabei
"steht nicht im Beleg" von "findet niemand". Dazu ein echter Paritaetsmangel:
die App schlug nur station_address nach, das Panel faellt seit jeher auf den
Namen zurueck - von 16 Testbelegen tragen vier eine Anschrift.
Der Suchbegriff darf Name und Anschrift NICHT zusammensetzen: gemessen findet
Nominatim "Pascalstr. 8, 85057 Ingolstadt", mit dem Betreibernamen davor
nichts. Jetzt zwei Kandidaten nacheinander (Anschrift, dann Name); fuer den
Kartendienst dagegen beides zusammen, weil Apple und Google Betriebsnamen
kennen.
Tankstelle steht ueber die volle Kachelbreite, zweizeilig (Tankstelle und
Strasse / Ort) und fuehrt beim Tippen in den Standard-Kartendienst - Apple
Karten auf Apple-Geraeten, sonst Google Maps. Dieselbe Wahl jetzt auch fuer
Fahrzeugstandort und Autohaus.
SmartDeal-Ersparnis brach um, weil die dt-Spalte 150,00px breit war und ihr
Inhalt 150,20px - zwei Zehntel Pixel, Zeile dadurch 44,8 statt 26,4px hoch.
Der Regler "Fahrt beenden" schreibt nicht mehr beim Loslassen: derselbe Wert
stellt den Schlaf-Timeout des Dongles, das soll bewusst ausgeloest werden.
Speichern/Verwerfen erscheinen nur bei echter Aenderung.
Share-Erweiterung: an der ausgelieferten .ipa gemessen trug sie 1.0, die App
2026.9.3.3 - iOS registriert eine Erweiterung mit abweichender Versionsnummer
nicht, sie fehlt dann im Teilen-Blatt. ios-signieren.sh schreibt die Version
jetzt in beide Ziele und liest die fertige .ipa gegen. Zwischenablage: dritter
Weg ueber UIPasteboard.itemProviders, und ein fehlender nativer Teil wird als
solcher gemeldet statt als "Kein Zugriff".
Am Geraet gesetzt: 1003 Network Ping Timeout 0 -> 60 s, 1004 ACK Type
TCP/IP -> AVL. Beide liegen bei flespi als pending bereit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vier Themen aus einer Sitzung.
1. Die Fahrt endet wieder bei uns statt im Dongle (Abschnitt BW). Der
Ignition-OFF-Timeout des FMM003 (900 s) und sein Schlaf-Timeout (ebenfalls
900 s) starten beide beim Zuendungs-Aus und fallen in derselben Sekunde -
am 02.09. zweimal beobachtet, einmal ging das Trip-Ende verloren, einmal kam
es eine Sekunde vor dem Schlaf an. Ausloeser ist jetzt die Zuendung, die
Wartezeit laeuft in Home Assistant. ZUENDUNG_NACHLAUF_S = 180 wird in beiden
Wegen abgezogen (ueber das Trip-Signal 1080 s, weil dessen Ende selbst an der
verzoegerten Zuendung haengt).
2. Schieberegler, neu in beiden Codebasen. Schrittweite 5 Minuten; der Daumen
war im Tagmodus weiss auf weiss und traegt jetzt einen Ring aus
--line-strong - ein Token, das genau dort sichtbar ist, wo es gebraucht wird.
3. Knopf "Fahrt beenden" in der Zuletzt-Kachel (Abschnitt BX). Schliesst auf
das letzte Lebenszeichen, nicht auf "jetzt", und kennzeichnet das Ende als
vorlaeufig. Ein spaet eintreffendes Zuendungs-Aus zieht es nach - innerhalb
von sechs Stunden, nur nach vorn, und nur bei einer vorlaeufigen Fahrt.
ts_end wandert bewusst NICHT in edited_fields, sonst blockierte der Schutz
fuer Handeingaben genau diese Korrektur.
4. Das OTA-Buendel kann auf dem Mac gar nicht entstehen (Abschnitt BV):
npm run ota ist eine Windows-PowerShell-Datei, ios-signieren.sh baut ein
frisches dist/ und fasst das Buendel nie an. Ausgeliefert war deshalb eine
Oberflaeche ohne den Versionshinweis unter richtiger Nummer.
Verifiziert: Backend 27/27 (5 Signalwechsel, 14 Zuendungspause, 8 Fahrtende),
companion-app tsc sauber und 179/179, Panel als Modul geparst, audi_ha_test auf
2026.9.3.7 sauber gestartet. Live am laufenden Panel und ohne Rueckstand
belegt: Wartezeit samt Abbruch, die 180-s-Rechnung, der Regler im Tagmodus und
der Knopf von der laufenden Fahrt bis zum verworfenen Kurzvorgang - Fahrten
vorher 16, nachher 16.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
KOEPFE. Jahr und Monat tragen dasselbe Format (13px, Zweitfarbe, gemischt) -
vorher drei Elemente in drei Formaten. Die Versalien aus .20 waren falsch: das
ist der iOS-Stil vor 13. Vom Eigentuemer aus drei gerenderten Vorschlaegen
gewaehlt.
ZEILEN. padding-left 20px statt 0 - die Spalte des Aufklapp-Pfeils, damit die
Zeilen auf derselben Kante stehen wie der Text der Koepfe. Nachgemessen bei
375px: Beschriftungsspalte 157px, laengster Ortsname 142,7px.
GALERIE. Der gezeigte Platz ueberlebt den Seitenwechsel - er lag in der
Komponente und starb mit ihr. Im Panel ist er seit jeher modulweit.
KALENDER. Jeder Termin hiess "-.ics": in dateiname() fehlte das \w in der
Zeichenklasse, es ueberlebten nur w/ae/oe/ue/ss und der Bindestrich. Zwei
Termine ueberschrieben einander damit. Jetzt mit Umschrift und Rueckfall, und
ueber Share.files statt Share.url.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TERMIN. Der Werkstatttermin wanderte bisher ins Fahrzeugprofil, stand als
Merkmal an der Karte und liess sich "verwerfen" - eine zweite Verwaltung neben
dem Kalender. Auf Ansage entfernt: er dient jetzt allein dem Kalendereintrag
"was, wann, bei welcher Werkstatt". Dabei aufgefallen: die App schrieb gar kein
LOCATION in die .ics, obwohl das Panel es seit jeher setzt.
Ohne Speicherung startete das Feld leer ("tt.mm.jjjj", so gemeldet). Es
schlaegt jetzt die Faelligkeit der gewaehlten Art vor, sonst heute - dafuer
liefert service.ts serviceKandidaten(). "Andere" ergaenzt die Auswahl.
BREITEN. Am laufenden Panel gemessen: die vier festen 132px-Datumsfelder
brauchen ab 140px, damit die letzte Ziffer nicht unter dem Kalendersymbol
liegt (jetzt 150px); die Art-Auswahl braucht 178px fuer
"Hauptuntersuchung" (jetzt 190px). In der App war nichts davon kaputt - eine
dort vorsorglich eingebaute Breite ist wieder entfernt.
LISTEN. Fahrten- und Tankliste verloren 58px an tote Breite: 22px Einrueckung
der Monatsebene plus 40px linkes Polster der Zeile. Auf dem Telefon brach
"Eichstaett -> Adelschlag" deshalb um. Apples Richtlinien gruppieren ueber
Abschnittskoepfe statt Einrueckung; die Zeilen stehen jetzt alle auf derselben
Kante (34 statt 96px), der Monat traegt Versalien und Sperrung und liest sich
als Kopf. Beschraenkt auf .liste/.dm-liste - anderswo ist das Polster gewollt.
BILDER. Die Draufsicht ist aus der Galerie genommen (nurStatus), gehoert aber
weiter in die Auswahl der Einstellungen: nur dort laesst sie sich hochladen.
Die Galerie schneidet Fotos nicht mehr an - die Frontansicht verlor unten die
Stossstange.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gemeldet vom Eigentuemer an der realen Instanz, in einem Zug abgearbeitet.
STATISTIK. "Monat kleiner als Woche" war kein Rechenfehler, sondern die
Definition: am 02.09. begann die Kalenderwoche am 31.08., der Monat erst am
01.09. Umgestellt auf rollende Fenster (1/7/30/365 Tage), damit 1 ⊂ 7 ⊂ 30 ⊂
365 an jedem Tag gilt. "Jahr" meint damit nicht mehr das Kalenderjahr - so
entschieden. Zwei neue Tests halten die Verschachtelung fest.
Aus dem Langzeitverbrauch sind Herleitung und Erklaerabsatz aus der ANSICHT
genommen, nicht aus der Rechnung; das Datum des letzten Tankstops ebenfalls.
UEBERSICHT. Unter "Letzter Tankvorgang" steht das Datum statt der Tankstelle.
BILDER. Die Draufsicht war der einzige sichtbare Bildplatz ohne Zugang -
bilder.py kannte den Dateinamen, BILDER/BILDPLAETZE nicht. Jetzt ein Platz wie
jeder andere. Die Vorschau in den Einstellungen schneidet Fotos nicht mehr an,
und der Bildbereich der Fahrzeugseite steht eingerueckt statt randlos.
ZAHNRAD. Es lag mit seiner 44px-Trefferflaeche 21px im Kachelinhalt und fing
die obere Haelfte des ersten Knopfes ab (Versicherung, "Inland"). Die Kopfzeile
bekommt jetzt die Hoehe, die es braucht.
SCREENING. Lief ausschliesslich bei einer Aenderung des Kilometerstands, also
nur waehrend der Fahrt - im Stand blieben Ortsnamen und Verbrauch liegen. Jetzt
zusaetzlich einmal nach dem Start, und danach faellt es selbst nach, solange
ein Lauf sein Ortsbudget aufbraucht UND dabei etwas aufloest. Kein Dauertakt:
die Kette endet, sobald ein Lauf mit uebrigem Budget durchkommt.
GESTEN. Zum Loeschen nach links wischen, jetzt auch im Radarchiv (das Panel
hatte die Mechanik, das Archiv war nie angeschlossen; die App hatte sie gar
nicht). Vom linken Rand nach rechts wischen = zurueck, jetzt auch in der App,
mit denselben Zahlen wie im Panel und in beiden mit sichtbarer Rueckmeldung.
CI-SYMBOLE. Das Kachel-Zahnrad ist settings-s - im Panel stand der Pfad
sechsmal wortgleich im Markup, jetzt einmal als CI.settingsS. Das
handgezeichnete Zahnrad der Seitenleiste ist ersetzt und geloescht. Die
Zapfsaeule des Tanken-Reiters ist fuel-station-s, Faktor 0,84 um die
Rastermitte - live per getBBox() gemessen, damit sie auf dieselbe senkrechte
Spanne kommt wie Statistik.
Zurueckgenommen: die Titel der Unterseiten stehen wieder mittig. Zentriert ist
Apples HIG fuer Navigationsleisten; die linksbuendigen Titel sind die der
Hauptbereiche und folgen der anderen Regel.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ortsauflösung serverseitig (geokodierung.py): der Ort steht jetzt in der Fahrt
statt im Zwischenspeicher jedes Geräts. Beide Oberflächen fragen nichts mehr ab.
Verbrauchskorrektur (verbrauchskorrektur.py): Faktor = Beleg-Liter / Summe der
Einzelfahrten, voll zu voll. Statt einer Schranke am Faktor wird der Nenner
geprüft - decken die erkannten Fahrten 90-110 % der Tacho-Spanne ab? Ausgelöst
beim Schreiben eines Tankvorgangs, nicht erst bei der nächsten Fahrt.
Radzähler: summiert die Fahrten des montierten Satzes statt Tacho-Deltas. Der
alte Weg hatte Fahrzeugwechsel als gefahrene Strecke verbucht (375.962 km bei
einem Tacho von 61.823).
Null heißt unbekannt: ein Kilometerstand von 0 oder ein leeres Feld werden zu
None normalisiert, statt an sechs Lesestellen als "Tachostand null" zu gelten.
Momentanwerte der Sensoren gelten nur für einen Tankvorgang von jetzt.
Oberfläche, beide Codebasen: Wertespalte der Fahrtenliste ausgerichtet, Ort ->
Ort in "Zuletzt", "Räder" statt "Reifen", "Termin vereinbart" entfernt,
Markenlogo 20 % größer, Übersicht-Symbol auf volle Rasterbreite.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DER VERBRAUCH WAR SYSTEMATISCH ZU HOCH
Der Startwert kam aus wert_bei(), also dem letzten Literstand VOR der Fahrt -
und das ist im Stand der Wert vom Ende der VORIGEN Fahrt. An der Fahrt
Eichstaett - Adelschlag nachgemessen: 36,4 l um 13:52 (Ende der vorigen Fahrt),
36,2 l um 16:20:49 (erster Datensatz der neuen). In der Standzeit dazwischen
ist niemand gefahren; diese 0,2 l Setzung wurden der neuen Fahrt zugerechnet.
alt: 36,4 - 35,6 = 0,8 l auf 6,896 km -> 11,6 l/100 km
neu: 36,2 - 35,6 = 0,6 l auf 6,896 km -> 8,7 l/100 km
Neu wert_ab() in verlauf.py: der erste Wert AB dem Zeitpunkt. Fuer einen
ZAEHLER ist "zuletzt davor" richtig (der Kilometerstand aendert sich im Stand
nicht), fuer einen gemessenen FUELLSTAND nicht - der driftet. Das Fahrtende
bleibt bei wert_bei(). Livepfad und Rueckblick benutzen beide die neue
Funktion.
Bereits gerechnete Fahrten behalten ihren Wert: _verbrauch_screenen() fuellt
nur fehlende. Die Neuberechnung kommt mit dem Korrekturwert aus den
Tankvorgaengen, den der Eigentuemer vorgeschlagen hat.
ANZEIGE
Hoechstgeschwindigkeit ohne Nachkommastelle. Statuswort raus aus der
Fahrtenliste - "vollstaendig" sagt dem Nutzer nichts, und "offen" verspricht
Daten, die bei einer laengst abgeschlossenen Fahrt nie mehr kommen; fehlt ein
Wert, steht dort ein Strich.
Strecke und Verbrauch stehen jetzt in einer Spalte: die Wertspalte wuchs mit
dem Inhalt, gemessen 86px gegen 37px, und die Zahlen standen versetzt. Feste
Mindestbreite in beiden Oberflaechen, nachgemessen alle Zeilen 92px.
Verifiziert: py_compile, Panel als Modul, tsc --noEmit sauber, 165/165 Tests,
wert_ab() gegen vier Randfaelle, im Browser nachgesehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tuer- und Fenstersensoren haben vier Positionen, aber nur einen Beispielnamen
(front_left_door). Der beschreibt die erste; die anderen drei koennen ihn nie
enthalten. Folge: nur die erste Position konnte gruen werden, und im Kopf
stand ein Erwartungswert, der fuer drei von vier Zeilen nicht galt.
Neu "beispiele" je Position im Feld-Katalog und feldBeispiel(feld, idx) im
Panel. Der Erwartungswert steht jetzt an jeder Position statt im Kopf -
rechtsbuendig, in der kleinen grauen Schrift des Positionslabels. Auch die
Sortierung der Vorschlagsliste nutzt ihn, sonst stuende in allen vier Zeilen
dieselbe Entitaet oben.
Typografie: .setup-feld-hinweis ist fuer die Kopfzeile gebaut (14px, --fg,
rechtsbuendig, max-width 55%). Im 12,5px-Positionslabel wirkt das falsch herum.
Eine Regel im Kontext .setup-unterfeld-label .setup-feld-hinweis laesst Groesse
und Farbe erben; die Rechtsbuendigkeit kommt aus justify-content: space-between
am Label, wie eine Ebene darueber bei .setup-feld-kopf.
Verifiziert: alle acht Positionen tragen ihren eigenen Beispielnamen,
py_compile und Panel als Modul sauber, audi_ha_test ohne Fehler gestartet.
Die Darstellung selbst habe ich nicht im Browser gesehen - das Panel liess
sich in der Testinstanz nicht ansteuern.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Passt die zugeordnete Entitaet zum Beispielnamen der Rolle (FELDER-Schluessel
"beispiel"), faerbt sich das Feld leicht gruen. Dieselbe Pruefung, die
entitaetScore() ohnehin mit 8 gewichtet - hier nur fuers Auge, damit man eine
richtig belegte Rolle sieht, ohne den langen Entity-Namen Zeichen fuer Zeichen
mit dem Beispiel daneben zu vergleichen.
Bewusst nur ein Hinweis, keine Bedingung: Installationen mit anderer
Datenquelle haben andere Namen und sind trotzdem richtig zugeordnet. Deshalb
gruen als Bestaetigung, aber kein Rot und keine Warnung, wenn es fehlt. Und
nicht waehrend gesucht wird - dann steht die Sucheingabe im Feld, nicht die
Zuordnung.
Die Farbe kommt per color-mix aus dem vorhandenen --ok-Ton und dem Feldgrund
statt aus einem eigenen Gruen, damit sie in beiden Themen ruhig bleibt.
"Auf Standard zurueckstellen" entfernt (Wunsch des Eigentuemers): Knopf,
Symbol, Zuhoerer, CSS und der nur dafuer vorhandene Helfer setupStandardwert().
Keine verwaisten Verweise mehr im Quelltext.
Panel als Modul geparst, Bundle und Manifest auf 2026.9.1.11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ZUENDUNG_SENSOR liegt jetzt auf dem Trip-Signal des FMM003 statt auf dem rohen,
prellenden Zuendungseingang. Damit kommt die Pausentoleranz vom Geraet - eine
Fahrt beginnt erst bei Zuendung UND Bewegung UND Start Speed.
MINDESTDAUER_S wandert nach verlauf.py und gilt jetzt auch im Livepfad. Vorher
verwarf nur der Import Zuendphasen unter 60 s; live entstanden daraus am 31.08.
elf Fahrten mit 0 km, zwei davon mit null Sekunden Dauer.
Das Panel erfand einen Literpreis von 0,00 EUR, wenn die Kosten noch nicht
feststanden (null/liter ist 0 in JavaScript) - neue Hilfsfunktion literpreis()
prueft beides, wie die App seit jeher. schnittpreis() teilte ohne Nennerpruefung
und konnte "NaN" oder "unendlich" anzeigen.
Der Setup-Dialog ist wirklich modal: die Tab-Leiste hatte einen eigenen Zuhoerer
vor der Sperre und liess einen Tabwechsel bei offenem Fenster zu.
Verwaister Code entfernt: drei Funktionen und vier Regeln im Panel, 20 Regeln in
der App.
Offen bleibt allein die leere Erstzulassung - eine Angabe, keine Aenderung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die App blieb nach einem Neustart von Home Assistant auf dem alten Stand
stehen, mit einer 502-Fehlerzeile, die erst ein Beenden der App wegbekam.
Zwei Ursachen: 502/503/504 galten als harter Ladefehler statt als "Server
faehrt gerade hoch", und nach dem Wiederverbinden wurde genau einmal
nachgeladen - schlug das fehl, kam nie wieder ein Versuch. Beides behoben,
vier Regressionstests dazu.
OTA: das Buendel ist von HEAD ueber die Platte bis zu den ausgelieferten
Bytes nachweislich deckungsgleich. Die Fassung haengt jetzt trotzdem als
?v= an der Adresse (der statische Pfad kommt ohne Cache-Control, aber mit
ETag), und ein Pruefsummenfehler wird erklaert statt durchgereicht.
Statistik: der Gesamtwert steht jetzt als grosse Zahl in der Kopfzeile,
darunter bleiben vier Spalten - fuenf passen auf dem Telefon nachweislich
nicht in eine Zeile.
Fahrzeugfoto ohne Beschnitt und ohne Bodenschatten, damit auch ohne den
Schalter dafuer. Setup filtert zusaetzlich nach dem Signalnamen aus dem
Katalog.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der 15-Minuten-Timer war doppelt: der FMM003 wartet laut Konfiguration
(Trip \ Odometer, Ignition OFF Timeout) selbst 900 s, die App noch einmal
15 Minuten. Zusammen eine halbe Stunde. Die Pausenregel ist damit entfallen -
in der Live-Erkennung, im Historienimport und in beiden Oberflaechen. Der
Schwellwert "ab wann ist es ein Parkplatz" hing an derselben Einstellung, hat
damit aber nichts zu tun und steht jetzt als eigene Zahl.
Hoechst- und Durchschnittsgeschwindigkeit je Fahrt. Der Durchschnitt folgt aus
Strecke und Dauer, vmax aus der neuen Rolle GESCHWINDIGKEIT_SENSOR - laut
Konfiguration liest das Geraet die Geschwindigkeit vom OBD/CAN. Es ist der
groesste gemeldete Wert, nicht die tatsaechliche Spitze: alle zehn Sekunden
ein Datensatz. So ist es auch beschriftet.
Der Langzeitverbrauch war um einen ganzen Tankinhalt zu hoch. Gemessen wird
die Strecke ZWISCHEN erstem und letztem Tankstop; verbraucht wurde darauf,
was ab dem ZWEITEN hineinkam - der erste fuellte die Strecke davor. Bei 13
Tankvorgaengen rund 8 Prozent, im Testfall 16,7 statt 8,3 l/100 km. Der Test
hatte die falsche Rechnung festgeschrieben und ist mitkorrigiert. Eine
negative Strecke (falscher Kilometerstand an einem Tankvorgang) gilt jetzt
als unplausibel statt als Null ohne Erklaerung.
Verbrauch je Fahrt bekommt Grenzen: am Sensor nachgemessen loest
can_fuel_volume 0,1 l auf, ein Schritt entspricht also 10/Strecke l/100 km
Fehler. Unter 3 km sagt die Differenz nichts mehr, ueber 60 l/100 km ist es
kein Verbrauch.
Statistik: zusaetzlich "Absolut", und die Einheit steht jetzt in eckigen
Klammern an der Rubrik statt vier Mal am Zeitraum. Fuenf Spalten passen auf
einem Telefon nicht nebeneinander, das Raster bricht um.
Radfoto in Reifen war ein reines <Bild> - Ersetzen und Loeschen von dort aus
gar nicht erreichbar. Jetzt BildMitMenue wie im Panel.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Share-Erweiterung: ein PDF aus Mail landet ueber Teilen -> DataMetric360 als
Tankbeleg. Alles Native liegt versioniert unter companion-app/native/, weil
ios/ gitignored ist und npx cap add ios es sonst wieder frisst;
scripts/ios-teilen-einrichten.mjs haengt es bei jedem Bau ins Xcode-Projekt
und ist in ios-signieren.sh eingehaengt. Der pbxproj-Teil ist auf keinem Mac
erprobt - er bricht vor dem Schreiben ab, und docs/SHARE_EXTENSION.md
beschreibt dieselben Handgriffe fuer Xcode.
"In den Kalender uebernehmen" ging in der App nie: WKWebView ignoriert das
download-Attribut, der Klick lief ins Leere. Auf dem Geraet jetzt
@capacitor/filesystem plus @capacitor/share.
useTheme/useBoden legten je Aufrufer eigenen Zustand an - fuenf Kopien. Der
Schalter aenderte nur seine eigene, data-theme in App.tsx blieb stehen, die
Tag/Nacht-Umschaltung wirkte erst nach einem Neustart. Jetzt ein Speicher je
Einstellung ueber useSyncExternalStore. Zwei Regressionstests, gegen den
alten Stand als fehlschlagend nachgewiesen.
Alle Popups nach Apple HIG: neue Bausteine Sheet und ActionSheet, blickdicht
und mit abgedunkeltem Schleier, in beiden Codebasen. Popup portalierte nach
document.body - ausserhalb von [data-theme] - und war deshalb im Tagmodus
fast unsichtbar; Portal zielt jetzt auf .ads-root.
ImagePlaceholder merkte sich "fehlgeschlagen" ohne die Adresse: nach einem
leeren Galerieplatz zeigten auch die mit Foto nur noch den Platzhalter.
Vier Regressionstests, ebenfalls gegen den alten Stand geprueft.
Bildadressen tragen jetzt einen Cache-Brecher - HA liefert /local/ mit 31
Tagen Cache-Vorgabe aus, im Panel eingefuegte Radfotos erschienen in der App
deshalb nicht.
uebersichtsbild: Panel speichert den Namen, die App verglich gegen den
Dateinamen - der Vergleich traf nie zu. Kanonisch ist der Name.
Weiter: Navigationspfeil statt gleichschenkligem Dreieck auf der Streckenlinie
(die Kerbe unterscheidet Kopf und Ende), CI-Symbol tour-s als Fahrten-Icon,
Datumsfelder zeigen ihren Wert ohne erstes Antippen, feste Beispielnamen im
Setup, Kopf-Gegengewicht fuer mittige Titel, Standort-Blatt mit festem
Fussabstand, NSLocationWhenInUseUsageDescription, watchPosition fuer die
Live-Ortung, Art-Pille wieder als Knopf, Zwischenablage fuer Tankbelege.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Aufgezogen wurde das Blatt exakt so hoch wie sein Inhalt - die Knoepfe Route
und Teilen schlossen dadurch unten buendig mit der Menueleiste ab.
Apple benennt dafuer das passende Konzept: Blaetter rasten auf "detents" ein,
Hoehen, auf denen ein Blatt natuerlich zur Ruhe kommt; large ist das voll
ausgefahrene Blatt, medium etwa die Haelfte davon (Human Interface
Guidelines, Sheets - nachgelesen, nicht aus dem Gedaechtnis zitiert). Unser
Blatt hatte im aufgezogenen Zustand ueberhaupt keine Rasthoehe, sondern nur
seine Inhaltshoehe.
Jetzt min-height: 50% im aufgezogenen Zustand. Der Ueberschuss liegt unter
den Knoepfen und haelt sie von der Leiste frei. Die eingeklappte Hoehe bleibt
unberuehrt, weil die Verschiebung mit 100% der jeweiligen Blatthoehe minus
dem Guckwert rechnet.
Gemessen: Panel 311px auf 622px Karte, App 298 auf 595 - beide exakt 50%,
Luft unter den Knoepfen 89 bzw. 76px statt zuvor 18.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim "Zuendung an"-Patch habe ich den Begruendungskommentar in den
${...}-Ausdruck gesetzt statt in den Markup-Text. Dort ist <!-- kein
HTML-Kommentar, sondern JavaScript. Folge: audi-dashboard-app.js liess sich
nicht mehr als Modul parsen, connectedCallback() brach ab, das Panel hatte
keinen Shadow Root - der Bildschirm blieb leer.
Betroffen sind .14 bis .18, also alles, was seit dem auf Gitea lag. Wer in
dieser Zeit aktualisiert und neu gestartet hat, bekam ein totes Panel.
Warum es durchrutschte - und das ist der eigentliche Befund: "node --check"
prueft eine .js-Datei als SCRIPT, und dort sind HTML-artige Kommentare per
Annex B ausdruecklich erlaubt. Der Browser laedt dieselbe Datei als MODUL,
wo sie verboten sind. Die Pruefung, auf die sich dieses Projekt bei jeder
Panel-Aenderung verlaesst, kann diesen Fehler grundsaetzlich nicht finden.
Ab sofort gilt: die Datei vor dem Ausliefern als Modul pruefen, also unter
.mjs kopieren und node --check darauf laufen lassen. Rueckwirkend ueber alle
heutigen Commits geprueft - .14 ist der erste kaputte.
Erschwerend kam dazu, dass ich den Panel-Tab nach .14 nie neu geladen habe.
Alle spaeteren "live geprueft"-Aussagen zur Panel-Seite liefen gegen das noch
im Speicher stehende alte Skript und waren damit wertlos.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der runde Knopf malte var(--tile) auf ein Blatt, das selbst deckend ist - im
Tagmodus beides #FFFFFF, also weiss auf weiss. Nachts faellt es nicht auf,
weil --tile dort ein Schleier ueber dunklem Grund ist.
Derselbe Fehlertyp wie bei den Wischzeilen von heute, nur andersherum: dort
addierten sich zwei Schleier im Nachtmodus, hier verschwindet eine Flaeche im
Tagmodus. Beide Male, weil eine Flaeche auf einer Flaeche mit --tile gemalt
wurde. Jetzt --ios-fill, in diesem Projekt ohnehin das Zeichen fuer "das hier
laesst sich bedienen"; es traegt in beiden Themes. In beiden Codebasen
geaendert - das Panel hatte den Fehler genauso.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Blatt trug padding-bottom: max(18px, env(safe-area-inset-bottom)). Es
liegt aber nicht am unteren Bildschirmrand, sondern ueber der Tableiste - und
die haelt den Bereich des Home-Indikators bereits frei. Der Einzug wurde also
doppelt gezaehlt: auf dem Geraet war das Blatt rund 16px hoeher als noetig und
schob sich beim Aufziehen entsprechend weiter hoch. Am Rechner faellt das
nicht auf, dort ist der Einzug 0. In beiden Codebasen entfernt.
Ausserdem: der Blatthintergrund der App stand auf --canvas statt auf dem
deckenden Wert, den das Panel dort nimmt - unter dem Blatt liegt die Karte.
Nachgemessen mit frisch gestarteten Panes: Blatt 240px, Unterkante buendig mit
der Karte, in beiden Anwendungen gleich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fahrzeug-Pin auf der Standortkarte fehlte: die Marker-Effekte lesen Refs,
die erst im asynchronen Leaflet-Import gesetzt werden. Beim ersten Lauf leer,
Effekt steigt aus - und weil die Koordinaten sich danach nicht mehr aendern,
lief er nie wieder. Ein Bereitschaftsschalter in den Abhaengigkeiten behebt
das fuer Marker, Kachelebene und eigene Position zugleich.
Kachelpfeil auf "Mein Audi" sass auf halber Kachelhoehe statt oben neben der
Ueberschrift; Auswahlfelder hatten nach appearance:none ueberhaupt keinen
Aufklapp-Pfeil mehr.
SmartDeal: das Datumsfeld war fehlerhaft und die Abfrage, bis wann der Rabatt
gilt, fehlte ganz. Das Panel fragt beim Einschalten und zeigt danach nur an -
genau daran haengt, dass der Rabatt von selbst auslaufen kann. Portiert.
Adressen statt Koordinaten: Nominatim drosselt uns inzwischen. Beide Apps
fielen korrekt zurueck, merkten sich Treffer aber nur bis zum Neuladen. Jetzt
dauerhaft im selben Cache wie die Tankstellensuche.
Ziehen zum Aktualisieren auf dem Geraet: dem Scrollbehaelter fehlte
overscroll-behavior, das native Overscroll nahm die Geste weg - derselbe
Befund, den das Panel am 2026-08-17 hatte.
Ausserdem: Platzhalter wieder in voller Groesse, FIN statt Fahrgestellnummer,
Details als Hinweiszeile, Chevron an der Batteriespannung, Reifenzeile
"aktuell montiert:", Zahnrad statt Stift am Anzugsmoment, Radkilometer in der
Zahlenschrift, Layer-Icon zentriert, share-s beim Teilen, Schliessen-Knopf nur
bei aufgezogener Karte.
Nicht nachstellbar und zurueckgemeldet: "Fahrten/Tanken, grauer Hintergrund" -
Panel und App sind dort deckungsgleich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei zusammenhaengende Runden, alle live bei 375x812 gegen audi_ha_test
geprueft und in beiden Codebasen angewandt.
Paritaetsrunde 2: der gemeinsame Rahmen war das eigentliche Problem -
Seitenrand, Kachelabstaende, Kopfleiste, Tableiste und vier Bausteine des
Design-Systems trugen noch den Stand vor der iOS-Entscheidung. Dazu sieben
Bildschirme neu aufgebaut. Zwei Panel-Fehler dabei mitbehoben: teaser()
zeigte unter "Letzte Fahrt" den aeltesten Datensatz, und "Daten bearbeiten"
war ein toter Knopf.
Paritaetsrunde 3: das Panel hat nie Audi Type gerendert. @font-face in einem
Shadow Root wird ignoriert - Schriftschnitte registriert der Browser pro
Dokument, nie pro Shadow Tree. Die drei Schnitte liegen jetzt in
audi-dashboard-schriften.css und werden ins Dokument gehaengt. Damit erledigt
sich eine ganze Reihe von "die Schrift sieht anders aus"-Eindruecken: die
beiden Anwendungen zeigten tatsaechlich verschiedene Schriften.
Ausserdem "Daten bearbeiten" im Panel gebaut und portiert, das Zeilenmenue
entfernt und die letzten neun Bildschirme angeglichen.
Designpruefung: die fuenf Punkte der Reihenfolge. Beim vierten hat das Messen
den Befund veraendert - gezaehlt waren die deklarierten Groessen, wirksam war
laengst eine saubere Sieben-Schritt-Skala mit 27 Ausreissern; die sind jetzt
auf den naechsten Schritt gezogen, keiner verschiebt sich um mehr als 1px.
Zuletzt: die Standortvorschau zeichnete die falsche Nadel (das Panel wechselt
den Icon-Satz ab 34px, die App nahm immer den grossen), und der Kopfabstand
der App ist auf den sicheren Bereich reduziert - die 56px des Panels liegen
dort unter der Kopfleiste von Home Assistant, in der nativen Huelle steht
darueber nichts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Erst zwei Zeilen (festes Beispiel + zugeordneter Sensor) versucht, aber die
erfundenen Beispiele waren für Reichweite/Sofort-Aktualisierung schlicht
falsch. Jetzt nur noch eine Zeile mit dem tatsächlich zugeordneten Sensor,
"(z. B. ...)" in Label-Größe/-Farbe, der Sensorname selbst wie die Einheit
daneben ([on/off], [km]); für Listenfelder (Türen/Fenster) ganz entfernt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Neues Profilfeld fahrzeug.fin_automatisch (Standard: an).
- identitaet.py: bei "aus" läuft die Ableitung (samt Mehrfach-Sensor-Abgleich)
gar nicht erst; bei "an" überschreibt der abgeleitete Wert auch einen
vorher von Hand eingetragenen - der Schalter selbst entscheidet jetzt, statt
aus einem leeren Feld zu raten.
- dienste.py: profil_schreiben löst die Ableitung jetzt auch aus, damit das
Umschalten des Schalters selbst sofort wirkt.
- Panel: Schalter "automatisch" zwischen Label und Textfeld in der
Fahrgestellnummer-Zeile, Feld wird bei "an" deaktiviert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- .teaser-Klasse auf die Kachel gesetzt (teaser()).
- .teaser .leaf .v: min-width:72px (gleiche Spaltenbreite je Zeile).
- .teaser .leaf .k: flex:1 1 auto, damit unterschiedlich lange Labels nicht
mehr über justify-content:space-between den ganzen Rest der Zeile
verschieben - vorher blieben .v-Boxen zwar gleich breit, saßen aber an
unterschiedlichen X-Positionen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- distanzVorschlag(): liest jetzt zuerst den Live-Wert von TANK_DISTANZ_SENSOR
(wie backendseitig schon in distanz_seit_tankung()), fällt ohne Zuordnung
auf die bisherige FILLS-Berechnung zurück (jetzt distanzVorschlagBerechnet()).
- .leaf .v: gap:3px ergänzt (fehlte im Gegensatz zu .leaf .k) - die zweizeiligen
Werte in der "Zuletzt"-Kachel (Übersicht) berührten sich sonst.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- entitaetIdKurz(): Präfix per Stimmenmehrheit über alle zugeordneten Sensoren statt
des einzelnen nächsten Nachbarn - verhindert Über-Kürzung durch zufällig geteilte
Namensteile zwischen verwandten Feldern (can_fuel_volume->fuel_volume,
oil_change_due->due waren falsch).
- .setup-feld-hinweis: Ellipsis-Kürzung entfernt, voller Sensorname sichtbar.
- entitaetKandidaten(): "Nur passende Sensoren anzeigen" filtert jetzt auch nach
device_class für Datum/Timestamp-Felder, nicht nur nach Domain/Einheit.
- tankFelder(): Kilometerstand/Getankte Liter in .mitEinheit gewrappt (wie alle
anderen km/l-Felder im Rest der App).
- distanzVorschlag(): negative Vorschläge (fehlerhafte km-Basis eines vorherigen
Tankvorgangs) werden nicht mehr angezeigt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Korrektur zur letzten Aenderung, vom Nutzer live erkannt:
- "fmm003_" war hart einprogrammiert und liess trotzdem noch
installationsspezifisches Rauschen stehen (Geraete-Slug, Instanzname der
Integration). Jetzt wird das laengste gemeinsame Praefix ueber alle
aktuell zugeordneten Sensoren berechnet (setupGemeinsamesPraefix()) -
nichts mehr hartkodiert. Faellt bei einer einzelnen Entitaet aus
anderer Quelle korrekt auf die volle ID zurueck, statt falsch zu kuerzen
(live bestaetigt: TANK_DISTANZ_SENSOR zeigte den vollen Namen, weil er
auf eine andere Integration zeigte).
- Der Live-Wert des Sensors gehoert nicht mehr neben die ID - stattdessen
zeigt das Label selbst jetzt die ERWARTETE Art des Werts an
("Tankfuellstand [%]", "12V-Batteriespannung [V]"), statisch aus dem
FELDER-Katalog abgeleitet, unabhaengig von einer aktuellen Zuordnung.
Version 2026.8.28.5, live im Testcontainer verifiziert (acht echte
Setup-Zeilen gegen die Nutzerbeispiele geprueft).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
companion-app nannte Servicebuch-Feldnamen betrieb/notiz, waehrend Panel und
Backend (profil["service"]["buch"]) werkstatt/kosten/arbeiten verwenden -
ohne Uebersetzung dazwischen zeigten in einer Oberflaeche angelegte
Eintraege in der anderen leere Werkstatt-/Kosten-Werte. werkstatt/kosten/
arbeiten als kanonisch uebernommen (aeltere, bereits etablierte Panel-
Konvention); ServicebuchEintrag, das Bearbeitungsformular (inkl. neuem
Kosten-Feld) und die Ansicht in Service.tsx angepasst, den Workaround-Cast
im CSV-Export (DatensatzPopup.tsx) sowie die Testfixture entsprechend
bereinigt.
Setup-Popup (Panel, Item 11 aus der letzten Sammel-Rueckmeldung): die
statische Beschreibung unter jedem Feldnamen ist jetzt die Kennung und der
aktuelle Wert des tatsaechlich zugeordneten Sensors.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Archiv-Knopf jetzt in Zeile mit "Montiert" (stale margin-top entfernt),
bekommt einen sichtbaren Hintergrund
- companion-app: Wechseltermin-Datumsfeld (appearance-Reset gegen
natives Safari-Chrome, Breite auf Inhalt geschrumpft)
- Mein Audi/Reifen-Box: "montiert: Sommerräder" links statt Marke/Modell,
"offen" durch "-" ersetzt
- "Servicebuch" ueberall in "Wartungsplan" umbenannt (nur Anzeigetext,
beide Codebasen)
- Version-Kachel: tote Fahrzeugdaten-/Position-/Dashboard-Zeilen entfernt
(inkl. der nie aktualisierten CONFIG.version-Konstante)
Version 2026.8.28.1, live im Testcontainer verifiziert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
.leaf (Panel) und .dm-listenzeile (companion-app) galten fuer echte
Navigations-Buttons UND fuer die reine <div>-Messwertliste gleichermassen -
Hand-Cursor und Tipp-Rueckmeldung suggerierten dort faelschlich Klickbarkeit,
obwohl die Liste nur Wischen-zum-Loeschen unterstuetzt. Beide Regeln jetzt
auf button.leaf/button.dm-listenzeile beschraenkt - echte Zeilen-Buttons
(Fahrten, Tankvorgaenge, Servicebuch) bleiben unveraendert klickbar.
Version 2026.8.27.22, live verifiziert (Cursor auto statt pointer bei der
Messwertliste, pointer weiterhin bei echten Zeilen-Buttons).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fünf vom Nutzer angeforderte Erweiterungen in einer Runde:
- Batteriespannungs-Kachel bekommt eine Messwertliste (Datum, Uhrzeit,
Spannung, optional Außentemperatur über den neuen AUSSENTEMP_SENSOR),
erreichbar über ein neues list-s-Symbol in der Diagramm-Kachel. Werte
über AGM_RUHE_MAX_V (12,8 V) sind keine Ruhespannung, sondern
Lichtmaschinenspannung - die Zeile markiert das jetzt mit
"Generatorspannung" statt es unkommentiert als Messwert auszugeben.
- Jede Zeile der neuen Liste wischbar zum Löschen (neuer Dienst
batterieverlauf_loeschen), über dieselbe Wisch-Mechanik wie Fahrten/
Tankvorgänge in beiden Oberflächen.
- Batteriespannungs-Diagramm im Panel war auf großen Bildschirmen (≥860px,
Spaltenlayout) stark in die Breite gezogen (preserveAspectRatio="none"
bei fester Höhe) - gedeckelt wie die dort bereits vorhandenen Popups.
- Statistik-Tab-Symbol in beiden Oberflächen durch das Audi-CI-Symbol
polls-s ersetzt.
- Neue Möglichkeit, einen Reifensatz zu archivieren ("Neue Räder
anlegen"): der aktuelle Stand (km, Marke, Modell, DOT, Maße, Solldruck,
Kommentar) wandert in ein Archiv, der laufende Satz beginnt bei 0 km neu.
Archiv als aufklappbare Übersicht mit voller Bearbeitungsmöglichkeit,
über drei neue, bewusst nicht über profilSchreiben laufende Dienste
(reifen_archivieren/-aktualisieren/-loeschen) - aus demselben Grund wie
reifen_wechseln: kein im Browser gehaltener Stand darf einen
zwischenzeitlich fortgeschriebenen km-Wert überschreiben.
Live im Testcontainer geprüft (erstmals über :18123 statt :8123 erreichbar)
und dabei zwei echte Layout-Fehler gefunden, die kein Compile-/Testlauf
sehen konnte: die Archiv-Eingabefelder waren durch ein fälschlich
verwendetes .mitEinheit (feste 96px-Breite, eigentlich für Zahl+Einheit
gedacht) abgeschnitten ("Continenta" statt "Continental"), und die
Kilometerzahl in der eingeklappten Archiv-Zeile war klein an das Datum
gequetscht statt wie der Satzname lesbar. Beides behoben, live erneut
bestätigt.
Backend: py_compile clean, services.yaml ergänzt. Panel: node --check
clean. companion-app: tsc/Testsuite (146/146)/Build/OTA-Bündel alle grün.
Manifest 2026.8.25.2 → .8, jeder Neustart im Testcontainer sauber.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- aktualisierung.py: Backup-Ordner verliert sein manifest.json beim Sichern,
sonst laedt HA ihn nach einem Neustart als zweite audi_dashboard-Integration
(Ursache des raetselhaften "gleicher Pfad"-Umbenennungs-Fehlers).
- service.ts/audi-dashboard-app.js: Uebersicht faellt jetzt wie Service schon
auf die Fahrzeugmeldung zurueck, wenn kein Servicebucheintrag existiert;
eigenes (kuerzeres) Oelwechsel-Intervall wird jetzt auch ohne Servicebuch-
eintrag naeherungsweise aus der Herstellermeldung hochgerechnet, statt
weiterhin unveraendert die Herstellervorgabe zu zeigen.
- Sicherheit neu gestaltet: vier Sammelzeilen (Fahrzeug verriegelt / Tueren
und Klappen geschlossen / Fenster und Dach geschlossen / Kein Licht) statt
einer flachen Liste, mit neuen Tuerschloss-, Dach- und Standlicht-Sensor-
rollen, Kreis-Haekchen-Symbolen und einer Detailseite je Tuer/Motorhaube/
Kofferraum in beiden Frontends.
Details, Verifikation und Sensor-Rollen in AGENTS.md (Abschnitte J/M/N).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Das Backend liegt jetzt als custom_components/audi_dashboard/ vor - eine
normale Home-Assistant-Integration mit Config-Flow, einer sensor-Plattform
und 18 Diensten. Damit ist die App über HACS installierbar; bis das Repo auf
GitHub gespiegelt ist (HACS spricht ausschließlich mit GitHub), installiert
homeassistant/installationspaket/install.ps1 denselben Ordner ohne HACS.
Fünf Installationsschritte entfallen ersatzlos: der pyscript:-Block, der
panel_custom:-Block, das Kopieren der Oberfläche nach www/, das langlebige
Zugriffstoken (der Verlauf wird direkt über die recorder-API gelesen) und
"pip install pypdf" (steht in manifest.json). Das Fahrzeugprofil legt die
Integration beim ersten Start aus ihrer Vorlage an.
Drei alte Schwächen sind dabei mit erledigt:
- Die Nutzlast landet nicht mehr in der Recorder-Datenbank
(_unrecorded_attributes - das kann nur eine echte Entität).
- Eine laufende Fahrt überlebt einen Neustart (Store statt Arbeitsspeicher);
fiel sie während eines Ausfalls ins Ende, schließt
nach_neustart_fortsetzen() sie beim letzten aufgezeichneten Zeitpunkt.
- Sensor-Zuordnungen wirken sofort - die Zustandsbeobachter werden neu
gebunden, der Neustart-Hinweis und der Neustart-Dienst sind weg.
Namensvertrag geändert, beide Oberflächen mitgezogen:
pyscript.audi_dashboard_x -> sensor.audi_dashboard_x,
pyscript.audi_dashboard_y -> audi_dashboard.y. Eine Companion-App vom alten
Stand findet nach dem Umstieg nichts mehr und muss neu gebaut werden; das
Panel liegt in der Integration und kann nicht driften.
Der selbstgebaute Updater entfällt - HACS ist die Update-Mechanik, die Home
Assistant kennt. Die Versionierung schrumpft auf eine Quelle: manifest.json.
Geprüft am laufenden Testcontainer (Container byteweise identisch mit dem
Repo): alle 18 Dienste, Panel, Config-Entry neu laden, Historienimport,
echter Shell-Beleg in-process, Neuinstallation im Wegwerf-Container blank mit
automatisch nachinstalliertem pypdf. Companion-App: tsc sauber, 112/112
Tests, beide Rauchtests gegen das laufende Backend grün. Belegparser 8/8.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>