Commit Graph

155 Commits

Author SHA1 Message Date
tobias d2994ce919 Standort: "Zuendung an" statt "Fahrzeug faehrt" (2026.8.30.14)
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>
2026-08-30 23:39:31 +02:00
tobias 534ce46096 Standort-Blatt: doppelter Sicherheitsabstand, deckender Hintergrund (2026.8.30.13)
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>
2026-08-30 23:35:43 +02:00
tobias 67135da4f7 Layer-Symbol: falscher Pfad in der App, zu klein in beiden (2026.8.30.12)
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>
2026-08-30 23:29:07 +02:00
tobias 0fd81df700 Ziehen zum Aktualisieren, Nachtmodus-Zeilen, Parkplatznamen (2026.8.30.10)
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>
2026-08-30 23:22:52 +02:00
tobias a08922e9a0 Befundliste des Besitzers: drei echte Fehler, dazu Feinschliff (2026.8.30.9)
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>
2026-08-30 23:13:01 +02:00
Paul Nothaft f38907991d iOS-App auf 2026.8.30.8 gebracht (Paritaetsrunden 2 und 3)
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.
2026-08-30 18:57:02 +02:00
tobias 4a58021670 Paritaetsrunden 2 und 3, Designpruefung umgesetzt (2026.8.30.8)
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>
2026-08-30 18:31:46 +02:00
Paul Nothaft 25c0d073c4 iOS-App auf den Stand des Paritaetsaudits gebracht (2026.8.30.2)
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.
2026-08-30 17:00:09 +02:00
tobias e1ebe6d694 Vollständiger Panel-companion-app-Paritätsaudit (11 Kapitel)
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>
2026-08-30 12:21:58 +02:00
Paul Nothaft 4fa5d4bc2d Eingabefelder zoomen nicht mehr: 16px setzen sich jetzt auch durch
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.
2026-08-29 13:34:07 +02:00
Paul Nothaft 4e97656a75 Korrektur: auch Ad-hoc-Apps verlangen seit iOS 16 den Entwicklermodus 2026-08-29 13:17:49 +02:00
Paul Nothaft b6a868df5e Ursache des Integritaetsfehlers festhalten: veraltetes Profil im Xcode-Zwischenspeicher 2026-08-29 13:16:02 +02:00
Paul Nothaft 49712f7c7a App neu signiert: Ad-hoc-Profil enthaelt jetzt beide registrierten Geraete 2026-08-29 13:15:26 +02:00
Paul Nothaft e46bec2e32 Luftweg ueber Gitea dokumentieren und den fertigen Safari-Link ausgeben 2026-08-29 13:04:27 +02:00
Paul Nothaft 84b0003070 Luftweg ueber Gitea: Manifest und Symbole in auslieferung/ ablegen 2026-08-29 13:03:41 +02:00
Paul Nothaft 959b98c93a Entscheidung des Besitzers festhalten: die .ipa bleibt im oeffentlichen Repo 2026-08-29 13:02:50 +02:00
Paul Nothaft b452c0a284 Befund festhalten: das Repository ist oeffentlich, die Lizenzregel verlangt privat 2026-08-29 13:00:44 +02:00
Paul Nothaft b4d44b2731 Signierte iOS-App gebaut und Luftweg-Installation vorbereitet
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.
2026-08-29 12:56:42 +02:00
Paul Nothaft fa7253a64c Team-Kennung nicht mehr vorbelegen: bezahltes Konto bekommt ein neues Team
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.
2026-08-29 11:44:10 +02:00
tobias 5fe19e5006 Merge remote-tracking branch 'origin/main' 2026-08-29 11:29:12 +02:00
tobias f9cd8de8fd AGENTS.md: QR-Code-Scanner fürs Token-Onboarding als offenen Punkt aufgenommen
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.
2026-08-29 11:28:36 +02:00
Paul Nothaft 0e16f68b4b Korrektur: das Apple-Konto ist ein kostenloses Personal Team
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.
2026-08-29 11:22:21 +02:00
Paul Nothaft da85a2c0d6 iOS-Signierung vorbereiten: Skript, Nachweis des Gerätebaus, offener Punkt
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.
2026-08-29 11:17:46 +02:00
tobias 44522db34e Internetzugriff: trusted_proxies-Fix bestätigt, fehlenden Freigabe-Block dokumentiert
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.
2026-08-28 18:13:11 +02:00
tobias 355177a50a INTERNET_ZUGRIFF_EINRICHTEN.md: Sicherheits-Checkliste ergänzt, Cloudflared-Add-on konkretisiert
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>
2026-08-28 15:49:24 +02:00
tobias 137d32d28d Domain auf datametric360.de umgestellt (war .app)
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>
2026-08-28 15:06:07 +02:00
tobias 3ad1809af6 Internetzugriff: fehlenden Einrichtungs-Runbook nachgereicht, Pfad-Freigabeliste korrigiert
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>
2026-08-28 14:41:10 +02:00
tobias 391725e663 Setup-Menü: Sensorhinweis auf (z. B. tatsächlicher Sensor) reduziert
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>
2026-08-28 14:40:55 +02:00
tobias bf1f9646e2 REVERSE_PROXY.md auf aktuelle Entitäts-/Dienstnamen korrigiert
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>
2026-08-28 12:01:19 +02:00
tobias 6b35de458d Fahrgestellnummer: expliziter "automatisch"-Schalter statt Nur-wenn-leer-Heuristik
- 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>
2026-08-28 12:01:10 +02:00
tobias 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>
2026-08-28 11:47:08 +02:00
tobias 8f88ccf581 Zuletzt-Kachel: Werte jetzt wirklich spaltenbündig
- .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>
2026-08-28 11:31:07 +02:00
tobias dd8d62e3b3 Tanken: Distanz-Vorschlag bevorzugt TANK_DISTANZ_SENSOR; Zuletzt-Kachel: Zeilenabstand ergänzt
- 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>
2026-08-28 11:26:23 +02:00
tobias ff9aaeb338 Setup-Menü: runde Klammern aus Feld-Labels entfernt, Popup verbreitert
- 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>
2026-08-28 11:19:28 +02:00
tobias d1cc742a59 Setup-Menü: Sensorkennung per Mehrheitsentscheid statt nächstem Nachbarn; Ellipsis entfernt; Filter/Tanken-Fixes
- 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>
2026-08-28 11:15:12 +02:00
tobias 4f85a179cf Setup-Menue: Sensorkennung per naechstem Verwandten statt globalem Praefix
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>
2026-08-28 10:54:16 +02:00
tobias af64fc39e3 Setup-Menue: Sensorkennung ohne installationsspezifisches Praefix, Einheit statt Live-Wert
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>
2026-08-28 10:45:45 +02:00
tobias b1cd03be51 Wartungsplan-Schema companion-app<->Panel angeglichen; Setup-Feldkopf zeigt zugeordneten Sensor
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>
2026-08-28 10:38:27 +02:00
tobias 2be6b99667 companion-app: Datensatz sichern/laden portiert (Item 9 Paritaet)
- "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>
2026-08-28 10:31:10 +02:00
tobias bfb7dec1e9 TANK_DISTANZ_SENSOR + Datensatz sichern/laden mit echtem CSV-Import (Panel)
- 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>
2026-08-28 10:19:06 +02:00
tobias edefdd66d8 Reifen/Version/Wartungsplan: erste Runde des Sammel-Feedbacks behoben
- 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>
2026-08-28 09:43:40 +02:00
tobias bdd8cb89a3 Batterie-Messwertliste: Zeilen sehen nicht mehr klickbar aus (Cursor/Presshighlight)
.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>
2026-08-28 00:47:57 +02:00
tobias 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>
2026-08-28 00:23:16 +02:00
tobias 90fff7b305 Vollaudit: sechs echte Fehler in Backend, Panel und companion-app behoben
- 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>
2026-08-28 00:05:58 +02:00
tobias 8ba3519090 Fix: ReferenceError bvRuhePunkte in vBatterieverlauf() - Batteriespannung-Klick brach das Rendering ab
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>
2026-08-27 23:33:49 +02:00
tobias e1ddf2cda1 AGENTS.md: dokumentiert den Update-Vorfall - Selbst-Update hat unveroeffentlichte Sitzungsarbeit ueberschrieben
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>
2026-08-27 23:24:24 +02:00
tobias 172db54e7a Statistik-Icon-Groesse, Batteriediagramm-Ueberarbeitung, Temperatur-Kopplung mit 300s-Fenster, letzte gueltige Spannung als Fallback
- 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>
2026-08-27 23:23:12 +02:00
tobias 80d73e8afd Fahrten: Verbrauch-Näherung, 0V-Zustandsanzeige gefiltert, Plausibilitätsgrenze für die Live-Vervollständigung
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>
2026-08-27 21:01:57 +02:00
tobias cf57c5f1a5 Batteriespannungs-Diagramm: feste 170px-Höhe statt aspect-ratio, Y-Achse geklemmt
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>
2026-08-27 18:33:31 +02:00
tobias b8e560e75b Batteriespannung: Diagramm-Y-Achse fest 10-15V, Plausibilitätsgrenze auf 10V angehoben
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>
2026-08-27 18:06:12 +02:00