Commit Graph

33 Commits

Author SHA1 Message Date
tobias ec55e5808e Fix real tab-bar-icons-vanish bug, dropdown popup color, wheel/Montiert swap
The reported "whole tab bar disappears when hiding labels" bug was real,
just one level deeper than first checked. .tabbar.ohne .tab span{display:
none} targeted the label span, but the icon is also wrapped in a <span
class="tabpille"> - a bare "span" type selector doesn't care about class,
so the icon's own wrapper collapsed too. Confirmed by measuring the <svg>
directly (0x0 bounding rect) after a live screenshot showed all 5 tab
buttons empty. Fixed with :not(.tabpille) in both stylesheets.

The Modell dropdown was still bright despite the color-scheme hint from
the last commit: a <select>'s opened option list is rendered by the
browser/OS as its own surface, entirely outside the page's paint tree -
confirmed when a screenshot call hung 30s trying to capture it open.
color-scheme only gets partial credit there; explicit background-color/
color on <option> is what Chrome/Firefox/Edge actually honor for the
popup rows. Added that, verified via getComputedStyle since the open
popup itself can't be screenshotted by this tooling.

Swapped the wheel photo (now right-aligned via margin-left:auto on the
now-correctly-square .bildbox.radbild) and Montiert (already left) per
request.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 20:52:46 +02:00
tobias 17b25d492a Fix wheel-photo squareness bug, native select popups, image-cycle crash
.bildbox.radbild lost to a same-specificity, later-declared .bildbox rule,
so the wheel photo stayed a full-width 4:3 box despite the earlier crop
fix - only which slice showed ever changed. Fixed with a compound selector
and moved "Montiert" to top-left to match the now-correctly-sized photo.

Native <select> popups had no color-scheme hint and rendered in the
browser's default light palette regardless of the app's dark theme -
this is what made "Modell" and other dropdowns flash bright white.

bildWeiter() (Mein Audi image-cycle tap) referenced a CSS class that was
never emitted (.platzhalter-datei vs. the real .platzhalter-aktion),
throwing and aborting before the page-dot indicator update - the photo
advanced but the dots never moved.

Merged the separate "Fahrzeugbilder" upload grid into "Bild der
Übersicht": pick a view from the existing dropdown, tap its preview to
upload/replace/delete - same generic popup plumbing, no new mechanism.
Removed the now-dead BILDER_UPLOAD_SLOTS/.bildgrid/.bildslot/.carfix.mini.

Back arrow changed from red to the neutral headline color, matching every
other navigation-color decision in this project.

Investigated but could not reproduce: user-reported "whole tab bar
disappears" when hiding labels. Traced the exact commit that added the
icon+label highlight and confirmed it's correctly scoped to :not(.ohne);
live DOM/computed-style testing across toggle, navigation, and both
mobile/desktop widths showed the tab bar staying visible throughout.
Left unchanged pending a repro from the user.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 20:40:14 +02:00
tobias 367985ba44 UI polish batch + fix genuinely-invisible map pins, Apple HIG audit
Battery voltage stat cutoff 13.2V -> 12.8V (values above that are already
alternator output, not the battery); fixed the battery chart's Y-axis
"stretching" on zoom by computing it once from the full dataset; removed
two explanatory paragraphs from the battery detail view; Tankfuellung now
shows "X % / X l"; removed the "noch etwa X l im Tank" suffix; fuel bar
color now matches the headline instead of a red/yellow/green gradient;
active/primary buttons are grey again, not red (destructive stays red per
HIG); select fields gained an Apple-HIG pull-down chevron (appearance:none
had removed the native one with nothing replacing it); selected menu icon
is white on desktop, matching mobile; Reifenfoto crops from the right edge;
"Montiert" button rebuilt as a compact top-right pill with a 44px invisible
tap target; tab-bar active highlight now covers icon+label, not just the
icon; removed two leftover explanatory texts from Einstellungen.

Root-caused the map pins looking "transparent": the CI poi-car/poi icons
are pure contour forms (nonzero-fill-rule ring + thin detail lines, only
13-40% of their own bounding box actually filled). Fixed by extracting each
icon's own first sub-path (the true outer balloon silhouette, verified by
rasterizing it in isolation) as a solid-filled layer behind the original
icon, applied to both the vehicle and station markers.

Read Color/Typography/Layout/Buttons/Materials on developer.apple.com and
applied the user-approved subset (11px text floor, 44px tap targets);
declined items (font weight, materials) documented with rationale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 19:05:54 +02:00
tobias 899b770cfa Einzelbeleg: CI poi pin from the receipt address, plus a centre button
The station marker was a red circleMarker. It is now the CI poi pin
(poi-l/poi-s via tankstellenMarkerSVG) - the plain pin rather than poi-car, so
the vehicle and the station stay distinguishable on a map.

While testing it turned out nothing in the backend ever writes station_lat /
station_lon, so that marker had never been reachable in practice. The receipt
address is now geocoded in the frontend via Nominatim /search
(adresseAufloesen, the forward counterpart to the existing reverse lookup),
with results cached in localStorage - negative ones too, since a station
address does not move and Nominatim's terms ask for caching. Verified live:
"Shell, SÖLDEN" resolves to 46.9756 / 11.0111.

The map card gained a centre button (CI.gps, which is byte-identical to the
delivered gps-s.svg), disabled until the coordinates arrive. .mapbox needed
position:relative so the control anchors to the card instead of an ancestor.
Only in the Einzelbeleg, as requested - the Standort fullscreen already has
its own centre controls.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 13:15:20 +02:00
tobias 484f2ffe6d Add one-click installer to installationspaket
Installieren.cmd (double-click) wraps install.ps1, which automates steps 1-3
of ANLEITUNG.md: find the HA config share, copy pyscript/, data/ ->
audi_dashboard/ and www/, merge the configuration.yaml snippet, optionally
write ha_token.txt. The .cmd wrapper exists because double-clicking a .ps1
opens it in an editor and the execution policy blocks it; the bypass applies
to that one call only.

Designed to be safe to re-run:
- Never overwrites fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl,
  entitaeten.json or ha_token.txt, so re-running on a live install keeps the
  vehicle profile, trips, fills and sensor mapping.
- configuration.yaml is backed up to .bak first; the inserted part sits
  between marker lines and gets replaced instead of appended twice.
