# Installation — Schritt für Schritt Betrifft den kompletten aktuellen Baustand: das pyscript-Backend (Fahrterkennung, Fahrtabschluss, Reifenzähler, Belegverarbeitung) **und** das Frontend (`panel_custom`, Sidebar-Eintrag „Mein Audi"). **Getestet, nicht nur geprüft.** Beides lief in einer Wegwerf-Testinstanz (Home Assistant in Docker) wirklich: das Backend über echte Service-Aufrufe (Reifen wechseln hat die Profildatei tatsächlich umgeschrieben, eine manuell angelegte Fahrt wurde tatsächlich an `fahrten.jsonl` angehängt), das Frontend, indem das Custom Element mit genau diesen echten Daten gefüttert wurde und daraus korrekt die Übersicht und die Fahrtenliste gerendert hat — inklusive der zuvor testweise umgeschalteten Winterbereifung, sichtbar an der Fahrbahn-Szene. Wofür die Testinstanz **nicht** reichte: der Weg über Home Assistants echte WebSocket-Verbindung, mit der der `panel_custom`-Rahmen (`ha-panel-custom`) das Element normalerweise selbst erzeugt und mit `hass` versorgt — diese Testumgebung ließ keine WebSocket-Verbindung zu, unabhängig vom eigenen Code. Dieser letzte Schritt — dass die Oberfläche beim ganz normalen Draufklicken in der Sidebar erscheint — ist deshalb der einzige Teil, der sich erst bei euch wirklich zeigt. `panel_custom` selbst ist Home Assistants eigener, seit Jahren stabiler Mechanismus, nicht eigener Code, entsprechend gering ist das Risiko dort. **Voraussetzung:** HACS ist bereits installiert (ergibt sich aus der laufenden Integration `TommiG1/HA_VAG-EU-Data-Act`). Zeitaufwand: ca. 30–40 Minuten, größtenteils Warten auf Neustarts. --- ## Schritt 1 — pyscript installieren 1. In Home Assistant: **HACS → Integrationen → Explore & Download Repositories** 2. Nach „pyscript" suchen, auswählen, **Download** 3. Home Assistant neu starten (**Einstellungen → System → Neu starten**) ## Schritt 2 — Dateien auf den Home-Assistant-Rechner kopieren Drei Ordner müssen in das `config`-Verzeichnis von Home Assistant kopiert werden. Wählt den Weg, der zu eurer Installation passt: **Vorher:** `data/fahrzeugprofil.json` enthält bei einer laufenden Installation echte Fahrzeug- und Personendaten (VIN, Kennzeichen, Versicherung, Werkstatt, Servicehistorie) und ist deshalb nicht Teil dieses Repos (siehe `.gitignore`). Für eine neue Installation zuerst `data/fahrzeugprofil.example.json` nach `data/fahrzeugprofil.json` kopieren — die Platzhalter darin lassen sich nach dem ersten Start bequem direkt in der App eintragen: **Einstellungen → Fahrzeug einrichten** deckt FIN, Kennzeichen, Erstzulassung und Ausführung ab, Versicherung/Werkstatt/Reifen haben eigene Bearbeiten-Ansichten. **Am einfachsten: Samba-Share-Add-on** 1. Falls noch nicht installiert: **Einstellungen → Add-ons → Add-on Store → „Samba share"** installieren und starten 2. Am Windows-Rechner im Explorer verbinden: `\\\config` 3. Von diesem Projektordner aus kopieren: - `pyscript\` (der ganze Ordner) → `\\\config\pyscript\` - `data\` (der ganze Ordner) → `\\\config\audi_dashboard\` (Ordner beim Kopieren von `data` in `audi_dashboard` umbenennen) - `www\` (der ganze Ordner, Frontend) → `\\\config\www\` (Inhalt zusammenführen, falls dort schon eine `www`-Ablage existiert) **Alternative: Studio Code Server Add-on** 1. **Einstellungen → Add-ons → Add-on Store → „Studio Code Server"** installieren, starten, öffnen 2. Im Dateibaum links Ordner `pyscript`, `audi_dashboard` und `www` unter `/config` anlegen, falls sie fehlen 3. Dateien einzeln per Drag & Drop aus dem Explorer in den Browser ziehen, oder Rechtsklick → „Upload" **Alternative: SSH & Terminal Add-on**, falls bereits eingerichtet — dann reicht `scp`/`rsync` vom gewohnten Terminal aus. ## Schritt 3 — configuration.yaml ergänzen `configuration_snippet.yaml` aus diesem Ordner öffnen. Die zwei Blöcke (`pyscript:` und `panel_custom:`) in die bestehende `configuration.yaml` übernehmen — **nicht** die Datei komplett ersetzen. Falls dort schon ein `pyscript:`-Block existiert, nur die Zeile `allow_all_imports: true` darin ergänzen statt einen zweiten Block anzulegen. Der `panel_custom:`-Block kann schon jetzt mit rein; er wird erst mit dem Frontend-Baustein wirksam und stört bis dahin nicht. ## Schritt 4 — die Entity-IDs eintragen Das ist die einzige Stelle, die inhaltlich angepasst werden muss — Datei `pyscript/modules/einstellungen.py`. **Zwingend fürs Backend** (ohne diese drei läuft die Kernlogik nicht): 1. In Home Assistant: **Entwicklerwerkzeuge → Zustände** 2. Dort suchen und die genauen Entity-IDs notieren für: - den Kilometerstand-Sensor (aus `TommiG1/HA_VAG-EU-Data-Act`) → `KM_SENSOR` - den Tankfüllstand-Sensor (dieselbe Integration) → `TANK_SENSOR` - den WLAN-Verbindungssensor des iPhones → `WLAN_SENSOR` — dafür vorher in der iOS-Companion-App unter **Einstellungen → Companion App → Sensoren** den Sensor für das verbundene WLAN aktivieren, falls er dort noch grau ist **Optional fürs Frontend** (nur für die Übersicht/Zustand-Seite, ohne sie zeigt die Oberfläche „unbekannt" statt eines Werts — kein Absturz): 3. Ebenfalls in Entwicklerwerkzeuge → Zustände suchen: - Reichweite → `RANGE_SENSOR` - Türstatus → `TUER_SENSOREN` (Liste mit vier Einzelsensoren: vorne links/rechts, hinten links/rechts) - Fensterstatus → `FENSTER_SENSOREN` (ebenfalls vier Einzelsensoren) - Verriegelung → `TUERSCHLOSS_SENSOREN` (vier Einzelsensoren; die Integration liefert kein `lock.`-Entity) - Heckklappe und Motorhaube → `HECKKLAPPE_SENSOR`, `HECKKLAPPENSCHLOSS_SENSOR`, `HAUBE_SENSOR`, `HAUBENSCHLOSS_SENSOR` - Service-Fälligkeit → `NAECHSTER_OELWECHSEL_SENSOR`, `OELWECHSEL_STRECKE_SENSOR`, `NAECHSTE_INSPEKTION_SENSOR`, `INSPEKTION_STRECKE_SENSOR` - Batteriespannung, falls überhaupt vorhanden → `BATTERIE_SENSOR` (bei der aktuellen Integration nicht vorhanden, bleibt leer) 4. Datei `pyscript/modules/einstellungen.py` öffnen (Samba: direkt im Explorer, Studio Code Server: im Editor) und alle gefundenen Werte eintragen. Was ihr nicht findet, einfach auf dem Platzhalter stehen lassen — siehe Kommentar in der Datei dazu. ## Schritt 5 — Long-Lived Access Token erzeugen Wird für das Kilometerstand-Screening gebraucht (§7.2) — pyscript hat keinen eingebauten Weg, auf die Recorder-Historie zuzugreifen, deshalb läuft das über die normale Home-Assistant-Web-API. 1. Unten links auf den eigenen Profil-Avatar klicken 2. Ganz nach unten scrollen zu **„Long-lived access tokens"** 3. **„Token erstellen"**, einen Namen vergeben (z. B. `audi_dashboard`) 4. Den angezeigten Token-Wert **sofort kopieren** — er wird danach nicht noch einmal angezeigt 5. Eine neue Datei `audi_dashboard/ha_token.txt` anlegen (im selben Ordner, in den `data/` kopiert wurde) und **nur den Token-Wert** hineinschreiben, keine Anführungszeichen, keine zweite Zeile ⚠️ Diese Datei enthält ein Geheimnis. Nicht weitergeben, nicht in ein Backup hochladen, das öffentlich einsehbar ist. ## Schritt 6 — neu starten **Einstellungen → System → Neu starten.** ## Schritt 7 — prüfen, ob alles geladen hat 1. **Einstellungen → System → Protokolle**, nach „pyscript" oder „audi_dashboard" filtern — es sollten keine roten Fehlermeldungen auftauchen, insbesondere keine `ImportError` oder `ModuleNotFoundError` 2. **Entwicklerwerkzeuge → Zustände**, nach `pyscript.reifen` suchen — dort sollten `pyscript.reifen_sommer_km`, `pyscript.reifen_winter_km` (Wert `0`, solange noch kein Kilometerstand-Update seit der Installation einging) und `pyscript.reifen_aktiver_satz` auftauchen 3. **Entwicklerwerkzeuge → Aktionen**, nach „audi_dashboard" suchen — die Services `pyscript.audi_dashboard_screening_jetzt`, `pyscript.audi_dashboard_reifen_wechseln`, `pyscript.audi_dashboard_fahrt_manuell_anlegen`, `pyscript.audi_dashboard_beleg_hochladen` und `pyscript.audi_dashboard_tankvorgang_manuell` sollten dort erscheinen Wenn das alles stimmt, läuft das Backend. Die Fahrterkennung selbst lässt sich am einfachsten testen, indem das WLAN am Handy kurz ausgeschaltet und wieder eingeschaltet wird (Pausenregel greift) bzw. länger als die eingestellte Pausenzeit ausgeschaltet bleibt (Fahrt wird angelegt) — danach in `audi_dashboard/fahrten.jsonl` nachsehen, ob eine Zeile entstanden ist. ## Schritt 8 — was jetzt noch fehlt, bevor es vollständig nutzbar ist - **Reifen-Kilometerstände:** laufen automatisch mit (`reifen.saetze. sommer/winter.km`, siehe reifenzaehler.py) — beide starten bei der Installation bei `0`. Hat einer der Sätze schon Laufleistung von vor der Installation, den Wert einmalig direkt in `audi_dashboard/ fahrzeugprofil.json` nachtragen - **Kfz-Steuer-Fälligkeit:** `steuer.faellig` im selben Profil eintragen - **shell_beleg_parser.py** liegt bereits unter `data/shell_beleg_parser.py` und wird mit dem `data`-Ordner aus Schritt 2 automatisch nach `audi_dashboard/shell_beleg_parser.py` mitkopiert. Er ruft `python3` als eigenen Prozess auf (nicht die pyscript-Sandbox) und braucht dafür einmalig `pypdf`: im **Terminal & SSH**-Add-on (oder per `docker exec`) `pip install pypdf` ausführen. Ohne das schlägt jeder Beleg-Upload mit `ModuleNotFoundError: No module named 'pypdf'` im Log fehl. - **Tailscale „VPN On Demand"** in der Tailscale-App selbst einrichten (Regel „Only On", gebunden an `Audi_MMI_2804_5GHz`) — unabhängig von Home Assistant, kann jederzeit parallel erledigt werden ## Schritt 9 — Frontend prüfen Der `panel_custom`-Eintrag aus Schritt 3 zeigt auf `/config/www/audi-dashboard-panel.js`, die in Schritt 2 mitkopiert wurde. 1. In der Sidebar sollte nach dem Neustart aus Schritt 6 ein neuer Eintrag „Mein Audi" erscheinen (Auto-Symbol). Anklicken. 2. Die Übersicht sollte erscheinen: Fahrzeugbild (als Platzhalter, siehe unten), Typenschild, Kilometerstand, Reichweite. Falls Kilometerstand oder Reichweite „unbekannt"/leer bleiben, obwohl Schritt 7 erfolgreich war: die optionalen Entity-IDs aus Schritt 4 nachtragen. 3. Falls die Seite leer bleibt oder gar nicht in der Sidebar erscheint: im Browser die Entwicklerkonsole öffnen (F12) und nach Fehlern mit „audi-dashboard" oder „pyscript" suchen — siehe Troubleshooting. **Was direkt sichtbar fehlt, ganz bewusst (siehe README):** - **Bilder** — der Ordner `bilder/` mit den elf Fotos aus §7a ist nicht Teil dieses Baustands. Die Bildflächen bleiben leer bzw. zeigen ein gebrochenes Bild-Symbol, das Layout selbst springt nicht (die Maße sind reserviert). Bilder können jederzeit einzeln unter `www/bilder/` nachgereicht werden, feste Dateinamen siehe §7a im Lastenheft. - **Karten** (Leaflet) laden weiterhin von einem CDN, genau wie im Prototyp. Das Gerät braucht dafür zusätzlich zur Tailscale-Verbindung normalen Internetzugang — sonst bleibt die Karte auf der Fahrt- und Tankvorgang-Detailseite leer. - **Statistik-Seite** wertet die eigenen Fahrten und Tankvorgänge echt aus (Zeiträume, Verbrauch, Tag/Nacht, privat/Arbeitsweg). Sie bleibt nur so lange leer, wie noch keine Fahrten und Tankungen erfasst sind. ## Schritt 10 — künftige Updates einspielen, ohne die App neu zu bauen Ab hier ändert sich der Ablauf: kein Neustart mehr nötig, weder für Backend- noch für Frontend-Änderungen. **Backend (pyscript):** pyscript überwacht `pyscript/` selbst auf Änderungen und lädt geänderte Dateien automatisch neu — an der Testinstanz gemessen: eine bearbeitete Datei war innerhalb von Millisekunden aktiv, neue Services erschienen sofort in Entwicklerwerkzeuge → Aktionen, ganz ohne Neustart. Es reicht, die neue Datei per Samba/Studio-Code-Server/`scp` in `pyscript/` zu überschreiben. **Frontend:** hier gibt es keinen eingebauten Auto-Reload, dafür aber ein echtes Cache-Problem — Home Assistant liefert Dateien aus `/local/` mit `Cache-Control: max-age=2678400` aus, 31 Tage (an der Testinstanz gemessen). Ohne Gegenmaßnahme würde eine Aktualisierung im Browser tagelang nicht ankommen. Deshalb ist das Frontend zweigeteilt: - `audi-dashboard-panel.js` ist ein kleiner, stabil bleibender Lade-Stub, auf den `panel_custom` in der `configuration.yaml` zeigt - er lädt bei jedem Seitenaufruf zuerst `audi-dashboard-version.json` ungecacht, hängt deren Versionsnummer als Parameter an und lädt darüber erst den eigentlichen Code aus `audi-dashboard-app.js` nach — jede neue Versionsnummer ist für den Browser eine neue URL und wird nie aus einem alten Cache bedient **Am einfachsten mit dem beiliegenden Skript:** ```powershell .\update.ps1 -Ziel "\\\config" ``` Kopiert `pyscript/` und die Frontend-Dateien, schreibt `audi-dashboard-version.json` automatisch mit einem neuen Zeitstempel — **lässt `data/` unangetastet**, damit ein bereits laufendes Fahrzeugprofil oder Fahrten-Archiv nicht überschrieben wird. Voraussetzung: der Samba-Share aus Schritt 2 ist als Netzlaufwerk verbunden. Danach: pyscript-Änderungen sind sofort aktiv, für das Frontend reicht ein ganz normales Neuladen der Seite (F5) — kein Hard-Refresh, kein HA-Neustart. ⚠️ Server-seitig geprüft: eine neue `audi-dashboard-version.json` und ein geänderter `audi-dashboard-app.js`-Inhalt standen an der Testinstanz sofort zur Verfügung (per `curl` nachgemessen). Ob ein echter Browser das beim nächsten Öffnen tatsächlich nachlädt, ließ sich in der Sandbox-Testumgebung nicht abschließend zeigen — deren eigene Netzwerkschicht verhielt sich bereits beim WebSocket-Test nicht wie ein normaler Browser (siehe README). Das Verfahren selbst (`cache:"no-store"` plus versionierter Import-Parameter) ist eine Standardtechnik gegen genau dieses Problem, keine Vermutung — der erste echte Test dafür ist trotzdem der erste echte Update-Durchlauf bei euch. --- ## Troubleshooting | Symptom | Wahrscheinliche Ursache | |---|---| | `ModuleNotFoundError: No module named 'einstellungen'` (oder `profil`, `fahrtabschluss_logik`) | Ordner falsch kopiert — `modules/`-Unterordner muss unter `pyscript/modules/` liegen, nicht direkt unter `pyscript/` | | pyscript lädt gar nicht, keine Fehler, keine Services | `allow_all_imports: true` fehlt oder Einrückung in der `configuration.yaml` ist falsch (YAML ist einrückungsempfindlich) | | Fahrt wird nie angelegt | `WLAN_SENSOR` in `einstellungen.py` zeigt auf die falsche Entity, oder `fahrzeug.wlan_name` im Profil passt nicht exakt zum Sensorwert (Groß-/Kleinschreibung zählt) | | Screening findet nie einen Kilometerstand | `ha_token.txt` fehlt, ist leer, oder der Token wurde widerrufen — in den Protokollen nach `HTTPError` oder `401` suchen | | Reifenzähler zeigt dauerhaft „unbekannt" | `KM_SENSOR` in `einstellungen.py` liefert keinen Wert, oder es kam seit der Installation noch keine Änderung des Kilometerstands an (reifenzaehler.py reagiert nur auf Sensor-Änderungen) | | „Mein Audi" fehlt in der Sidebar | `panel_custom:`-Block fehlt oder ist falsch eingerückt in `configuration.yaml`; nach Änderungen daran hilft nur ein vollständiger Neustart, kein „YAML neu laden" | | Sidebar-Eintrag da, Seite bleibt leer | Browser-Konsole (F12) prüfen: 404 bei `/local/audi-dashboard-panel.js` → Datei liegt nicht unter `/config/www/`; JS-Fehler beim Laden → Datei unvollständig kopiert, Dateigröße mit dem Original vergleichen | | Übersicht erscheint, aber alle Werte „unbekannt" | Normal, solange `KM_SENSOR`/`TANK_SENSOR`/... in `einstellungen.py` noch Platzhalter sind (Schritt 4) — kein Frontend-Fehler | | Karten bleiben leer auf Fahrt-/Tankdetailseite | Gerät hat keinen Internetzugang zusätzlich zu Tailscale — Leaflet lädt von einem CDN (siehe Schritt 9) |