Files
audi-app/homeassistant/INSTALL.md
T
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

20 KiB
Raw Blame History

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. 3040 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 <(curl -fsSL https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/homeassistant/install.sh)

Liegt das Repository privat (Standard), braucht der Aufruf Zugangsdaten — mit Token oder mit Nutzer und Passwort, beides funktioniert:

curl -fsSL -H "Authorization: token <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

Eine Überlegung lohnt sich dabei: Was in --repo steht, wird als Updatequelle hinterlegt und landet im Klartext in pyscript/modules/einstellungen.py. Ein Token ist dort besser aufgehoben als das Kontopasswort, weil er einzeln widerrufbar und auf Lesezugriff beschränkbar ist. Wer gar nichts ablegen will, hängt --update-repo aus an und aktualisiert weiter über dieses Skript. Die Abwägung im Einzelnen steht in ha_install.md, Abschnitt 1b.

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

./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:

.\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)