- If pyscript: or panel_custom: are already there from another source, the
  file is left untouched and the script prints what to merge by hand -
  duplicate top-level keys would be invalid YAML and HA would not start.
- Aborts before writing if the target has no configuration.yaml.

Steps that cannot be automated from a Windows share (HA restart, pip install
pypdf, sensor mapping) are collected into a closing to-do list. -Pruefen shows
what would happen without writing.

install.ps1 is stored UTF-8 *with* BOM - PowerShell 5.1 reads scripts as ANSI
otherwise and mangles the umlauts; the files it writes stay BOM-less.

Verified against a fake config tree: fresh install, re-run idempotency,
existing-data preservation, foreign-key refusal, wrong-directory abort, and
the merged configuration.yaml parses as valid YAML.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 13:02:02 +02:00
tobias fb38c297bd Station name as "brand, street, city", grey box on all editable fields
The "grey box around the icons" report turned out not to be a defect: the box
on "10.000 km"/"1 Jahr"/"15" is the wanted pattern, and every value the user
can change should carry it. All .feld inputs and selects now get the grey iOS
fill; inputs with their own visual language (checkbox/radio/range/file) keep
the transparent base rule, so the switches are unaffected.

Fuel stations are now displayed as "Shell, Pascalstr. 8, Ingolstadt" instead of
the bare operator name. New _marke()/_ist_strasse()/_tankstelle() helpers are
shared by both parser paths so Shell and non-Shell receipts format the same.
The brand is only matched against the receipt header - searching the whole text
would let "Total" hit a totals line. Missing parts are dropped instead of
leaving empty comma slots, and without a known brand the operator name takes
its place. station_address still carries the full street and postcode.
test_bekannte_stationen updated to the new format; suite stays green.

installationspaket/ is versioned from now on (user request). It contains no
real vehicle data - only the example profile with empty FIN/plate placeholders.
Keep it in sync whenever pyscript/ or www/ changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 12:52:31 +02:00
tobias 39da68cd87 Fix broken map rendering, split GPS cleanup, receipt parser and design backlog
Leaflet's stylesheet was appended to document.head, so it never reached the
panel's shadow root: .leaflet-tile{position:absolute} never applied, tiles laid
out as in-flow images (~1040px inside a 190px box) and the marker pane ended up
far below the visible area. That is the real cause of the long-standing
"fragmented Leaflet rendering" finding and of the invisible vehicle pin - every
tile request had actually succeeded. The stylesheet now goes into the shadow
root and is awaited before the map is built.

Also in this round:
- Map tiles are always light (Google-Maps-style), no dark variant at night.
- Vehicle marker uses the real CI poi-car icons (poi-car-l >=34px, poi-car-s
  below), with a white halo so the outline stays readable on tiles.
- Removed the obsolete combined STANDORT_TRACKER field; only the split
  lat/lon sensors remain.
- Receipt upload: widened the try block so base64/save failures surface, and
  the frontend call site now reports a rejected service call.
- Generic receipt parser: total detection is line-based (letter-spaced
  headings, no more matching the SUMME-EUR column header, tax lines excluded),
  address heuristic handles 4-digit postcodes and single-line address blocks,
  and "Preis/L" matches without a spelled-out "Liter".
- Design backlog: red hairline frame on list rows (delete button bled through
  at fractional row heights) and select fields now use the grey background box.

Shell 10-receipt regression suite still passes; all changes verified live in
the audi_ha_test container.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 12:46:48 +02:00
tobias 25d1cebd12 Fuenf gemeldete Bugs behoben: Haubenschloss/Tuerschloesser entfernt, Bestaetigungsdialog-Transparenz, geteilte FMM003-Koordinaten, Laedt-Haenger, generischer Beleg-Parser
Entfernt Haubenschloss-/Tuerschloss-Erkennung dauerhaft aus Setup-Katalog und
Sicherheitscheck (auf ausdruecklichen Wunsch, nicht nur leer/unzuordenbar wie
der Rest der abgeloesten VAG-Integration). Behebt eine durchscheinende
Bestaetigungs-Sheet ("Doppelt zugeordnet" u.a.) - derselbe --tile-2-
Transparenz-Fehler, der fuer das Setup-Popup schon behoben war, hier
nachgezogen. Ergaenzt einen zweiten GPS-Pfad (STANDORT_LAT_SENSOR/
STANDORT_LON_SENSOR) fuer Integrationen wie flespi, die Breiten-/Laengengrad
als zwei eigene Sensoren statt als device_tracker-Attribute liefern. Haertet
den bekannten "Laedt ..."-Haenger beim App-Start zusaetzlich ab: Tab-Klicks
pruefen jetzt aktiv nach, ob Daten inzwischen da sind. Ergaenzt
shell_beleg_parser.py um einen stationsunabhaengigen Fallback fuer
Tankbelege unbekannter Formate (Adresse/Gesamtbetrag/Menge/Rabatt-Herleitung
wie vom Nutzer vorgegeben) - die bestehende Shell-Erkennung bleibt
unveraendert und weiterhin durch die zehn echten Testbelege abgedeckt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 11:32:15 +02:00
tobias 440ff22bda EU-Data-Act-Reste bereinigt, Slider-Bug behoben, zwei Design-Audit-Runden umgesetzt
Entfernt die letzten Verweise auf die abgeloeste TommiG1/HA_VAG-EU-Data-Act-
Integration (Versionstile, Testumgebungs-Fixture) und ersetzt sie durch die
FMM003-Werte. Behebt eine CSS-Spezifitaetskollision, durch die alle iOS-
Toggle-Switches viel zu breit gerendert wurden. Dokumentiert und behebt sieben
Layout-Befunde aus zwei Design-Audit-Runden (Zahnrad-Ueberlauf auf breiten
Bildschirmen, zu kleine Ringe als mobiler Einstellungen-Zugang, zu breite
Popups, Kopfzeilen-Versatz, ueberlappende Kachel-Pfeile, fehlender
Editierbarkeits-Hinweis bei Auswahlfeldern, Haekchen-artige Auf/Zu-Pfeile) -
siehe DESIGN_AUDIT_2026-08-13.md fuer Root-Cause und Beleg je Befund.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 20:52:07 +02:00
tobias 5fc86d2b5e iOS-Optik: Rot-Semantik korrigiert, Popup-Radius vereinheitlicht
Zwei unabhaengig vom iOS-Entscheid offene Befunde aus DESIGN_REVIEW_2026-08-13.md
§B behoben:

