Es gibt keinen Bewegungssensor am Fahrzeug. Der einzige Anhaltspunkt ist
ZUENDUNG_SENSOR, und der meldet on auch bei blosser Zuendung oder in
Zubehoerstellung - "Fahrzeug faehrt" behauptete also mehr, als bekannt ist.
Mein zwischenzeitlicher Vorschlag, zusaetzlich eine laufende Fahrt zu
verlangen, war falsch begruendet: fahrt_start_ts in fahrterkennung.py wird aus
genau demselben Signal abgeleitet und haette nur eine zweite Huelle um
dieselbe Aussage gelegt.
Der umgekehrte Fall bleibt unangetastet: Zuendung aus heisst verlaesslich,
dass gerade nicht gefahren wird - "Fahrzeug steht" und "Geparkt seit ..."
stehen weiter. Zwei Typ-Kommentare, die dieselbe Gleichsetzung
weitertrugen, sind mitkorrigiert.
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>
Drei Anlaeufe, die ersten beiden mein Fehler. Gemeldet war "Icon falsch im
Knopf platziert". Ich habe die Zeichenflaeche gemessen, sie fuellt 20,9x15,6
des 24er-Rasters gegen 20x20 bis 24x22 bei den Nachbarn, und daraus auf "zu
schwer und aussermittig" geschlossen - also verkleinert. Zwei Fehler darin:
gemessen habe ich das Panel und geaendert habe ich beide, ohne das Symbol der
App je selbst zu messen; und "fuellt weniger Flaeche als die Nachbarn" spricht
fuer "wirkt kleiner", nicht dagegen.
Nach der Ruecknahme im Panel zeigte die Messung der App den echten Fehler
dort: ihr mapLayer-Pfad begann mit grossem M statt kleinem m. Beim ersten
Befehl ist das gleichbedeutend, aendert aber alles danach - nach M gelten
folgende Zahlenpaare als absolute Linien, nach m als relative. Der zweite
Punkt sprang damit auf (-8.97,-5.66), weit aus dem Raster: das Symbol war
verzerrt, nicht bloss falsch dimensioniert. Pfad wortgleich vom Panel
uebernommen, alle vier Steuerungssymbole vergleichen sich jetzt zeichengleich.
Damit stand die urspruengliche Meldung fuer sich und war schlicht richtig: die
flache Form wirkt bei gleicher Kastengroesse kleiner. Beide zeichnen sie jetzt
mit 26px statt 22px - dieselbe Loesung wie beim Oelwechsel-Icon der
Servicebloecke, das aus demselben Grund 26px neben 20px bekommt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ziehen zum Aktualisieren funktionierte auf keinem Geraet, in keiner der
beiden Anwendungen - und der Grund entwertet zugleich, wie es bisher geprueft
wurde. Beide trieben die Geste ueber pointermove und riefen dort
preventDefault(). Das verhindert laut Spezifikation kein Scrollen; darueber
entscheidet allein touch-action. Auf echtem Touch uebernimmt der Browser die
senkrechte Geste, schickt pointercancel und stellt pointermove ein - der Zug
wird zurueckgesetzt, lange bevor er die Schwelle erreicht. Eine Maus kennt
diese Uebernahme nicht, synthetische PointerEvents ebenso wenig: genau
deshalb lief die Geste 2026-08-17 im Test sauber durch und am Geraet nie.
Jetzt laeuft sie auf Touch-Ereignissen, touchmove zwingend mit passive:false
(sonst ist preventDefault() wirkungslos); der Zeigerweg bleibt fuer Maus und
Stift und ignoriert pointerType "touch". Mit echten TouchEvents geprueft,
inklusive defaultPrevented - dem einzigen Signal, das belegt, dass das native
Ueberscrollen wirklich unterbunden ist.
Der zuletzt nicht nachstellbare Befund war nachtmodus-spezifisch: --tile ist
dort ein durchscheinender Schleier, und die Wischzeilen malten ihn ein
zweites Mal auf die Kachel, auf der sie ohnehin liegen. Am Tag sind beide
deckend weiss, deshalb war nichts zu sehen. Das Panel nutzt an dieser Stelle
--tile-deckend; dieses Token fehlte im Design-System und ist jetzt da.
Ausserdem: steht das Auto auf einem benannten Platz, zeigen beide dessen
Namen statt der naechsten Hausnummer - Nominatim liefert ihn mit, die
Pruefung auf die Art der Flaeche verhindert, dass irgendein benanntes
Gebaeude die Anschrift verdraengt.
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>
Neu gebaut und Ad-hoc signiert nach Commit 4a58021. Enthaelt den neuen
TankstellenKarte-Screen und die einkompilierte Version 2026.8.30.8. Profil
weiterhin mit beiden registrierten Geraeten, gueltig bis 29.08.2027.
Vorher geprueft: design-system neu gebaut (dessen Komponenten-CSS hat sich
in dieser Runde stark geaendert), Typecheck sauber, 147/147 Tests gruen.
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>
Neu gebaut und Ad-hoc signiert nach dem Audit-Commit e1ebe6d. Enthaelt den
neuen Standort-Screen und die einkompilierte Version 2026.8.30.2. Profil
weiterhin mit beiden registrierten Geraeten, gueltig bis 29.08.2027.
Vorher geprueft: design-system neu gebaut (dessen CSS hat sich mitgeaendert),
Typecheck sauber, 147/147 Tests gruen.
Systematischer Bildvergleich der companion-app gegen das HA-Panel (companion-app/AGENTS.md
Kapitel 1-11): Farbtoken/Radien aus dem falschen Stylesheet gelesen (iOS-Overlay statt Basis-CSS,
betraf fast jede Kachel/Farbe/Radius app-weit), vier app-weite @audi-dash/ui-Bugs (Switch/Seg/Feld
rot statt neutral bzw. falsche Feldbreite), Reifen-Seite strukturell neu gebaut (beide Radsätze
gleichzeitig statt Umschalter, editierbare Felder, Anzugsmoment-/km-Korrektur), Standort-Feature
komplett neu (fehlte bisher ganz), sowie diverse Struktur-/Typografie-/Datenlücken in
MeinAudi/Service/Versicherung/Sicherheit/Fahrten/Tanken/Statistik/Batterie/Einstellungen.
Manifest auf 2026.8.30.2 angehoben, OTA-Bündel neu gebaut und in audi_ha_test verifiziert
(sauberer Neustart, keine Tracebacks).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Beim Antippen eines Feldes auf dem Willkommensbildschirm zoomte iOS die
ganze Seite heran und machte sie verschiebbar. Ursache war nicht eine
fehlende Regel, sondern eine unterlegene: grundlage.css und .dm-eingabe
setzen laengst 16px, aber @audi-dash/ui setzt ".ads-feld input" auf 13.5px -
Klasse plus Typ schlaegt die blosse Klasse. Unterhalb von 16px zoomt iOS
beim Fokus, das ist der ganze Mechanismus.
Behoben mit einem spezifischeren Selektor im App-CSS, gleicher Wert wie
ohnehin beabsichtigt. @audi-dash/ui bleibt unangetastet, wie schon beim
type=date-Fall darunter.
Bewusst nicht genommen: user-scalable=no im Viewport. Das haette das
Symptom in einer Zeile versteckt, nimmt aber allen das Aufziehen - und
dasselbe Buendel wird auch als Web-App aus Home Assistant ausgeliefert.
Phase 10 Schritt 7 ist damit erledigt. auslieferung/App.ipa, 2,4 MB, Ad-hoc
signiert mit "Apple Distribution: Paul Nothaft", Profil gueltig bis
29.08.2027, genau ein eingetragenes Geraet.
Zwei Annahmen von heute frueh waren falsch und sind korrigiert: die bezahlte
Mitgliedschaft stuft das bestehende Team hoch, statt ein neues anzulegen (die
Kennung bleibt RMACS9VLS4), und der Export als Ad-hoc funktioniert einwandfrei.
Neue Falle festgehalten: beim ersten Signieren fragt der Schluesselbund per
Dialog um Erlaubnis. Bleibt der unbeantwortet, haengt xcodebuild wortlos und
endet mit errSecInternalComponent. Die Diagnose steht in AGENTS.md, weil das
Symptom von sich aus nirgendwohin zeigt.
Neu: scripts/ios-luftweg.sh erzeugt manifest.plist, Installationsseite und
Symbole fuer die Uebertragung ueber die Luft. Es verweigert eine Basis-Adresse
ohne https, weil iOS sonst erst auf dem Telefon still scheitert.
Offen bleibt der Host, der die Dateien ausliefert.
Der fest eingetragene Wert RMACS9VLS4 gehoert zum kostenlosen Personal Team.
Mit der bezahlten Mitgliedschaft entsteht ein eigenes Team mit anderer
Kennung; der alte Wert wuerde still weiter mit dem kostenlosen Team signieren
und die App nach 7 Tagen sterben lassen. Ohne APPLE_TEAM_ID bricht das Skript
jetzt mit einem Hinweis ab, wo die Kennung zu finden ist.
Owner-Anfrage 2026-08-28 - war 2026-08-11 bewusst weggelassen, jetzt wieder
gewünscht. Ursprünglicher Plan aus UMSETZUNGSPLAN.md Phase 10 als Referenz.
Der vorige Commit ging von einer bezahlten Mitgliedschaft aus und nannte als
Ausweg, die UDID auf developer.apple.com einzutragen. Das ist falsch.
Xcodes eigener Zwischenspeicher belegt das Gegenteil:
isFreeProvisioningTeam = 1, teamType = "Personal Team". Damit gibt es gar
keine Geräteverwaltung im Portal -- ein Gerät wird ausschließlich dadurch
bekannt, dass es angeschlossen und vertraut ist. Zusätzlich verfallen Profil,
App-ID und Geräteeintrag alle 7 Tage.
Auch die ältere Behauptung weiter oben in AGENTS.md ("Paul has an Apple
Developer Program") ist damit als falsch markiert.
Offen und bewusst als ungeprüft vermerkt: ob -exportArchive mit einem
Personal Team überhaupt eine brauchbare .ipa liefert. Der direkte Weg aufs
angeschlossene Gerät steht als Rückfallebene im Skriptkopf.
Phase 10 Schritt 7 lässt sich nicht abschließen, aber alles bis zur Signatur
ist gebaut und belegt: Simulator- und Gerätebau (arm64, Release) laufen
fehlerfrei durch, 146/146 Tests grün, Typecheck sauber.
Die Signatur scheitert allein daran, dass dem Entwicklerteam kein Gerät
bekannt ist -- Apple erzeugt ein Development-Profil nur für konkrete UDIDs.
Kein iPhone angeschlossen, keins je mit diesem Mac gepaart, kein
App-Store-Connect-Schlüssel zum Nachtragen.
Neu: companion-app/scripts/ios-signieren.sh macht Bauen, Synchronisieren,
Signieren und den .ipa-Export zu einem Befehl. Nötig, weil ios/ absichtlich
gitignored ist und jede in Xcode geklickte Signatureinstellung beim nächsten
npx cap add ios wieder verschwinden würde -- die Team-Kennung braucht eine
versionierte Heimat.
Bewusst nicht getan: eine unsignierte .ipa als Platzhalter einchecken. Sie
wäre nicht installierbar und läge als Binärdatei dauerhaft in der Historie.
Live verifiziert: /api/ liefert jetzt 401 statt der generischen NPM-Fehlerseite - der
Proxy-Vertrauen-Fix (X-Forwarded-For/trusted_proxies, seit Migration über die HA-UI statt
YAML gesetzt) greift. Zusätzlich den include-Datei-Bug beim NPM-Add-on genauer beschrieben
und einen Hinweis ergänzt, dass der abschließende location-/-Block nach Debug-Tests immer
wieder eingefügt werden muss - sonst landet jede Anfrage ungefiltert bei Home Assistant.
Neuer Schritt 6 mit den Cloudflare-/NPM-Sicherheitseinstellungen (SSL-Modus,
HSTS, Bot Fight Mode, DNS-Aufräumen, Token pro Gerät, Router-Portcheck) und
dem größten praktischen Stolperstein (Tunnel-Hostname zeigt versehentlich
direkt auf HA statt auf den Reverse Proxy). Nachfolgende Schritte/Verweise
umnummeriert, ein alter Nummerierungsfehler in der Einleitung mitkorrigiert.
Cloudflared-Add-on jetzt namentlich mit Link genannt und geprüft
(homeassistant-apps/app-cloudflared) - die frühere Bezeichnung "offizielles
Add-on" war ungenau (Community-Add-on, kein Nabu-Casa-Produkt). Festgehalten,
dass der dokumentierte Tunnel-Token-Weg keinen Cloudflare-API-Token braucht.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Alle Referenzen in Doku und Code aktualisiert (REVERSE_PROXY.md,
INTERNET_ZUGRIFF_EINRICHTEN.md, COMPANION_APP_ARCHITECTURE.md, AGENTS.md,
UMSETZUNGSPLAN.md, companion-app/src/api/umgebung.ts-Kommentar). Dabei den
.app-spezifischen HSTS-Preload-Hinweis in COMPANION_APP_ARCHITECTURE.md §5.4
korrigiert - gilt für .de nicht, Force-SSL in Nginx Proxy Manager deckt das
weiterhin ab. UMSETZUNGSPLAN.md Phase 12 zusätzlich mit einem
Aktualisierungshinweis versehen (zwei-Hostnamen-Plan und pyscript-Namen dort
waren ohnehin schon überholt, jetzt klar auf REVERSE_PROXY.md/
INTERNET_ZUGRIFF_EINRICHTEN.md als maßgeblich verwiesen).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
REVERSE_PROXY.md verwies auf INTERNET_ZUGRIFF_EINRICHTEN.md, das nie
geschrieben wurde - jetzt vorhanden (Cloudflare-Konto, Nameserver-Umstellung,
Cloudflared/NPM-Add-ons, Pfad-Freigabeliste eintragen, Prüfung).
Dabei einen echten Fehler in der Freigabeliste gefunden: sie ging noch von
einem companion-app-Web-Build unter /local/dm360/ aus (Planungsstand
2026-08-11) - das wurde nie gebaut, die App ist nativ/sideload-only. Ersetzt
durch den tatsächlichen Fernbedarf: das OTA-Bündel unter
/audi_dashboard_static/app/* (@capgo/capacitor-updater). Damit genügt auch
ein einziger Hostname statt der ursprünglich erwogenen App-/API-Trennung.
COMPANION_APP_ARCHITECTURE.md §5 und AGENTS.md entsprechend nachgezogen.
Co-Authored-By: Claude Sonnet 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>
Die Pfad-Freigabeliste ging noch von pyscript.audi_dashboard_*/
pyscript.reifen_* und /api/services/pyscript/... aus - seit der Umstellung
auf die native Integration (2026-08-23) heißen Entitäten
sensor.audi_dashboard_* und Dienste audi_dashboard.<name>. Ergänzt um zwei
seither neu hinzugekommene Bedarfe, die in der alten Fassung fehlten:
homeassistant.restart (Update-Neustart-Knopf) und /local/dm360/* (die
ausgelieferte App selbst - ohne diesen Pfad hätte sie über den Tunnel gar
nicht geladen).
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>
Neues identitaet.py: durchsucht das Geräte-Register der aktuell im Setup
zugeordneten Sensoren (cupra_eu_data_act, FMM003, ...) nach einem
VIN-förmigen Geräte-Identifier/Seriennummer, statt ein eigenes Setup-Feld zu
verlangen. Mehrere übereinstimmende Quellen werden akzeptiert, abweichende nur
geloggt statt geraten; eine bereits von Hand eingetragene FIN wird nie
überschrieben. Läuft nach jedem Start und nach jeder Setup-Änderung
(koordinator.py/dienste.py).
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>
- FELDER-Katalog: "(Datum)"/"(Restkilometer)"/"(Liter)"/"(Knopf)"/"(Fahrertür)"
aus sieben Labels entfernt - die Unterscheidung übernimmt bereits das
[Einheit]-Label neben der Überschrift (feldEinheitAnzeige()).
- .setup-popup auf max-width:760px verbreitert (eigener Wert, getrennt von
.sdpopup/.sheet/.beleg-popup), damit lange Rohsensornamen nicht mehr
umbrechen müssen.
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>
Zwei weitere Korrekturrunden, beide vom Nutzer live erkannt:
- .6: paarweise Abstimmung statt fortlaufender Verengung - robuster gegen
einen einzelnen Ausreisser, aber grundsaetzlich noch falsch.
- .7: die eigentliche Ursache war, dass diese Installation zwei etwa
gleich grosse Sensorquellen gleichzeitig hat (9 FMM003-Rollen, 18 Rollen
einer zweiten Integration mit "audi_rs_4_avant_"-Praefix) - ein
EINZELNES globales "Sieger"-Praefix kann immer nur eine der beiden
Quellen richtig kuerzen. entitaetIdKurz() sucht jetzt pro Feld den
naechsten Verwandten unter allen zugeordneten Sensoren und kuerzt nur
dessen gemeinsames Praefix - unabhaengig von Anzahl und Groesse der
Quellen.
Diesmal vor dem Deploy anhand der ECHTEN sensor.audi_dashboard_entitaeten-
Zuordnung durchgerechnet statt mit erfundenen Test-IDs (das hatte den
.6-Fehler faelschlich als behoben erscheinen lassen). Version 2026.8.28.7,
live verifiziert: alle 20 Einzelwert-Felder zeigen die richtige, kurze
Kennung, keine installationsspezifischen Reste aus beiden Quellen mehr.
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>
- "Daten ausgeben" zu "Fahrzeugprofil" umgebaut, gleiche zwei Knoepfe wie
im Panel: Datensatz sichern/laden, popup mit vier Aktionen
- CSV-Spaltennamen jetzt byte-identisch zum Panel-Export (gemeinsamer
Backend-Parser, csv_import.py) - vorher eigene, abweichende Kopfzeilen
ohne Reimport-Moeglichkeit
- neue api.csvImportieren(), Fahrzeugprofil-Import ueber das bestehende
api.profilSchreiben() (volles Profil, nicht die teilweise
zusammenfuehrende profilSpeichern()-Bequemlichkeitsfunktion)
- Blinden Fleck geprueft: importStatusLesen()/zustandLesen() lesen per
REST, nicht aus lokalem Cache - dieselbe Racebedingung wie im Panel kann
hier strukturell nicht auftreten
- Toten dateiwahl-Scaffolding entfernt (nie verdrahtet)
Beim Bauen echten, vorbestehenden Fehler gefunden: companion-app und Panel
verwenden unterschiedliche Feldnamen fuer Wartungsplan-Eintraege
(betrieb/notiz vs. werkstatt/kosten) - als eigene Aufgabe geflaggt statt
hier mitgefixt.
tsc --noEmit sauber, 146/146 Tests, vite build erfolgreich. Nicht live
getestet (kein laufender companion-app-Dev-Server mit Backend-Zugang in
dieser Sitzung).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Neuer optionaler Sensor TANK_DISTANZ_SENSOR ersetzt die eigene
Kilometerstand-Subtraktion fuer die Tankvorgang-Strecke, wo zugeordnet
(Live-Erkennung, manuelle Erfassung, historischer Import)
- "Fahrzeugprofil" und "Daten ausgeben" zu einer Kachel zusammengelegt:
"Datensatz sichern" (4 Exporte wie bisher) / "Datensatz laden" (neu:
echter CSV-Import fuer Fahrten/Tankvorgaenge/Wartungsplan)
- Import gleicht per ID ab (Fahrten/Tankvorgaenge) bzw. Datum+Art
(Wartungsplan, hat keine eigene ID) und aktualisiert nur die in der CSV
enthaltenen Spalten - alles andere am Datensatz bleibt unangetastet
- Nebenbei gefunden und behoben: belege.tankvorgang_aktualisieren()
ueberschrieb bisher immer alle Felder, auch mit None, wenn irgendeins
geaendert wurde - fuer den CSV-Import gefaehrlich, jetzt nur noch
tatsaechlich uebergebene Felder
- Ebenfalls gefunden und behoben: Panel las das Import-Ergebnis per
HASS.states direkt nach dem Dienstaufruf - ein Wettlauf mit dem
state_changed-Push. Nutzt jetzt denselben HASS.callWS(get_states)-Weg
wie der bestehende historie_importieren-Ablauf.
companion-app-Portierung von "Datensatz sichern/laden" steht noch aus.
Version 2026.8.28.3, live im Testcontainer verifiziert (alle drei
CSV-Datensatztypen: anlegen + aktualisieren per ID/Datum+Art getestet,
Testdaten danach geloescht).
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>
Der RAM-only Fallback fuer die Zustand-Kachel wurde bei jedem Neustart
geleert und zeigte "unbekannt", solange seit dem Neustart keine echte
Live-Messung eintraf (Dongle bei ausgeschaltetem Fahrzeug erwartungsgemaess
immer offline). spannung_cache_vorladen() laedt ihn jetzt beim Start aus
der gespeicherten Historie vor, begrenzt auf den vereinbarten Bereich
10,0-13,0 V (SPANNUNG_MIN_V bis AGM_RUHE_MAX_V) - eine Generatorspannung
(z.B. 15,4 V) soll dort nie als Batteriespannung erscheinen.
Version 2026.8.27.21, im Testcontainer verifiziert (12,149 V statt
"unbekannt", trotz Dongle weiterhin 0 V live).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- companion-app Batterie.tsx: Generatorspannung zeigte sich faelschlich als
Ruhespannung/verzerrte den SOH-Trend, Panel-Filter (AGM_RUHE_MAX_V) fehlte
- Manuell angelegte Fahrten/Tankvorgaenge trugen naive Zeitstempel und wurden
von der Import-Dublettenpruefung stillschweigend uebersprungen; neue
gemeinsame zeit_normalisiert() in verlauf.py schliesst die Luecke
- Batteriespannungsverlauf fehlte im Backup (sicherung.py)
- Tankvorgangs-Import verlor stillschweigend aeltere Tankvorgaenge vor Beginn
der Litersensor-Historie; laeuft jetzt zweigleisig (Prozent + Liter)
- Panel-Statistikseite behauptete faelschlich, der Verbrauch je Fahrt komme
vom Fahrzeug (OBD) - ist eine Naeherung aus dem Tankfuellstand
- companion-app Statistik.tsx: Arbeitsweg-Segment war noch rot statt neutral
Version 2026.8.27.19, OTA-Buendel neu gebaut, im Testcontainer verifiziert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Beim Zurueckbauen von bvPunkte/bvRuhePunkte auf eine einzige gefilterte
Liste (voriger Commit) blieb eine Fundstelle unbeachtet: die SOC-Berechnung
in vBatterieverlauf() las weiterhin aus dem entfernten bvRuhePunkte. Jeder
Klick auf "Batteriespannung" liess render() mit einem ReferenceError
abbrechen, bevor die Zielseite ueberhaupt gezeichnet wurde - von aussen
ununterscheidbar von "Klick tut nichts". Live im Browser gefunden (Konsole
zeigte den echten Fehler), nicht durch Codelesen - node --check haette das
nie gefangen, da es nur Syntax prueft, keine Laufzeitreferenzen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Der Nutzer fuehrte ein Selbst-Update aus, das Gitea's letzten committeten Stand
(80d73e8) zog - alle Fixes dieser Sitzung waren bis dahin nur per docker cp an
audi_ha_test ausgeliefert, nie committet. Manifest fiel auf 2026.8.27.8 zurueck,
alle Symptome (Batteriespannung "unbekannt", Diagramm-Maximalwert 13,99V) passten
exakt zum Vor-Sitzungs-Stand. Container wiederhergestellt, jetzt committet -
Lehre fuer kuenftige Sitzungen im Dokument festgehalten.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Statistik-Tab-Icon per zentrierter Stauchung an die Fuellflaeche der
anderen Tab-Icons angeglichen (Panel + companion-app), auf Nutzerwunsch
anschliessend 10% groesser.
- Batteriediagramm neu gezeichnet: dynamische viewBox (1 Einheit = 1 Pixel,
kein preserveAspectRatio-Verzerren mehr), ein Punkt je Ruhespannungsmessung
statt Datumsbeschriftung, Tageshoechstwert nur noch im Tooltip. Generator-
spannungen (> AGM_RUHE_MAX_V = 13,0 V, vom Nutzer festgelegt) bleiben aus
dem Diagramm aussen vor; der SOC-Kurve-Eckwert "100% / voll" bleibt bei den
ursprünglich recherchierten 12,8 V. companion-app auf dieselbe lineare
SOC-Interpolation umgestellt (vorher eine abweichende Stufenkurve).
- Außentemperatur wird jetzt auch beim Batterieverlauf-Import nachgetragen
(vorher nur live) - Kopplung an die naechstgelegene Messung innerhalb
NEBENWERT_MAX_ABSTAND_S (verlauf.py), vom Nutzer nach Live-Daten-Analyse
auf 300s festgelegt. Merge-Logik in ablage.py ergaenzt: ein erneuter Import
kann eine zuvor fehlende Temperatur jetzt tatsaechlich nachtragen, auch
wenn sich der Tagesminimalwert selbst nicht aendert.
- "Mein Audi"/Zustand zeigt bei unplausibler Live-Messung (z. B. Dongle
offline) die zuletzt gemessene Spannung statt "unbekannt".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Verbrauch (l/100km) war bislang totes Schema - kein Codepfad füllte
verbrauch_l_100km je. Jetzt aus der Literstand-Differenz (TANK_LITER_SENSOR)
über die Distanz genähert, live und beim Import, in beiden Frontends.
Die "Zustand"-Kachel zeigte die Batteriespannung ungefiltert direkt vom
Sensor, unabhängig von der Plausibilitätsgrenze der Verlaufsaufzeichnung -
ein Sensorausreißer (0V) zeigte sich dort weiterhin, obwohl die Messwertliste
ihn längst verwarf. Dieselbe Grenze gilt jetzt auch für diesen Anzeigepfad.
Reale Fahrtendaten zeigten eine Fahrt mit 22km in 67s (~1180 km/h) - die
Live-Vervollständigung (screening.py) hatte anders als der Import keine
Plausibilitätsprüfung der Durchschnittsgeschwindigkeit. Jetzt gemeinsam in
verlauf.py (UNPLAUSIBLE_KMH/durchschnitt_kmh) für beide Pfade. Dabei einen
zweiten echten Bug gefunden: _fahrt_screenen() zog sein Ergebnis nie ins
In-Memory-Objekt nach (nur in die Ablage) - eine im selben Durchlauf gerade
erst ermittelte Distanz blieb für spätere Schritte (z. B. Verbrauch) bis zum
nächsten Screening unsichtbar. Beide Stellen jetzt behoben.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die aspect-ratio-Lösung für die volle Spaltenbreite ließ auf großen Bildschirmen
die gesamte Koordinatenfläche mitwachsen - Achsenbeschriftungen (fester font-size
in SVG-Einheiten) wurden dadurch auf ~26px zu groß, das Diagramm unnötig hoch.
Zurück auf eine feste 170px-Höhe: der Y-Maßstab bleibt immer 1:1, nur die
X-Achse dehnt sich auf die volle Breite - normale Schriftgröße, kompaktes
Diagramm, trotzdem volle Spaltenbreite.
bvSkalaY()/y() klemmen jetzt auf [0,1] statt roh zu extrapolieren - ein Punkt
außerhalb von yMin/yMax (z. B. ein Ausreißer auf einer noch nicht aktualisierten
Instanz) zeichnet sich sonst weit außerhalb der Fläche und reißt die Linie über
den Rand hinaus, statt sichtbar am Achsenrand zu liegen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die Y-Achse beider Batteriespannungs-Diagramme (Panel und companion-app) war bisher
aus den sichtbaren Punkten berechnet - jetzt fest 10-15V, auf Nutzerwunsch (zunächst
8-15V, dann auf 10-15V korrigiert). SPANNUNG_MIN_V (batterie.py) auf denselben Wert
angehoben, damit die Plausibilitätsgrenze zur Achse passt - historienimport.py
übernimmt den Wert automatisch, da er von dort importiert statt dupliziert wird.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>