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>
- 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>
- 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>
Batteriespannung: Werte unter 8V (Sensor-/Verbindungsfehler, nicht physikalisch
plausibel für eine 12V-Bleibatterie) werden nicht mehr erfasst - live und beim
Import. "Neue Räder anlegen"-Knopf sitzt jetzt auf derselben Zeile wie "Montiert".
Fahrten: start_lat/-lon, end_lat/-lon und route wurden bisher nur beim
rückwirkenden Import befüllt, nie bei live erkannten Fahrten (dem Normalfall) -
Screening trägt sie jetzt aus dem GPS-Verlauf nach, unabhängig vom
Kilometerstand-Status. fakeTrack() (eine erfundene Linie) ist entfernt, die
Karte zeichnet jetzt die echte Route oder eine ehrliche Gerade zwischen den
bekannten Punkten. CARTOs anonyme Kartenkacheln verlangen inzwischen einen
API-Schlüssel ("API key required" auf jeder Karte in beiden Apps) - auf
schlüssellose OpenStreetMap-Kacheln umgestellt. Start/Ziel zeigen jetzt Datum
und Uhrzeit über der Adresse; die fehlerhafte "Status"-Zeile ist entfernt.
Batteriespannungs-Diagramm nutzt auf großen Bildschirmen die volle
Spaltenbreite statt einer festen 400px-Deckelung.
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>
Die Zündungs-Entität stammt vom FMM003-Tracker; verliert er unterwegs
kurz die Verbindung, meldet Home Assistant "unavailable" statt eines
echten Zündungszustands. Die Live-Erkennung wertete das bisher wie
"aus" - eine Funklücke über der Pausenzeit teilte eine durchgehende
Fahrt in zwei. zuendung_geaendert() ignoriert "unavailable"/"unknown"
jetzt vollständig und leitet "fährt gerade" aus dem eigenen
Zwischenstand (fahrt_start_ts) statt aus dem letzten Rohwert ab.
historienimport.py bekommt zusätzlich eine Plausibilitätsprüfung: eine
errechnete Durchschnittsgeschwindigkeit über 300 km/h deutet auf einen
Kilometerstand-Ausreißer an der Fahrtgrenze hin, nicht auf eine echte
Fahrt - die Strecke wird dann verworfen statt eine unmögliche Fahrt
anzuzeigen.
Tankerkennung: optionaler zweiter Sensor für das Tankvolumen in Litern
(TANK_LITER_SENSOR, direkt vom CAN) neben dem bisherigen
Prozent-Füllstand. Ist er zugeordnet, übernimmt er die automatische
Tankerkennung vollständig - genauer als der Umweg über das im
Fahrzeugprofil hinterlegte Tankvolumen, und der erkannte Anstieg
liefert gleich eine grobe Vorbelegung für die getankte Menge statt
eines leeren Feldes. Ohne den Sensor bleibt alles beim Alten. Der
historische Import zieht mit derselben Präferenz nach.
Manifest auf 2026.8.25.2, beide Änderungsrunden live im Testcontainer
verifiziert (py_compile, Neustart, sauberes Setup-Log).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dauerText() zeigte "1 Std. 15 Min." - der Besitzer wollte exakt die Schreibweise,
die companion-app/src/format.ts' dauer() bereits verwendet: "1 h 15 min", Minuten
zweistellig gepolstert. Betrifft sowohl die Einzelfahrt-Detailansicht als auch die
Dauer-Anzeige im Fahrt-Bearbeiten-Formular (gemeinsamer Helfer).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
vTrip() zeigte "75 min" statt der bereits vorhandenen dauerText()-Formatierung
("1 Std. 15 Min."), die jede andere Dauer im Panel schon verwendet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zwei Meldungen des Besitzers ("Update installieren" braucht manuelles
Neuladen, um den Neustart-Knopf zu zeigen; die "HA startet neu..."-
Anzeige ebenso) auf denselben Grund zurückgeführt: datenLaden() rief
render() nur bei Änderungen an profil/fahrten/tank/status/batt auf,
nie bei einer reinen Änderung des Versions-Sensors. Dazu ein bereits
im Code kommentiertes, bisher nur per Tab-Klick umgangenes Rennen
beim echten HA-Neustart gefunden und behoben: panel_custom baut das
Element neu auf, aber nichts zeichnete es automatisch, bis der Nutzer
irgendwo klickte. companion-app erhielt den passenden Fix für die
Neustart-Anzeige (Panel-Bug 1 betraf sie nicht, siehe AGENTS.md).
Alle drei Fixes live im Testcontainer über einen echten
homeassistant.restart bestätigt, nicht nur simuliert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Auf Update prüfen/Update installieren ließ die Seite im Seitenleisten-Layout
sichtbar nach oben springen - render()s eigene Scroll-Wiederherstellung
reichte hier nicht, vermutlich weil die Zustandsänderung des
Update-Sensors zusätzlich über HAs eigenes set-hass-Durchreichen an das
eingebettete Panel einen zweiten Render-Pfad anstößt. Statt die genaue
Ursache weiter zu jagen: fester Scroll-Merkwert vor dem Klick, per
requestAnimationFrame nach jedem eigenen render()-Aufruf dieses Ablaufs
erneut erzwungen. Live bei 1280x800 verifiziert: kein Sprung mehr.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Türschlösser auf ein Sensor reduziert (Fahrertür genügt, Zentralverriegelung
schließt alle Türen gemeinsam) - Kofferraum-/Motorhauben-Schloss entfernt.
- "Sicherheit" heißt im Panel jetzt "Fahrzeugstatus", wie in der companion-app.
- naechsterTermin() (Panel): sortierte null als Epoch 1970 und ließ dadurch
einen datenlosen Termin (Hauptuntersuchung ohne Eintrag/Erstzulassung) immer
vor einem echten, berechneten Termin (Ölwechsel) gewinnen - Ursache dafür,
dass Übersicht nach dem Leeren des Servicebuchs nichts mehr zeigte.
- "Licht ausgeschaltet" statt "Kein Licht" (Formulierung zurückgenommen).
- Große Bildschirme: Unterseiten (Standort, Service, ...) zeigten ihren Titel
in 26px statt der sonst überall genutzten 17px - wirkte neben dem
durchgängig leichten Fließtext wie Fettschrift, obwohl font-weight nirgends
wechselt. Jetzt dieselbe Standardgröße wie im Telefon-Layout.
Details und Verifikation in AGENTS.md.
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>
Der erste echte Live-Test des Selbst-Updates gegen das private Gitea-Repo
lief erfolgreich (mehrfach im Test-Container bestätigt) - deckte aber zwei
UX-Lücken auf, die der Owner direkt gemeldet hat:
- Prüfen/Installieren gaben während der 15-25 Sekunden dauernden
Netzwerkaktion keine sichtbare Rückmeldung - nicht von einem Hänger zu
unterscheiden. Jetzt ein Ladeindikator (Panel: wiederverwendetes
.lade-spinner; companion-app: neues .dm-spinner-Äquivalent, gab es dort
noch gar nicht).
- Nach erfolgreicher Installation stand nur ein Hinweistext da, kein Weg
zum eigentlich nötigen nächsten Schritt. Der Knopf wechselt jetzt zu
"Installation abschließen - Jetzt neu starten" und stößt
homeassistant.restart direkt an.
Das separat gemeldete "Lädt"-Hängenbleiben war kein Bug: reproduziert durch
Live-Test des neuen Neustart-Knopfs - eine echte HA-Verbindungsunterbrechung
während eines Neustarts zeigt exakt denselben, bereits bestehenden
Bootstrap-Ladebildschirm. Vermutlich derselbe Effekt durch den
Docker-Neustart früher in dieser Sitzung.
Verifiziert im Test-Container per Browser-Automatisierung: Neustart-Knopf
ausgelöst, Verbindungsabbruch beobachtet, per docker logs bestätigt, dass
Home Assistant tatsächlich neu gestartet ist und die neue Version aktiv
wurde.
Details in AGENTS.md, Abschnitt L.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Service -> Autohaus -> Zahnrad hat jetzt einen "vCard importieren"-Knopf
(öffnet den Dateiauswahldialog für .vcf). Liest FN/ORG, TEL, EMAIL, ADR
und befüllt das Formular - in beiden Frontends, jeweils passend zum
bestehenden Speicherverhalten (Panel speichert sofort, companion-app
erst über den vorhandenen "Speichern"-Knopf).
- update_pruefen/update_installieren loggten bisher nur bei einem Fehler -
ein erfolgreicher Aufruf war im Log nicht von "noch nicht ausgeführt" zu
unterscheiden. Jetzt auch eine Erfolgsmeldung.
- Panel: der feste Hinweis auf den fehlenden Gitea-Token stand dauerhaft in
der Integration-Update-Kachel, auch wenn ein Token längst hinterlegt war.
Erscheint jetzt nur noch als Teil einer echten Fehlermeldung.
Details in AGENTS.md, Abschnitte J (Nachtrag) und K.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zwei getrennte Themen in einem Commit, beide in derselben Sitzung entstanden:
1. Ölwechsel/Inspektion wurden komplett ausgeblendet ("kein Eintrag im
Servicebuch"), sobald kein Servicebucheintrag vorlag - selbst wenn der
zugeordnete Sensor eine gültige Fälligkeit meldete. In beiden Frontends
prüfte die Anzeige nur den Servicebuch-Zweig, bevor sie die
Fahrzeugmeldung überhaupt las. Jetzt steht die Fahrzeugmeldung für sich;
fehlt zusätzlich ein Servicebucheintrag, übernimmt eine neue,
fahrtenlog-basierte Prognose (kmProTagAusFahrten()/meldungsPrognose())
die Hochrechnung statt der Servicebuch-Rate - deckelt auf die vom
Fahrzeug selbst gemeldete Zeitgrenze, falls zu wenig gefahren wird.
2. install.ps1 als Update-Weg wird von Windows Smart App Control blockiert,
ohne Umgehungsmöglichkeit. Die Integration lädt sich jetzt auf
Tastendruck selbst von Gitea (aktualisierung.py), verifiziert das
Manifest vor jedem Tausch und tauscht per os.rename mit automatischem
Rollback bei Fehlern - install.ps1 bleibt nur noch für die
Erstinstallation nötig. Zugangstoken über einen neuen OptionsFlow in
entry.options, nie in configuration.yaml.
Nebenbei: mehrere seit der HACS-Ausschluss-Entscheidung liegen gebliebene
falsche HACS-Referenzen in Code-Kommentaren und einem UI-Text korrigiert.
Details, Sicherheitsbegründung und Verifikationsstand in AGENTS.md,
Abschnitte I und J.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Der am 2026-08-24 angelegte Spiegel nach github.com/T130B/DM360 hatte keinen
Zweck erfüllt: HACS lehnt private Repositories laut eigener Dokumentation
kategorisch ab, unabhängig davon, ob sie auf Gitea oder GitHub liegen. Ein
GitHub-Konto zusätzlich zu pflegen kaufte also nichts. Auf Wunsch entfernt -
entwickelt wird ausschließlich auf der eigenen Gitea-Instanz.
- hacs.json entfernt: tote Konfiguration ohne GitHub-Ziel, das sie bedienen
könnte.
- manifest.json: documentation/issue_tracker/codeowners zeigen jetzt auf
gitea.nothaft.cloud/paul/audi-app statt auf den abgeschafften Spiegel.
- install.ps1: Kopfkommentar nennt keinen aktiven Spiegel mehr.
- AGENTS.md: die HACS-Ablehnung als endgültig festgehalten (nicht nur "heute
privat"), samt der Begründung, warum ein erneuter GitHub-Anlauf nichts
ändern würde - falls das je wieder aufkommt.
Am laufenden Testcontainer geprüft: Integration lädt mit dem neuen Manifest
fehlerfrei neu, keine Fehler im Protokoll.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
HACS kann laut eigener Dokumentation grundsätzlich nicht mit privaten
GitHub-Repositories arbeiten (hacs.xyz/docs/faq/private_repositories) - keine
Ausnahme für Tokens oder verbundene Konten. Meine frühere Annahme, HACS käme
damit zurecht, wenn es unter dem richtigen Konto angemeldet ist, war falsch.
Da das Repository aus Lizenzgründen privat bleiben muss (Audi-Hausschrift,
Typenschilder), ist install.ps1 damit nicht die Rückfallebene, sondern der
einzige Installationsweg - README, INSTALL.md, ANLEITUNG.md, install.ps1 und
VERSIONIERUNG.md korrigiert.
Oberflächen-Updates für die iOS-App laufen jetzt ohne Xcode:
@capgo/capacitor-updater eingebaut, ein Update-Abschnitt in den
Einstellungen lädt ein neues Bündel und tauscht die Oberfläche aus. Kein
Selbstlauf (autoUpdate: false) - nur auf Tastendruck, nie während der
Benutzung.
Das Bündel liegt in der Integration selbst
(custom_components/audi_dashboard/frontend/app/), nicht unter /local/: so
reist es bei jeder Installation automatisch mit, ohne zweiten
Auslieferungsweg. Gebaut von companion-app/scripts/ota-paket.ps1 (neuer
Befehl: npm run ota), gemeldet über sensor.audi_dashboard_app_version
(neues Feld daten.buendel).
Ein echter Bug beim Bauen gefunden: [IO.Compression.ZipFile]::CreateFrom-
Directory schreibt unter Windows PowerShell 5.1 Backslashes in die
Zip-Einträge - iOS hätte das Archiv falsch entpackt. Behoben, indem die
Einträge von Hand mit "/" geschrieben werden.
Rückfallebene: notifyAppReady() läuft erst, wenn React nachweislich
gerendert hat (App.tsx). Kommt diese Meldung nicht, rollt das Plugin nach
20 Sekunden von selbst auf das vorherige Bündel zurück.
Am laufenden Testcontainer verifiziert: die ausgelieferte Zip hasht exakt
auf den in bundle.json hinterlegten Wert, 13 Einträge, index.html in der
Wurzel, keine Backslashes, keine Beschädigung. tsc sauber, 117/117 Tests
(5 davon neu für buendelPasst() - dabei eine echte Lücke gefunden: die
Funktion hätte bei unbekannter eigener Version fälschlich ein Update
angeboten, jetzt genauso vorsichtig wie versionVergleichen).
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>