- .aktion (audi-dashboard-ios.css) fuellte bisher JEDE Aktion rot statt nur
  destruktive - jetzt neutrale --ios-fill-Flaeche fuer die Sekundaeraktion,
  neue .aktion.primaer-Regel traegt die rote Fuellung als einzige Stelle
  (deckt sich mit dem Sekundaer/Primaer/Loeschen-Schema, das die Basis-CSS
  schon vorgibt). Gleiche Ursache auch bei Schalter-Ein-Zustand (jetzt --ok
  gruen statt rot, echtes iOS-Systemgruen) und aktiver Desktop-Sidebar-
  Navigation (Flaeche jetzt neutral, Rot bleibt Text-/Icon-Akzent).
- Zwei Balkensegmente in audi-dashboard-app.js nutzten --red fuer eine
  neutrale Kategorie (Arbeitsweg-Fahrten, Versicherungsbeitrag-Aufteilung) -
  jetzt wie die Nachbarsegmente auf --fg umgestellt.
- .setup-popup/.standortmenu (audi-dashboard.css) hatten 20px als Literal
  statt var(--r-tile) - folgen jetzt dem Token wie alle anderen Kacheln.

Im Docker-Testcontainer verifiziert: Setup-Popup, Einstellungen (mobil und
Desktop-Sidebar), Schalter - korrekte Fuellungen, keine Konsolenfehler.
2026-08-13 19:31:16 +02:00
tobias f5976e6865 iOS-Optik offiziell machen, Audi-CI-Spezifikation vorher archivieren
Entscheidung nach DESIGN_REVIEW_2026-08-13.md §A, Option 1: die additive
iOS-Auflage (audi-dashboard-ios.css) wird zur verbindlichen Optik erklaert,
statt die App auf reine Audi-CI zurueckzuschneiden. Der bisherige
SPECIFICATION.md-§2-Wortlaut (Audi-CI-Farben, 20px-Radius) ist wortgleich
in AUDI_CI_ARCHIV_2026-08-13.md gesichert, inklusive Anleitung fuer den
Rueckweg - der Code selbst braucht dafuer kein Backup, da die iOS-Auflage
rein additiv ist und die Audi-CI-Basiswerte in audi-dashboard.css
unveraendert erhalten bleiben.

SPECIFICATION.md §2 beschreibt jetzt die tatsaechlichen iOS-Werte aus
audi-dashboard-ios.css. bauauftrag.md §8 bleibt unangetastet (Projekt-
konvention: historisches Dokument), gilt aber ab hier als ueberholt.

Zwei aus demselben Review noch offene Implementierungsfehler (Rot-Semantik
invertiert, 20px/16px-Radius-Inkonsistenz bei Popups) sind unabhaengig von
dieser Richtungsentscheidung und bleiben offen.

Zusaetzlich: Versionsbump nach dem Redeploy in audi_ha_test.
2026-08-13 19:20:28 +02:00
tobias 163efe1392 Merge branch 'umsetzung-datametric360': Companion-App-Phasen 1-10 uebernehmen
Bringt die vollstaendig gebaute DataMetric360-App zusammen (React/Vite,
21 Screens, Audi-Assets, PWA + native Capacitor-Huelle, 90+9 Tests) sowie
die profil_lesen()-Haertung gegen fehlende/kaputte Profildatei zusammen.

Konfliktaufloesung:
- AGENTS.md, INSTALL.md, README.md: main-Fassung war jeweils die
  chronologisch neuere, uebernommen und um die durch den Merge tatsaechlich
  erledigten Punkte ergaenzt (profil_lesen()-Haertung, Audit-Reste-Entscheidung).
- fahrterkennung.py: toten WLAN-Zweig vom Branch verworfen, Zuendungs-
  basierte Erkennung von main behalten.
- homeassistant/FMM003_MAPPING.md (MQTT/Mosquitto-Ansatz vom 2026-08-11,
  vor der Umstellung auf flespi) bewusst nicht uebernommen - main nutzt seit
  2026-08-12 flespi als alleinigen FMM003-Datenweg. UMSETZUNGSPLAN.md Phase 13
  entsprechend als ueberholt markiert, verweist auf AGENTS.md als massgeblich.
- REVIEW_main_2026-08-13.md, ha_install.md (add/add): main-Fassung war die
  spaetere Revision derselben Dokumente, uebernommen.

Die von REVIEW_main_2026-08-13.md befuerchtete Merge-Falle (profil_lesen()
gibt jetzt None zurueck, main-seitige Aufrufer pruefen das nicht) wurde
verifiziert als bereits entschaerft: alle 5 Aufrufstellen im gemergten Stand
(backup.py x2, fahrterkennung.py, frontend_veroeffentlichung.py,
reifenzaehler.py, tankerkennung.py) sind None-sicher.

installationspaket/ nicht Teil dieses Commits (gitignored, wird bei Bedarf
neu zusammengestellt).
2026-08-13 19:03:20 +02:00
Paul Nothaft 2a3c4f2ab5 Zugangswege zum privaten Repository dokumentieren und trennen
Neue Option --update-repo trennt, woher installiert wird, von dem, was als
Updatequelle hinterlegt wird. Damit laesst sich mit vollen Zugangsdaten
installieren, ohne sie abzulegen (--update-repo aus). Enthaelt die hinterlegte
URL Zugangsdaten, weist das Skript darauf hin und maskiert sie in der Ausgabe.

Neuer Abschnitt 1b in ha_install.md beantwortet die drei naheliegenden Fragen
und benennt den Haken dahinter:

- Werkzeuge sind vorhanden. git 2.54, curl, unzip und ssh liegen im
  offiziellen HA-Container bereits vor, an der Instanz nachgesehen.
- Passwort in der URL funktioniert genauso wie ein Token - es ist aber das
  Kontopasswort, im Klartext in /config und in jeder Sicherung, und bei
  Zwei-Faktor-Anmeldung verweigert Gitea es ohnehin.
