4ab6b9fca57f36bcaa8a9ccf41e4ed16e8bf4fda
17 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4ab6b9fca5 |
Debug-Mode, eine Version-Kachel, Knoepfe nach HIG, Bilder ohne Verzoegerung (2026.9.4.11)
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. |
||
|
|
4d4890034a |
Regler stellt den Schlaf-Timeout des Dongles (2026.9.3.10)
Der Regler "Fahrt beenden" ist jetzt eine Zahl fuer zwei Dinge: unsere eigene
Wartezeit bis zum Fahrtende und der Schlaf-Timeout des FMM003 (103). So lange
bleibt der Dongle wach und wartet darauf, dass es gleich weitergeht; danach
schlaeft er. Die 180 s Ignition OFF Delay laufen davor und bleiben unsichtbar -
sie werden nur von der Fahrtdauer abgezogen. Der Regler geht deshalb von 1 bis
60 in Einerschritten; das Geraet kennt kein Timeout 0.
flespi.py liest und schreibt die Geraete-Konfiguration. Drei Annahmen sind an
der echten API gefallen und stehen als Messung im Modulkopf: der Wert liegt in
current (nicht value), die Einstellung heisst sleep_mode mit dem Wert eine Ebene
tiefer unter mode, und ein PUT braucht {"properties": ..., "address": ...}.
Die eigene Auftrags-Warteschlange ist wieder entfallen. Sie war fuer "das Geraet
schlaeft" gebaut - das gilt aber nur fuer das Geraet, nicht fuer die
Schnittstelle: die vollstaendige Konfiguration kam herein, waehrend das Fahrzeug
seit dem Vortag stand. flespi puffert selbst (pending + address=connection), ein
zweites Auftragsbuch waere eine zweite Warteschlange fuer dieselbe Aufgabe.
Gegengelesen wird nach jedem Schreiben; als Erfolg zaehlt current ODER pending -
letzteres ist bei stehendem Fahrzeug der Normalfall.
Live gegen den echten Account belegt: Token sieht genau ein Geraet, 127
Einstellungen bei parkendem Fahrzeug gelesen, Regler 15 geschrieben und als
pending bestaetigt (Nachbarfelder unveraendert), zweiter Neustart ohne erneute
Anfrage.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
8c96d9b78e |
Zugaenge: die Dienste-Token aus App und Panel bedienbar (2026.9.3.8)
Die Token liegen seit jeher in entry.options, geschrieben vom Options-Flow unter Einstellungen -> Geraete & Dienste -> Konfigurieren. Der Weg bleibt und ist der Rueckfall, wenn die App den Server nicht erreicht - genau der Fall, in dem ein abgelaufener Token auffaellt. Erreichbar ist er aber nur ueber HAs eigene Weboberflaeche; die iOS-App zeigt keine Konfigurationsdialoge. Die neue Kachel ist die Bedienflaeche dafuer, kein zweiter Speicherort. Der Wert kommt nie zurueck: veroeffentlicht werden nur "gesetzt/nicht gesetzt" und die letzten vier Zeichen (unter zwoelf Zeichen Laenge gar nichts). Auch das Protokoll bekommt ihn nicht, und das Panel leert das Eingabefeld sofort nach dem Absenden. Bewusst NICHT im Fahrzeugprofil: sicherung.py sichert fahrzeugprofil.json, und "Backup exportieren" laedt es als Datei auf das Geraet - ein Token dort wanderte in jede Sicherung und jede weitergegebene Datei. Ein Dienst statt zwei: zugang_setzen(dienst, token), leerer Text loescht. In der App nicht ueber die Warteschlange - ein Stunden spaeter nachgereichter Token ueberschriebe womoeglich einen inzwischen eingetragenen neuen. CONF_FLESPI_TOKEN ist neu und noch ohne Leser; der Flespi-Weg zum Auslesen der Geraetekonfiguration ist damit vorbereitet, aber nicht gebaut. Verifiziert: py_compile auf sechs Backend-Dateien, Panel als Modul geparst, companion-app tsc sauber und 179/179, audi_ha_test auf 2026.9.3.8 sauber gestartet. Live am laufenden Panel der ganze Kreis, Container hinterher wie vorgefunden: Wegwerf-Token gesetzt -> "gesetzt . ...0000", der Wert selbst taucht in den veroeffentlichten Attributen nirgends auf (darauf geprueft), ueber die Sicherheitsabfrage geloescht -> wieder "nicht gesetzt", der Gitea-Token unberuehrt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5ccbfec92d |
Fahrt beenden auf Knopfdruck, Schieberegler, Zuendungspause (2026.9.3.5-.7)
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> |
||
|
|
6016053a92 |
Kalender ueber EventKit, Orte nach dem Import, Fotos verkleinert, Signalsperre (2026.9.3.1-.3)
- Kalendertermine gehen nativ ueber EventKit statt ueber das Teilen-Blatt:
Apples Kalender meldet sich beim System gar nicht als Teilen-Ziel an, ein
anderes Dateiformat haette also nie geholfen (Abschnitt BS).
- Der Rueckblick stoesst jetzt selbst das Screening an, wenn er Fahrten
angelegt hat - sonst blieb eine importierte Fahrt ohne Ort liegen, solange
das Fahrzeug steht (Abschnitt BT).
- Fahrzeugfotos werden vor dem Upload im Browser auf 2000 px/WebP gebracht.
Gemessen: 3.099.022 -> 325.994 Bytes. Damit ist die Nachrichtengrenze der
WebSocket-Verbindung kein Thema mehr ("connection lost" auf der realen
Instanz). Formate, die der Browser weder umwandeln noch anzeigen kann,
werden mit klarer Meldung abgelehnt statt roh gespeichert.
- Zwei Wechsel des Fahrtsignals in derselben Sekunde kosteten eine ganze
Fahrt: das "on" ueberholte den noch laufenden Beende-Vorgang und fiel durch
beide Zweige. Neue asyncio-Sperre plus Regressionstest, der ohne sie
nachweislich rot ist (Abschnitt BU).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
38e7731a3d |
Rollende Zeitraeume, zwei Gesten, CI-Symbole und das Screening faellt nach (2026.9.2.8-.12)
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> |
||
|
|
b73a8fb334 |
Meldezeit auch nach hinten prüfen - "Geparkt seit 20698 Tg." war die Unix-Epoche
geraetezeit() prüfte nur, ob die Meldezeit in der Zukunft liegt. Ein Sensor, der 0 meldet, rutschte durch, und fromtimestamp(0) ergibt 1970 - auf der realen Instanz sichtbar als "Geparkt seit 20698 Tg. 9 Std. 39 Min.". Neu geraetezeit_plausibel(): nicht aus der Zukunft und nicht älter als MELDEZEIT_RUECKLAUF (365 Tage). Geprüft wird an drei Stellen - beim Auslesen der Gerätezeit, beim Setzen des Parkbeginns und beim LADEN aus dem Laufzeit-Store, denn ein einmal falsch gespeicherter Wert überlebt sonst jedes Update. Fängt auch eine im Setup falsch zugeordnete ID-Entität ab: das flespi-Gerät hat drei ID-Sensoren, deren Namen dem Zeitstempel ähneln, und deren Werte ergeben als Unix-Zeit ebenfalls 1970. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2af5c469d6 |
Ortsnamen aus dem Backend, Verbrauchsfaktor aus dem Tankbeleg, Radzaehler ueber Fahrten
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> |
||
|
|
d1e3f7230c |
Parkbeginn nach einem Neustart aus der Aufzeichnung holen (2026.9.1.7)
Der Zuhoerer bekommt den Zuendungswechsel nur mit, wenn Home Assistant laeuft. Ging die Zuendung aus, waehrend es unten war - ueber Nacht der Normalfall -, feuerte nichts, und die Registrierung beim Hochfahren wird bewusst ignoriert (sonst begaenne die Parkdauer bei jedem Neustart neu). Ergebnis war "Parkdauer unbekannt", obwohl der Zeitpunkt im recorder steht. _parkbeginn_nachholen() laeuft einmal in _nach_start und schlaegt ihn nach - nur, wenn kein Wert gespeichert ist und die Zuendung auf "aus" steht. Genommen wird der letzte echte Wechsel an -> aus im Fenster von sieben Tagen; gibt es keinen, bleibt es bei "unbekannt" statt den Rand des Fensters zu erfinden. Wieder mit der Meldezeit desselben Datensatzes statt seiner Ankunftszeit - dieselbe Begruendung wie in verlauf.geraetezeit(), hier rueckblickend. VERIFIZIERT in audi_ha_test, der Test trennt genau die beiden Zeiten: Speicher geleert, neu gestartet -> "Parkbeginn aus der Aufzeichnung nachgeholt: 09:04:57". Das ist die Geraetezeit; angekommen war der Datensatz um 09:44. Ein zweiter Neustart ruehrt den Wert nicht an, schreibt keine Zeile und erzeugt keinen Fehler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
553e128066 |
GNSS-Rollen vorbereitet, "Geparkt seit" von der Zuendung (2026.9.1.5/.6)
GNSS-STRECKENROLLEN, NOCH OHNE VERBRAUCHER 11806 steht seit dem 01.09. auf GNSS. Zwei neue Sensorrollen angelegt, damit nach der ersten echten Fahrt nur noch gemessen und nicht mehr zugeordnet werden muss: GNSS_KM_SENSOR (total_calculated_mileage, der robustere fuer eine Fahrtstrecke - ein verlorener Datensatz verfaelscht die Differenz nicht) und GNSS_TEILSTRECKE_SENSOR (segment_mileage, zeigt WO Strecke fehlt, taugt als Gegenprobe). Kein Code liest sie; die Zuordnung aendert nichts. KM_SENSOR bleibt der Anker - er ist der Tacho des Fahrzeugs und driftet nicht. Der alte Warnhinweis dort zeigt jetzt auf die neue Rolle statt ins Leere. "GEPARKT SEIT" KOMMT VON DER ZUENDUNG Die Anzeige rechnete "jetzt minus ts_end der juengsten Fahrt". Das ist keine Aussage ueber das Parken, sondern ueber die Fahrterkennung: am 01.09. stand dort "Geparkt seit 2 Tg. 16 Std.", waehrend am Vorabend 7 km gefahren wurden - die Fahrt fehlte im Bestand, weil trip_status festhing. Der Koordinator merkt sich jetzt den Zeitpunkt, zu dem die Zuendung zuletzt ausging, in der Zeit des Geraets. Er liegt im Laufzeit-Store neben fahrt_start_ts und ueberlebt einen Neustart. Kein Rueckfall auf die Fahrtenliste: null heisst unbekannt und wird auch so angezeigt - ausdrueckliche Ansage des Eigentuemers, eine falsche Zahl ist schlechter als keine. Beim Ausliefern fiel derselbe Neustart-Fehler auf wie bei der Phantomfahrt: der Zuhoerer las die Registrierung der Entitaet als Wechsel und stempelte den Parkbeginn bei jedem Neustart neu. if alt is None: return behebt es. Merkposten fuer dieses Projekt: jeder neue Zustandszuhoerer braucht diese Pruefung. VERIFIZIERT in audi_ha_test: Neustart laesst 09:34:15 unveraendert; Zuendung an -> null; Zuendung aus mit Geraetezeit von vor 40 Minuten -> 09:04:57 statt jetzt. Companion-App gleichgezogen, tsc --noEmit sauber, 165/165 Tests gruen. NOTIERT, NICHT GEBAUT: der GNSS-Zaehler driftet im Stand. Die 0,034 km waren GPS-Rauschen, nicht Aufloesung - der Dongle lag unbewegt. Die GNSS-Zuwaechse brauchen deshalb ein Bewegungstor, bevor sie summiert werden duerfen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4cc91c461b |
Fahrtzeiten vom Geraet, Trip und Zuendung getrennt (2026.9.1.3)
Enthaelt 2026.9.1.2, das nie einzeln ausgeliefert wurde. FAHRT- UND TANKZEITEN KOMMEN VOM GERAET Fahrtbeginn war datetime.now() - die Uhrzeit, zu der Home Assistant den Wechsel verarbeitet. Hat das Geraet gepuffert (Funkloch, Tiefgarage, Tiefschlaf), liegt die Wahrheit beliebig weit davor. Gemessen: ein Datensatz mit Fahrtende trug die Geraetezeit 07:29:04 und kam um 07:35:23 an. Neue Sensorrolle MELDEZEIT_SENSOR (message_timestamp, Unix-Sekunden). Der Wert ist UTC, keine Ortszeit - nachgemessen lag der Versatz zur UTC-Uhr von HA bei Sekunden, nicht bei zwei Stunden; eine Zeitzonenumrechnung baute einen Zwei-Stunden-Fehler ein. geraetezeit() liegt in verlauf.py, weil Fahrt- und Tankerkennung denselben Zeitstempel bestimmen muessen. tankerkennung._automatisch_anlegen() stempelte bisher ebenfalls mit now(); ein aus einem gepufferten Datensatz erkannter Tankvorgang trug damit die Uhrzeit des Auftauchens. Die flespi-Integration setzt die Entitaeten eines Datensatzes nacheinander - gemessen Zuendung 07:35:23.633, zugehoerige Meldezeit 2 ms spaeter. Wer sofort liest, bekommt den vorigen Datensatz: beim Fahren zehn Sekunden daneben, im Stand Stunden (On Stop Min Period = 43200 s). geraetezeit() wartet deshalb bis zu 2 s auf den passenden Wert. Zwei Notbremsen, beide live ausgeloest: Zeitstempel in der Zukunft und Ende vor dem Beginn. TRIP UND ZUENDUNG SIND ZWEI ROLLEN ZUENDUNG_SENSOR zeigte auf das Trip-Signal; im Setup stand "Zuendung/ACC" ueber einer Trip-Entitaet und die echte Zuendung war nirgends zugeordnet. Neu: TRIP_SENSOR loest Fahrten aus, ZUENDUNG_SENSOR liefert nur noch die Anzeige "faehrt/steht". verlauf.fahrtsignal() ist die eine Stelle, die entscheidet - Trip-Status wenn zugeordnet, sonst Zuendung, damit bestehende Installationen unveraendert weiterlaufen und Livepfad und Rueckblick nicht auseinanderlaufen. VERIFIZIERT in audi_ha_test, jeder Weg einzeln: - Fahrtbeginn 08:30:03 (Geraetezeit) statt 08:38:27 (Ankunft) - Fahrtende 08:04:40 -> 08:09:22 statt 08:11:04 -> 08:11:24 - Tankvorgang 08:18:45 statt 08:38:51 - 20 Minuten frueher - Meldezeit in der Zukunft und Ende vor Beginn: Warnung, Ankunft genommen - Zuendung schalten legt keine Fahrt mehr an, Trip-Signal schon Der Livetest fing dabei einen NameError, den py_compile nicht sehen konnte: der Import von geraetezeit in tankerkennung.py fehlte. Kompiliert ist nicht verifiziert. Alle Testdatensaetze wurden ueber die eigenen Dienste wieder entfernt; Bestand unveraendert 11 Fahrten, 13 Tankvorgaenge, keine offene Fahrt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c0acc836f0 |
Fahrgestellnummer (FIN) automatisch aus den zugeordneten Sensoren ableiten
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> |
||
|
|
f4222b715f |
Batteriespannung-Fallback: zeigt letzte Ruhespannungsmessung ueber Neustarts hinweg
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> |
||
|
|
70253e83a5 |
Fahrterkennung: FMM003-Funklöcher reißen keine Fahrt mehr auseinander
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> |
||
|
|
fb251154c7 |
Ölwechsel/Inspektion-Anzeige repariert, Selbst-Update der Integration gebaut
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>
|
||
|
|
1354ca6b06 |
OTA-Updates für die iOS-App; HACS-Fehlannahme korrigiert
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> |
||
|
|
d8b12da36d |
pyscript-Backend zur echten HA-Integration umgebaut (HACS-fähig)
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> |