# 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 (wird für pyscript selbst
gebraucht, siehe Schritt 1). Für die Fahrterkennung und die Fahrzeugdaten
wird zusätzlich ein Teltonika FMM003 (bzw. dessen Integration in Home
Assistant, z. B. über flespi) vorausgesetzt — Details siehe
`COMPANION_APP_ARCHITECTURE.md` im Projektstamm. Ohne FMM003 läuft die App
trotzdem: alle davon abhängigen Werte zeigen einfach „unbekannt" statt
eines Werts.

Zeitaufwand: ca. 30–40 Minuten, größtenteils Warten auf Neustarts.

---


## Der schnelle Weg: install.sh

Für eine neue Instanz gibt es ein Skript, das die Schritte 1 bis 3 und 5
zusammen erledigt. Am einfachsten direkt auf der HA-Instanz im Add-on
**Terminal & SSH**:

```bash
bash <(curl -fsSL https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/homeassistant/install.sh)
```

Liegt das Repository privat (Standard), braucht der Aufruf ein Zugangstoken:

```bash
curl -fsSL -H "Authorization: token <DEIN-GITEA-TOKEN>" \
  https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/homeassistant/install.sh -o install.sh
bash install.sh --repo https://<nutzer>:<token>@gitea.nothaft.cloud/paul/audi-app.git
```

Alternativ von einem Rechner aus gegen ein eingebundenes config-Verzeichnis:

```bash
./install.sh --ziel /Volumes/config --von ~/Development/audi-app
```

Das Skript installiert pyscript, spielt Backend und Oberfläche ein, legt das
Fahrzeugprofil aus der Vorlage an (**vorhandene Daten bleiben unangetastet**),
trägt den Abschnitt in die `configuration.yaml` ein — mit Sicherungskopie und
so, dass ein zweiter Lauf ihn ersetzt statt anhängt — und verdrahtet die
Selbstaktualisierung, damit „Update suchen" in der App funktioniert.
`--hilfe` zeigt alle Optionen.

Danach bleiben nur noch drei Dinge, alle in der Weboberfläche: neu starten,
Sensoren zuordnen (Schritt 4 unten), Fahrzeugdaten eintragen.

Wer lieber jeden Schritt selbst nachvollzieht, folgt der ausführlichen
Anleitung ab hier.


## 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: `\\<HA-IP-Adresse>\config`
3. Von diesem Projektordner aus kopieren:
   - `pyscript\` (der ganze Ordner) → `\\<HA-IP>\config\pyscript\`
   - `data\` (der ganze Ordner) → `\\<HA-IP>\config\audi_dashboard\`
     (Ordner beim Kopieren von `data` in `audi_dashboard` umbenennen)
   - `www\` (der ganze Ordner, Frontend) → `\\<HA-IP>\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 Sensoren zuordnen

Anders als früher wird dafür **nicht** mehr `pyscript/modules/
einstellungen.py` von Hand bearbeitet — das übernimmt ein grafisches
Setup-Menü direkt in der App: **Mein Audi → Einstellungen → Fahrzeug
einrichten → Einrichten → „Setup — Sensoren zuordnen"** (letzter Punkt,
erscheint erst nach Klick auf „Einrichten").

> **Reihenfolge beachten:** Dieser Schritt braucht eine bereits laufende App.
> Arbeite deshalb erst die Schritte 5 bis 9 ab (Token, Neustart, Prüfung,
> Restarbeiten, Frontend) und komm dann hierher zurück. Schritt 7 verweist
> seinerseits auf die hier vorgenommene Zuordnung — das ist kein Widerspruch,
> sondern schlicht die Reihenfolge: erst starten, dann zuordnen, dann prüfen.