- Ein vorher im Terminal eingerichteter Anmeldehelfer hilft der
  Selbstaktualisierung NICHT. Sie klont aus dem Home-Assistant-Prozess und
  allein anhand von UPDATE_REPO_URL; _git() setzt keine Umgebung. Unter HA OS
  laeuft das Terminal-Add-on ausserdem in einem eigenen Container, geteilt ist
  nur /config. Fuer die Installation selbst genuegt der Helfer dagegen.

Dazu eine Optionstabelle mit Bewertung, der Hinweis dass auch curl fuer das
Skript selbst Zugang braucht, und was sich nach der Umstellung auf die
Integration daran aendert: der Zugang wandert in den Konfigurationsdialog und
Home Assistants eigene Ablage statt in eine Python-Datei.
2026-08-13 17:21:19 +02:00
Paul Nothaft c11c492d86 Installationsskript: eine Zeile statt dreissig Minuten Handarbeit
homeassistant/install.sh richtet das Panel samt Backend auf einer
Home-Assistant-Instanz ein und verdrahtet dabei die Selbstaktualisierung, so
dass danach alles Weitere ueber die Weboberflaeche laeuft: Sensoren zuordnen,
nach Updates suchen, einspielen.

Gedacht fuer das Add-on "Terminal & SSH" direkt auf der Instanz:
  bash <(curl -fsSL <ROH-URL>/homeassistant/install.sh)
Alternativ von einem Rechner aus mit --ziel gegen ein eingebundenes
config-Verzeichnis, oder mit --von gegen eine lokale Arbeitskopie.

Was es tut: pyscript installieren (neueste Version von GitHub, falls nicht
vorhanden), pyscript/ und www/ einspielen, den Belegleser mitliefern (er
liegt in data/, ist aber Code), fehlende Datenbestaende aus der Vorlage
anlegen, den Abschnitt in die configuration.yaml eintragen und
UPDATE_REPO_URL setzen.

Drei Eigenschaften, auf die es dabei ankommt:

- Mehrfach ausfuehrbar. Der Abschnitt in der configuration.yaml steht
  zwischen Markern und wird beim zweiten Lauf ersetzt statt angehaengt.
  Stehen pyscript oder panel_custom bereits ausserhalb dieses Abschnitts,
  weist das Skript darauf hin, statt einen doppelten Schluessel zu erzeugen.
- Vorhandene Daten bleiben unangetastet. Fahrzeugprofil, Fahrten,
  Tankvorgaenge und ein bereits hinterlegtes Token werden nie ueberschrieben,
  nur fehlende Dateien angelegt.
- Die configuration.yaml wird vor jeder Aenderung mit Zeitstempel gesichert.

Geprueft gegen eine frische Home-Assistant-Instanz im Container: HA startet
ohne Konfigurationsfehler, alle neun pyscript-Entitaeten werden
veroeffentlicht, das Panel ist als "Mein Audi" mit mdi:car-sports unter
/audi-dashboard-panel registriert und rendert im Browser mit fuenf Tabs. Ein
zweiter Durchlauf laesst Profil und Token unveraendert und den
Konfigurationsabschnitt genau einmal stehen.

Ausserdem den blockierenden Verlaufsabruf in fahrtabschluss_logik.py
uebernommen: urlopen lief direkt statt ueber task.executor, was Home
Assistant seit 2026.8 abbricht - jede Fahrt waere ohne Strecke geblieben.
Der Fix lag bisher nur im Branch umsetzung-datametric360; eine frische
Installation haette den Fehler sonst mitgebracht.

INSTALL.md nennt den schnellen Weg jetzt vor der ausfuehrlichen Anleitung.
2026-08-13 16:20:34 +02:00
Paul Nothaft e1180f8e34 Kleinere Befunde und Dokumentation aus dem Review
Frontend, kleinere Befunde:
- Das Standort-Menue liess sich nur wischen oder ueber den Kartenmarker
  oeffnen. Der Griff ist jetzt ein Knopf mit aria-expanded, damit auch per
  Tastatur erreichbar; der Umschalter Strasse/Satellit hat aria-pressed und
  ein Label, das den Zustand nennt.
- Der Filterschalter "Nur passende Sensoren anzeigen" wirkte nicht, solange
  eine Auswahlliste offen war: der Klick-Handler ersetzte das Overlay-DOM,
  bevor das change-Ereignis des Kontrollkaestchens ausgeliefert wurde. Er
  wird jetzt vor dem Schliessen der Liste behandelt.
- Der Theme-Wechsel zeichnete nicht neu, die Leaflet-Kacheln blieben bis zum
  naechsten Backend-Update im alten Stil - seit der Dauerkarte auf der
  Uebersicht deutlich sichtbar.
- Toter Code entfernt (fahrzeugGlyphPfade, .dot.neutral) und zwei Kommentare
  berichtigt, die Gegenteiliges behaupteten.

Dokumentation:
- AGENTS.md widersprach sich an sechs Stellen. Berichtigt: Fahrterkennung
  laeuft ueber die Zuendung, nicht ueber WLAN; Datenweg ist flespi, nicht
  MQTT; Modulzahl und Zeilenzahl stimmen wieder; Entity-IDs werden im
  Setup-Menue zugeordnet, nicht in einstellungen.py; STANDORT_TRACKER ist
  belegt, nicht leer.
- SPECIFICATION.md beschreibt durchgehend den Stand vor der FMM003-
  Umstellung. Statt es zu Teilen umzuschreiben und dabei Ungenauigkeiten zu
  riskieren, steht jetzt ein datierter Hinweis am Anfang, der die drei
  geaenderten Punkte benennt und auf AGENTS.md verweist. Alles Uebrige des
  Dokuments gilt unveraendert weiter.
- INSTALL.md: Die zirkulaere Schrittfolge (Schritt 4 verweist auf 9, Schritt
  7 auf 4) ist als solche benannt und aufgeloest. Die Override-Datei ist mit
  Pfad genannt, samt dem Hinweis, dass sie gesichert wird. Und die drei mit
  Test-Entitaeten der Entwicklungsinstanz vorbelegten Rollen sind erwaehnt -
  auf einer frischen Installation zeigen sie ins Leere.
- README, Profilvorlage: WLAN-Reste entfernt, zwei Falschaussagen aus dem
  ersten Review nachgezogen (Statistik rechnet echt, die
  97-Prozent-Volltankungsregel wurde entfernt), Dateiuebersicht um die
  fuenf fehlenden pyscript-Dateien und entitaeten.py ergaenzt.
- update.ps1 liefert jetzt auch shell_beleg_parser.py aus. Die Datei liegt in
  data/, ist aber Code - Aenderungen am Belegleser, dem einzigen getesteten
  Teil des Projekts, kamen bisher auf keiner Instanz an.
- design/README: Zwei Dateien der Inhaltstabelle liegen gar nicht in dem
  Ordner, weshalb das Board aus der Repo-Kopie heraus leer bleibt - jetzt
  vermerkt. Ausserdem die Behauptung berichtigt, die Auflage ruehre
  audi-dashboard-app.js nicht an: der Stylesheet-Loader wurde dort ergaenzt.

Geprueft: Panel laedt, alle neun pyscript-Entitaeten werden veroeffentlicht,
Zuordnen und Zuruecksetzen funktionieren, keine neuen Fehler im Protokoll.
2026-08-13 16:10:19 +02:00
Paul Nothaft bc2834e867 Bedienbarkeit, CSS-Robustheit und drei Anzeigefehler
Befund 9: In Telefonbreite blendet die iOS-Auflage das Zahnrad aus, die Ringe
waren dort der einzige Zugang zu den Einstellungen - als div mit
pointer-events:none aber weder fokussierbar noch fuer Sprachausgabe
erreichbar. Sie sind jetzt ein echter Knopf mit aria-label, in jeder Breite
bedienbar und unabhaengig davon, ob die Auflage geladen wurde.

Befund 10: .navmarke{display:none} stand nur in der iOS-Auflage. Ohne sie
waere der Markenklon ein sechstes Element im fuenfspaltigen Raster und die
Menueleiste zerfiele. Die Regel steht jetzt in der Basis-CSS, die
Sichtbarkeit in der Auflage - genau andersherum als bisher.

Befund 13: Das Setup-Fenster deklariert role=dialog aria-modal=true, hielt den
Vertrag aber nicht ein. Escape schliesst jetzt (Reihenfolge: Auswahlliste,
dann Fenster), der Tabulator wandert im Fenster im Kreis statt in den
verdeckten Hintergrund, und der Filterschalter hat einen zugaenglichen Namen.

CSS-Spezifitaet: main{padding} in der Auflage verlor gegen main#view in der
Basis - auf grossen Bildschirmen blieb der Seitenrand bei 20px statt 44px.
Der Rand liegt jetzt in einer Variablen, die auch der negative Rand der
randlosen Standortkarte benutzt; sonst haette deren Ausgleich nach dem Fix
nicht mehr gepasst.

Drei Anzeigefehler, im Browser gegen die Testinstanz gefunden und behoben:
ein unlesbares Datum ergab NaN/N statt eines Strichs (das Profil wird laut
INSTALL.md von Hand gepflegt, ein ISO-Datum genuegt), ein fehlender
Tanksensor ergab 0 Prozent statt unbekannt, und neben dem Typenschild stand
die Ausfuehrung doppelt, wenn sie schon im Modellnamen steckt.

Alles im echten Panel geprueft: #marke ist ein BUTTON mit aria-label, der
Markenklon ist ohne die Auflage versteckt, der Seitenrand folgt der
Variablen, und die drei Anzeigen zeigen jetzt Striche statt Rechenreste.
2026-08-13 16:04:05 +02:00
Paul Nothaft 7a43be9764 Standort: Dauerabfrage, abgebrochene Gesten, Aufraeumen
Befund 8: USER_POS_TS wurde nur im Erfolgsfall gesetzt. Lehnt der Nutzer die
Standortfreigabe ab, griff die 30-Sekunden-Drossel damit nie - bei einem
GPS-Tracker als Quelle waren das dutzende Hochgenauigkeits-Abfragen pro
Stunde. Der Fehlschlag zaehlt jetzt als Versuch, und die Drossel prueft auf
den Zeitstempel statt auf ein Ergebnis.

Befund 11: Das Standort-Menue hatte als einzige der vier Zeigergesten keinen
pointercancel-Handler. Uebernimmt das System die Beruehrung, blieb der
Startpunkt gesetzt und preventDefault() blockierte das Scrollen in der
ganzen App. Zuruecksetzen jetzt gemeinsam fuer pointerup und pointercancel.

Befund 12: Ein fehlgeschlagener Adressabruf setzte trotzdem den
Cache-Schluessel - fuer diese Zelle blieb es danach die ganze Sitzung bei den
blossen Koordinaten, auch wenn das Netz laengst wieder da war.

Befund 15: disconnectedCallback raeumte nur eine von drei Karten ab.

Nicht umgesetzt, mit Begruendung im Code: die Karte nur bei echtem
Ansichtswechsel neu aufzubauen. Ich hatte das zunaechst geaendert und wieder
zurueckgenommen - render() ersetzt den Inhalt per innerHTML, eine
ueberlebende Leaflet-Instanz zeigte danach auf ein abgehaengtes Element und
bliebe leer. Der Neuaufbau haengt am 20-Sekunden-Takt des Backends; das
liesse sich nur durch einen Umbau der Render-Architektur aendern.
2026-08-13 15:56:35 +02:00
Paul Nothaft 4c62b9b529 Setup-Menue: Datenverlust verhindern, Vorbelegung korrigieren
Befund 1 (Datenverlust): Solange pyscript.audi_dashboard_entitaeten nicht
veroeffentlicht ist, liefert setupKatalog() eine leere Liste. Das Fenster ging
trotzdem auf - ohne eine Zeile, ohne Meldung - und ein Klick auf Speichern
schrieb {}. Weil overrides_schreiben() die Datei vollstaendig ersetzt, waren
damit alle Zuordnungen weg, sichtbar erst beim naechsten Neustart. Jetzt drei
Riegel: das Setup laesst sich ohne Katalog gar nicht oeffnen, Speichern bricht
bei leerer Zuordnung ab, und die Entitaet wird im Nachlade-Pfad mitgeholt -
der sie bisher als einzige der sechs ausliess.