Das Setup-Menü listet jede Sensor-Rolle, die die App kennt (Zündung/
Fahrterkennung, Kilometerstand, Tankfüllstand, Standort, Batteriespannung,
Türen/Fenster/Schlösser, Ölwechsel/Inspektion, …), schlägt je Rolle
passende vorhandene HA-Entitäten vor (Schalter „Nur passende Sensoren
anzeigen" grenzt auf die erwartete Domäne/Einheit ein) und schreibt die
Auswahl direkt in eine Override-Datei — `einstellungen.py` selbst bleibt
unverändert.

Die Override-Datei ist `/config/audi_dashboard/entitaeten.json`. Sie wird von
der automatischen Sicherung und vom Backup-Export mit erfasst; ein
Wiederherstellen spielt die Zuordnung also mit zurück.

**Hinweis zu den Vorgabewerten:** Drei Rollen sind in `einstellungen.py` mit
den Test-Entitäten der Entwicklungsinstanz vorbelegt (Zündung, Batterie-
spannung, Standort — jeweils `*_testzone_fmm003`). Auf einer frischen
Installation zeigen sie ins Leere; das Setup-Menü meldet dann „Entität nicht
gefunden". Einfach die eigenen Entitäten zuordnen, damit ist es erledigt.

**Zwingend, damit die Fahrterkennung läuft:**
- **Zündung/ACC-Status** (`ZUENDUNG_SENSOR`) — ein `binary_sensor`, `on`
  = Fahrt läuft. Kommt vom Teltonika FMM003 (z. B.
  `binary_sensor.<gerätename>_engine_ignition_or_acc_status`).

**Alles Weitere ist optional** — ohne zugeordneten Sensor zeigt die
Oberfläche „unbekannt"/em-dash statt eines Werts, kein Absturz:
- Kilometerstand (`KM_SENSOR`), Tankfüllstand (`TANK_SENSOR`), Reichweite
  (`RANGE_SENSOR`) — bis zu einer neuen Datenquelle unbelegt, siehe
  `AGENTS.md` (die frühere `TommiG1/HA_VAG-EU-Data-Act`-Integration liefert
  diese nicht mehr)
- Standort (`STANDORT_TRACKER`, ein `device_tracker`) und Batteriespannung
  (`BATTERIE_SENSOR`) — vom FMM003, z. B. `device_tracker.<gerätename>`
  bzw. `sensor.<gerätename>_external_power_voltage` (**nicht**
  `..._battery_voltage` — das ist die interne Pufferzelle des Trackers,
  nicht die Fahrzeugbatterie)
- Türen/Fenster/Schlösser, Ölwechsel/Inspektion — je nach Fahrzeug/
  Integration vorhanden oder nicht

Wer lieber direkt in Entwicklerwerkzeuge → Zustände nach Entity-IDs sucht,
kann das weiterhin tun — die Suche im Setup-Menü filtert exakt auf
denselben Datenbestand (`HASS.states`), nur mit Vorschlägen und Filter.

**Einschränkung bei drei Feldern** (Zündung, Kilometerstand,
Tankfüllstand): sie sind intern fest mit einem Auslöser verdrahtet
(`@state_trigger`), der einmalig beim Laden des Backends gesetzt wird.
Eine Änderung im Setup-Menü wird gespeichert, wirkt für die Fahrterkennung
selbst aber erst nach einem Neustart von Home Assistant — das Setup-Menü
zeigt dafür einen Hinweis an.

## 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 der Zündungs-Sensor (`ZUENDUNG_SENSOR`,
nach dem Zuordnen in Schritt 4) kurz auf `on` und wieder auf `off` gesetzt
wird (Pausenregel greift, kurzer Ausflug wird als eine Fahrt gewertet) bzw.
länger als die eingestellte Pausenzeit auf `off` bleibt (Fahrt wird
angelegt) — am Fahrzeug reicht dafür kurz die Zündung, ohne Fahrzeug
funktioniert es auch manuell über **Entwicklerwerkzeuge → Zustände** (den
Sensor suchen, Zustand testweise auf `on`/`off` setzen). 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 Sensoren aus Schritt 4 im Setup-Menü zuordnen.
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 "\\<HA-IP-Adresse>\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 | `ZUENDUNG_SENSOR` ist im Setup-Menü nicht oder falsch zugeordnet, oder er ist nach einer Änderung im Setup-Menü noch nicht durch einen HA-Neustart aktiv geworden (siehe Schritt 4) |
| 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` ist im Setup-Menü nicht zugeordnet, 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`/... im Setup-Menü noch nicht zugeordnet 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) |