Befund 3 (gleiche Sensoren): Der Vorschlag haengt nicht vom Index ab, also
bekamen alle vier Positionen einer Liste denselben Sensor. Der
Sicherheitscheck haette danach viermal dieselbe Tuer geprueft und Sicher
abgestellt gemeldet, obwohl drei Tueren nie geprueft wurden. Vergebene IDs
werden jetzt mitgefuehrt und uebersprungen.

Befund 4 (beliebige Sensoren): entitaetScore vergibt fuer einen reinen
Domain-Treffer bereits 3 Punkte - die Schwelle 3 war damit immer erfuellt und
belegte jedes leere Feld mit dem erstbesten Sensor der Domain, in willkuer-
licher Reihenfolge. Schwelle jetzt 5, also mindestens ein Stichworttreffer.

Geprueft mit den echten Funktionen aus der Datei: vier Tuerpositionen
erhalten vier verschiedene Sensoren, ein Bewegungsmelder wird der Zuendung
nicht mehr zugeordnet, ein Sensor mit passendem Namen dagegen schon.

Ausserdem wird die Sensor-Zuordnung jetzt im Browser-Backup mitgesichert und
beim Import wieder eingespielt.
2026-08-13 15:54:04 +02:00
Paul Nothaft 64f457dd87 Setup-Zuordnung: Zuruecksetzen wirkt, Sicherung, Absicherung
Drei Befunde aus REVIEW_main_2026-08-13.md, alle an der Testinstanz geprueft.

Zuruecksetzen (Befund 2 und 5): overrides_anwenden() uebersprang leere Werte
und setzte nur belegte. Weil setattr das Modul-Attribut dauerhaft veraendert,
blieb ein einmal gesetzter Wert danach fuer immer stehen - bei 15 von 17
Feldern hatte Zuruecksetzen keine Wirkung, und die Oberflaeche zeigte wieder
den alten Wert, als sei das Speichern fehlgeschlagen. Umgekehrt wurde eine
Liste aus leeren Eintraegen gesetzt statt uebersprungen, was den
Sicherheitscheck mit zwoelf unbekannt-Zeilen fuellte. Jetzt wird fuer jedes
bekannte Feld geschrieben: der Override, wenn belegt, sonst der eingebaute
Standardwert. Damit ist der Vorgang zugleich wiederholbar.

Sicherung (Befund 6): entitaeten.json war weder in backup.py noch in der
Wiederherstellung noch im Browser-Export enthalten - die gesamte Zuordnung
waere nach einem Rueckspielen still weg gewesen. Jetzt ueberall dabei; fehlt
der Abschnitt in aelteren Sicherungen, bleibt die aktuelle Zuordnung stehen.

Absicherung (Befund 7): overrides_lesen() fing kaputtes JSON nicht ab. Der
Aufruf steht in beim_start() vor alles_veroeffentlichen() - eine unlesbare
Zeile liess das Panel komplett leer bleiben. Geprueft: es folgt jetzt eine
verstaendliche Meldung, alle sechs Entitaeten werden trotzdem veroeffentlicht.

Dabei ein pyscript-Fallstrick gefunden und im Code vermerkt: Generator-
ausdruecke sind nicht implementiert (not implemented ast ast_generatorexp),
Mengen-, Listen- und Dict-Comprehensions dagegen schon.
2026-08-13 15:52:05 +02:00
tobias d5562c71ef Setup-Menü: Wertvorschau, Unavailable-Warnung, Duplikat-Check, Reset, Neustart-Hinweis
Fünf Erweiterungen des bestehenden Setup-Popups: Live-Wert neben jedem
Such-Kandidaten, Warnhinweis bei unavailable/unknown/fehlender Entität,
Duplikat-Check mit Bestätigung vor dem Speichern, Zurücksetzen-Button je
Feld (Standardwerte-Snapshot in entitaeten.py, vor jedem Override
genommen), und ein bestätigter "Jetzt neu starten"-Knopf nach dem
Speichern, falls sich eines der drei trigger-gebundenen Felder geändert
hat (neuer Service audi_dashboard_neustart). Im Docker-Testcontainer
Feld für Feld verifiziert.
2026-08-12 18:48:35 +02:00
tobias 3548f773c9 update.ps1: fehlende ios.css/badges-Kopie fixen, Installationspaket-Konzept
update.ps1 kopierte audi-dashboard-ios.css und www/badges/ nie, obwohl beide
von der laufenden App gebraucht werden - jedes Update seit Einfuehrung dieser
Dateien liess den deployten Stand dort veraltet zurueck. Ausserdem zwei
verwaiste *.bak-before-audit-merge-Dateien aus www/ entfernt (bereits
gitignored, nie versioniert) und installationspaket/ (generiertes,
gitignored Deployment-Bundle fuer eine frische HA-Installation) als neuen
Ignore-Eintrag ergaenzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 17:17:15 +02:00
tobias 7980f9672d Desktop-Sidebar-Markenklon (.navmarke) aus Claude Design nachziehen
audi-dashboard-app.js war bereits mit dem Design-Projekt identisch, aber
audi-dashboard-ios.css war seit einer Weile nicht mehr neu gezogen worden:
Design hatte inzwischen einen Rings-Klon oben in der Desktop-Sidebar
(.navmarke) sowie einen gefuellten Pill-Stil fuer den aktiven Tab ergaenzt.
Nach Byte-Diff-Pruefung (nur additive CSS-Aenderungen) komplett uebernommen,
in Docker deployt und bei 402px/1400px verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 16:20:19 +02:00
tobias 2c6e8e5ce4 INSTALL.md an Setup-Menü und FMM003 anpassen
Ersetzt die veralteten Installationsschritte (manuelles Eintragen von
WLAN_SENSOR/TommiG1-Entity-IDs in einstellungen.py) durch eine Anleitung
für das neue Setup-Menü in der App und die aktuellen FMM003-Feldnamen
(ZUENDUNG_SENSOR, STANDORT_TRACKER, BATTERIE_SENSOR). AGENTS.md entsprechend
nachgeführt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 16:07:47 +02:00
tobias 9794193803 Setup-Menü für Sensor-Zuordnung + Umstellung von WLAN/VAG-Integration auf FMM003
Setup-Menü (Einstellungen -> Fahrzeug einrichten -> Setup): ordnet alle von
der App genutzten Sensor-Rollen echten HA-Entitäten zu, statt sie in
einstellungen.py von Hand einzutragen - durchsuchbares Dropdown je Feld,
Vorauswahl aus vorhandenen Entitäten, Schalter für "nur passende Sensoren".
Neues Modul entitaeten.py (Katalog + JSON-Override, zur Laufzeit über
setattr() auf einstellungen angewendet, kein Neustart nötig außer für die
drei trigger-gebundenen Felder).

Zusätzlich: Fahrzeug-WLAN-Erkennung und alle Entity-IDs der nicht mehr
genutzten TommiG1/HA_VAG-EU-Data-Act-Integration entfernt. Fahrterkennung
läuft jetzt über den Zündungs-/ACC-Status des neu angebundenen Teltonika
FMM003 (ersetzt die WLAN-Verbindungserkennung); Standort und 12V-
Batteriespannung kommen ebenfalls vom FMM003. Kilometerstand, Tankfüllstand,
Reichweite, Türen/Fenster/Schlösser sowie Ölwechsel-/Inspektionsdaten haben
dadurch vorerst keine Quelle mehr und zeigen "unbekannt" - die Funktionen
selbst bleiben erhalten und lassen sich über das neue Setup-Menü jederzeit
neu zuordnen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 15:55:59 +02:00
tobias 7e979ecfab Standort: Feinschliff aus Claude Design übernehmen + Satellit/Straßenkarte-Umschalter
Übernimmt den in Claude Design überarbeiteten Stand der Standort-Funktion
(echte Audi-CI-Icons statt Platzhalter-SVGs, robustere Abstands-/Adress-
Anzeige, dynamisch gemessene Menü-Zugweg-Höhe) und ergänzt lokal den
Layer-Knopf so, dass er wie gewünscht zwischen Satellit (Esri World
Imagery, kostenlos ohne Key) und Straßenkarte umschaltet statt zwischen
Tag/Nacht-Theme.
2026-08-12 12:32:34 +02:00
tobias dc4c1ff0bf Standort-Kachel: Live-Fahrzeugposition auf der Übersicht
Neue Kachel oberhalb von "Zuletzt" mit echter Leaflet-Mini-Karte,
öffnet per Klick eine Vollbild-Standortansicht (Kartendarstellung
wählen, auf Fahrzeug/User zentrieren, beide zeigen) mit einem
ausziehbaren myAudi-Stil-Menü: Distanz zum Gerät, Adresse (Reverse-
Geocoding via Nominatim), fährt/steht/Letzter-Parkplatz-Status,
Tankfüllstand/Reichweite, Route- und Teilen-Aktionen.

Backend: STANDORT_TRACKER-Einstellung (device_tracker-Entity) plus
_standort()-Veröffentlichung, bewusst leer gelassen bis eine echte
GPS-Quelle (FMM003/flespi) angebunden ist - Kachel zeigt bis dahin
"kein GPS-Signal". Verifiziert in audi_ha_test mit einer manuell
gesetzten Test-Position.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 11:07:49 +02:00
tobias b98d624359 Höhen-Kollaps-Bug in audi-dashboard-ios.css beheben
Die iOS/Großbildschirm-Auflage setzte :host > div{height:100%}
bedingungslos, was die App auch im mobilen Layout brach, da HA die
reale Höhe durch panel_custom nicht zuverlässig durchreicht. Jetzt
bleibt die viewport-verankerte 100dvh-Höhe (mit 880px-Deckel) bei
allen Breiten erhalten; der Deckel entfällt nur noch innerhalb der
@container (min-width:860px)-Desktop-Auflage. Fix lokal in Docker und
im Claude-Design-Board (DataMetric360 Board.dc.html) verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 22:46:54 +02:00
tobias b10ce7c0a5 iOS/Grossbildschirm-Auflage im HA-Panel scharf schalten
audi-dashboard-app.js laedt jetzt zusaetzlich audi-dashboard-ios.css in
den Shadow-Root (zweiter <link>, rein additiv neben audi-dashboard.css).
Im Docker-Testcontainer bei 375px (Tab-Leiste unten) und 1280px (Grid mit
264px-Seitennavigation) verifiziert.

Zwei Fixes an audi-dashboard-ios.css waren dafuer noetig:
- :host-Selektoren werden von diesem Browser innerhalb von @container
  verworfen (kein Fehler, die Regel fehlt einfach im CSSOM) - die alte
  412px-Zentrierung aus audi-dashboard.css wird deshalb unbedingt statt
  nur ab 860px aufgehoben.
- audi-dashboard-version.json hochgezaehlt, sonst liefert der Browser die
  alte Datei aus dem HTTP-Cache trotz neuem Serverstand.

design/README.md dokumentiert beide Fixes fuer kuenftige Aenderungen an
dieser Datei.
2026-08-11 15:12:51 +02:00
tobias 838ea7f362 DataMetric360 Board aus Claude Design importieren: iOS/Großbildschirm-Optikauflage
Neuer Vergleichsentwurf (Smartphone + Großbildschirm nebeneinander) direkt per
Claude-Design-MCP importiert. Enthaelt die responsive Grossbildschirm-Umsetzung
(Tab-Leiste wird zur Seitennavigation ab 860px) als reine CSS-Auflage.

audi-dashboard-app.js aus dem Export weicht 641 Zeilen vom produktiven Stand ab
(fehlende Vier-Kacheln-Kurzwahl, Balkenfarbe, Resttank-Liter) - deshalb NICHT
uebernommen, nur die CSS-Auflage (audi-dashboard-ios.css) nach homeassistant/www/
kopiert, aber noch nicht in die Panel-Ladelogik eingebunden. Entscheidung zur
Aktivierung und zur Aufloesung der JS-Abweichung steht noch aus.
2026-08-11 14:55:00 +02:00
Paul Nothaft 4395ff6ac6 Native iOS-Huelle in Betrieb, drei Darstellungsfehler behoben
Xcode ist vorhanden, die Huelle liess sich also wirklich bauen statt nur
vorzubereiten: Capacitor 8 fuer iOS und Android, Build fuer den Simulator
erfolgreich, App laeuft und zeigt echte Daten vom Server.

CapacitorHttp eingeschaltet. Das ist keine Feinheit: die native Huelle
liefert die Oberflaeche unter eigenem Ursprung aus, jede Anfrage an Home
Assistant ist damit ursprungsuebergreifend, und die WebView lehnt sie ohne
CORS-Freigabe ab. Nativ gestellte Anfragen kennen keine CORS-Pruefung -
die App braucht dadurch keine CORS-Einstellung am Server.

Drei Fehler, die erst die Bildschirmfotos zeigten:

1. Der Fahrzeug-Block auf der Uebersicht war unsichtbar. Ursache war der
   Flexbox-Fallstrick: "overflow: hidden" setzt die automatische Mindesthoehe
   auf 0, und sobald die Seite laenger ist als der Bildschirm, quetscht
   flex-shrink den Block auf Hoehe 0. Modellname, Typenschild und Kennzeichen
   waren damit schlicht weg.
2. Neben dem Typenschild stand der Modellname noch einmal komplett, obwohl
   das Schild ihn bereits zeigt. Das alte Panel loest das laengst richtig -
   nur der Zusatz gehoert daneben. Nachgezogen, samt Entdopplung, wenn die
   Ausfuehrung schon im Namen steckt.
3. In der Fotogalerie liefen die Dateinamen ueber den Rand der Miniaturen.

Dazu: Datumszeile in Listen bricht um statt abzuschneiden, Statistik nutzt
auf der Flaeche mehrere Spalten.

Im Backend war das Kilometerstand-Screening kaputt: es rief urlopen direkt
auf, was Home Assistant seit 2026.8 als blockierenden Aufruf abbricht. Jede
Fahrt blieb dadurch ohne Strecke - sichtbar nur als Warnung im Protokoll.
Laeuft jetzt ueber task.executor und rechnet an der Testinstanz wieder echte
Strecken aus dem Verlauf.

Die CORS-Freigabe fuer die Web-Fassung ist in der Testkonfiguration
hinterlegt. Sie greift in Home Assistant 2026.8 allerdings nicht - deshalb
wird die App aus Home Assistant selbst ausgeliefert (gleicher Ursprung, kein
CORS), was ohnehin der geplante Weg ist.

Die erzeugten Ordner ios/ und android/ bleiben ungetrackt; sie entstehen
jederzeit neu aus dem Webbuendel.
2026-08-11 12:44:11 +02:00
Paul Nothaft f8b877d555 Phase 10-13: PWA fertig, blockierte Phasen vorbereitet
PWA laeuft: Manifest, Symbole in allen noetigen Groessen und die
iOS-Angaben, die Apple statt des Manifests auswertet. Das Startsymbol ist
bewusst neutral - die Vier Ringe auf einem Homescreen waeren nach aussen
sichtbar und fielen nicht mehr unter die private Nutzung.

Vorbereitet, aber nicht ausgefuehrt: Capacitor-Konfiguration, ein
Ablage-Adapter fuer Schluesselbund und Keystore (greift defensiv auf die
Laufzeit zu, damit die App ohne das Plugin unveraendert weiterlaeuft), die
Pfad-Freigabeliste fuer den Reverse Proxy und das Geruest der
FMM003-Zuordnungstabelle.

Die QR-Seite fuer die Einrichtung war zunaechst ein Fehlgriff: Ich hatte den
QR-Erzeuger selbst geschrieben. Der Vergleich gegen eine erprobte
Implementierung zeigte 1239 abweichende Module von 3249 - der Code waere
unlesbar gewesen. Jetzt liegt eine bewaehrte Bibliothek (MIT, 57 KB) neben
der Seite im eigenen Home Assistant. Das erfuellt die eigentliche
Anforderung genauso: kein Netzzugriff, der Token verlaesst das eigene Netz
nicht. Geprueft ueber einen Umlauf - 233 Zeichen hinein, identisch wieder
heraus.
2026-08-11 11:27:20 +02:00
Paul Nothaft 8e268f044d Phase 2: Doku an Codestand angleichen, profil_lesen haerten
Doku-Drift behoben: die Statistik-Seite rechnet laengst echt (Behauptung
stand an drei Stellen), INSTALL.md nannte in Schritt 4 vier Variablennamen,
die es nie gab, README erwaehnte die entfernte 97-Prozent-Volltankungsregel
und liess fuenf pyscript-Dateien in der Uebersicht aus. Obsoleter
TODO-Kommentar in belegverarbeitung.py entfernt.

profil_lesen() gibt bei fehlender oder beschaedigter Profildatei None
zurueck statt zu werfen; alle sieben Aufrufstellen fangen den Fall ab.
An der Testinstanz geprueft: Datei entfernt, es folgt eine verstaendliche
Fehlermeldung mit Verweis auf INSTALL.md statt eines Tracebacks pro
Trigger-Durchlauf, Home Assistant laeuft normal weiter.
2026-08-11 10:48:33 +02:00
tobias e1d570992e Initialer Import: HA-Panel, Design-System, Companion-App
Drei zusammengehörige Teile in einem Repository:

- homeassistant/  Das fertige, im Einsatz befindliche Home-Assistant-Panel
  (panel_custom Custom Element + pyscript-Backend). Echte Fahrzeug- und
  Personendaten (fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl,
  Tankbelege) bleiben per .gitignore außen vor; die anonymisierte Vorlage
  fahrzeugprofil.example.json ist mit dabei.

- design-system/  Eigenständige React-Komponentenbibliothek (@audi-dash/ui),
  die die visuelle Sprache des Panels nachbildet - ohne Audi-Markenzeichen
  und ohne die lizenzierte Hausschrift. Dient als Grundlage für Claude
  Design. War bis hierher ein eigenes Repository und ist in dieses
  eingeschmolzen worden.

- companion-app/  Datenschicht der neuen App DataMetric360 (iOS/Android via
  Capacitor, zusätzlich als Iframe im HA-Dashboard). Noch ohne Oberfläche:
  REST- und WebSocket-Zugriff auf Home Assistant plus Warteschlange für
  Änderungen ohne Netz. Ersetzt das eingespritzte hass-Objekt, das nur
  innerhalb des HA-Frontends existiert.

Dazu die Projektdokumentation: SPECIFICATION.md (Ist-Stand des Panels),
COMPANION_APP_ARCHITECTURE.md (Architekturentscheidungen der neuen App),
AUDIT_2026-08-10.md, DESIGN_BRIEF_DATAMETRIC360.md und der ursprüngliche
Bauauftrag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:20:05 +02:00