d8b12da36d
Das Backend liegt jetzt als custom_components/audi_dashboard/ vor - eine normale Home-Assistant-Integration mit Config-Flow, einer sensor-Plattform und 18 Diensten. Damit ist die App über HACS installierbar; bis das Repo auf GitHub gespiegelt ist (HACS spricht ausschließlich mit GitHub), installiert homeassistant/installationspaket/install.ps1 denselben Ordner ohne HACS. Fünf Installationsschritte entfallen ersatzlos: der pyscript:-Block, der panel_custom:-Block, das Kopieren der Oberfläche nach www/, das langlebige Zugriffstoken (der Verlauf wird direkt über die recorder-API gelesen) und "pip install pypdf" (steht in manifest.json). Das Fahrzeugprofil legt die Integration beim ersten Start aus ihrer Vorlage an. Drei alte Schwächen sind dabei mit erledigt: - Die Nutzlast landet nicht mehr in der Recorder-Datenbank (_unrecorded_attributes - das kann nur eine echte Entität). - Eine laufende Fahrt überlebt einen Neustart (Store statt Arbeitsspeicher); fiel sie während eines Ausfalls ins Ende, schließt nach_neustart_fortsetzen() sie beim letzten aufgezeichneten Zeitpunkt. - Sensor-Zuordnungen wirken sofort - die Zustandsbeobachter werden neu gebunden, der Neustart-Hinweis und der Neustart-Dienst sind weg. Namensvertrag geändert, beide Oberflächen mitgezogen: pyscript.audi_dashboard_x -> sensor.audi_dashboard_x, pyscript.audi_dashboard_y -> audi_dashboard.y. Eine Companion-App vom alten Stand findet nach dem Umstieg nichts mehr und muss neu gebaut werden; das Panel liegt in der Integration und kann nicht driften. Der selbstgebaute Updater entfällt - HACS ist die Update-Mechanik, die Home Assistant kennt. Die Versionierung schrumpft auf eine Quelle: manifest.json. Geprüft am laufenden Testcontainer (Container byteweise identisch mit dem Repo): alle 18 Dienste, Panel, Config-Entry neu laden, Historienimport, echter Shell-Beleg in-process, Neuinstallation im Wegwerf-Container blank mit automatisch nachinstalliertem pypdf. Companion-App: tsc sauber, 112/112 Tests, beide Rauchtests gegen das laufende Backend grün. Belegparser 8/8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
220 lines
11 KiB
PowerShell
220 lines
11 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Installiert "Mein Audi" (DataMetric360) als Home-Assistant-Integration -
|
|
der Weg ohne HACS.
|
|
|
|
.BESCHREIBUNG
|
|
Kopiert genau einen Ordner:
|
|
|
|
custom_components\audi_dashboard\ -> <Ziel>\custom_components\
|
|
|
|
Mehr ist nicht nötig. Alles, was früher an dieser Stelle von Hand gemacht
|
|
werden musste, macht die Integration inzwischen selbst: sie meldet ihr Panel
|
|
an, liefert ihre Oberflächen-Dateien selbst aus, legt beim ersten Start ein
|
|
Fahrzeugprofil aus der Vorlage an und bringt pypdf über ihre manifest.json
|
|
mit, das Home Assistant beim ersten Laden nachinstalliert.
|
|
|
|
WOFÜR ES DIESES SKRIPT ÜBERHAUPT NOCH GIBT
|
|
------------------------------------------
|
|
Der eigentliche Weg ist HACS. HACS spricht aber ausschließlich mit GitHub
|
|
(github.com/api.github.com stecken fest im Code) - solange dieses Projekt
|
|
nur auf der eigenen Gitea-Instanz liegt, findet HACS es nicht. Dieses Skript
|
|
ist der Weg dorthin, der ohne GitHub auskommt. Es installiert exakt
|
|
denselben Ordner, den auch HACS installieren würde; ein späterer Wechsel auf
|
|
HACS überschreibt ihn einfach.
|
|
|
|
SICHERHEIT GEGENÜBER DER BESTEHENDEN HA-INSTALLATION
|
|
----------------------------------------------------
|
|
Die riskanteste Stelle der früheren Fassung gibt es nicht mehr: sie musste
|
|
die configuration.yaml ergänzen (pyscript:, panel_custom:), und eine kaputte
|
|
configuration.yaml ist der eine Weg, auf dem ein Installer Home Assistant am
|
|
Starten hindern kann. Diese Fassung fasst die Datei überhaupt nicht mehr an.
|
|
|
|
Was bleibt, ist nachprüfbar:
|
|
- Geschrieben wird ausschließlich in <Ziel>\custom_components\audi_dashboard.
|
|
Kein anderer Pfad wird angefasst - nicht .storage\, nicht
|
|
configuration.yaml, nicht automations.yaml, nicht www\, nicht
|
|
audi_dashboard\ (die Fahrzeugdaten).
|
|
- Entfernt wird nur der eigene Ordner, und nur, wenn darin eine
|
|
manifest.json mit "domain": "audi_dashboard" liegt. Ein fremder Ordner
|
|
unter diesem Namen führt zum Abbruch, nicht zum Löschen.
|
|
- Es startet Home Assistant nicht neu und greift nicht in den laufenden
|
|
Betrieb ein.
|
|
- -Pruefen zeigt den kompletten Ablauf, ohne irgendetwas zu schreiben.
|
|
Im Zweifel damit anfangen.
|
|
|
|
Warum der Zielordner vor dem Kopieren geleert wird (und nicht nur
|
|
überschrieben): bleibt eine Datei aus einer älteren Fassung liegen, die es
|
|
im neuen Stand nicht mehr gibt, lädt Home Assistant sie trotzdem mit. Das
|
|
ist genau der Fehler, den man hinterher am schwersten findet. HACS macht es
|
|
aus demselben Grund so.
|
|
|
|
Die Fahrzeugdaten liegen woanders (<Ziel>\audi_dashboard\) und werden von
|
|
diesem Skript nie berührt - ein Update kann sie deshalb gar nicht treffen.
|
|
|
|
.PARAMETER Ziel
|
|
config-Verzeichnis der HA-Instanz, z. B. "\\homeassistant.local\config"
|
|
(Samba-Add-on) oder ein lokal gemounteter Pfad. Ohne Angabe sucht das
|
|
Skript die üblichen Samba-Namen selbst ab.
|
|
|
|
.PARAMETER Pruefen
|
|
Nur anzeigen, was passieren würde - es wird nichts geschrieben.
|
|
|
|
.BEISPIEL
|
|
.\install.ps1
|
|
.\install.ps1 -Ziel "\\192.168.1.50\config"
|
|
.\install.ps1 -Pruefen
|
|
#>
|
|
param(
|
|
[string]$Ziel,
|
|
[switch]$Pruefen
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$hier = $PSScriptRoot
|
|
|
|
function Schritt($text) { Write-Host "`n$text" -ForegroundColor Cyan }
|
|
function Gut($text) { Write-Host " [ok] $text" -ForegroundColor Green }
|
|
function Info($text) { Write-Host " [info] $text" -ForegroundColor DarkGray }
|
|
function Warnung($text) { Write-Host " [!] $text" -ForegroundColor Yellow }
|
|
|
|
$restliste = New-Object System.Collections.ArrayList
|
|
|
|
Write-Host ""
|
|
Write-Host " Mein Audi - Installation" -ForegroundColor White
|
|
Write-Host " ========================" -ForegroundColor White
|
|
if ($Pruefen) { Warnung "Pruefmodus - es wird nichts geschrieben." }
|
|
|
|
# ------------------------------------------------------------ Quelle finden
|
|
# Zwei Lagen, damit sowohl der Aufruf aus dem Projektordner heraus als auch
|
|
# ein separat weitergegebenes Paket funktioniert.
|
|
$quellKandidaten = @(
|
|
(Join-Path $hier "custom_components\audi_dashboard"),
|
|
(Join-Path $hier "..\..\custom_components\audi_dashboard")
|
|
)
|
|
$quelle = $null
|
|
foreach ($k in $quellKandidaten) {
|
|
if (Test-Path (Join-Path $k "manifest.json")) { $quelle = (Resolve-Path $k).Path; break }
|
|
}
|
|
if (-not $quelle) {
|
|
throw "custom_components\audi_dashboard nicht gefunden - dieses Skript gehört in den Projektordner (oder das Paket daneben)."
|
|
}
|
|
$version = (Get-Content (Join-Path $quelle "manifest.json") -Raw | ConvertFrom-Json).version
|
|
Gut "Quelle: $quelle (Version $version)"
|
|
|
|
# ---------------------------------------------------------------- Ziel finden
|
|
if (-not $Ziel) {
|
|
Schritt "Suche Home Assistant ..."
|
|
# Die Reihenfolge ist Absicht: der kurze Name antwortet in den meisten
|
|
# Heimnetzen schneller als der .local-Name über mDNS.
|
|
$kandidaten = @(
|
|
"\\homeassistant\config",
|
|
"\\homeassistant.local\config",
|
|
"\\hassio\config"
|
|
)
|
|
foreach ($k in $kandidaten) {
|
|
Info "probiere $k"
|
|
if (Test-Path $k) { $Ziel = $k; break }
|
|
}
|
|
if (-not $Ziel) {
|
|
Write-Host ""
|
|
Warnung "Keine HA-Instanz automatisch gefunden."
|
|
Write-Host " Bitte den config-Pfad angeben, z. B. \\192.168.1.50\config"
|
|
Write-Host " (Samba-Share-Add-on in HA muss laufen und verbunden sein.)"
|
|
Write-Host ""
|
|
$Ziel = Read-Host " config-Pfad"
|
|
if (-not $Ziel) { throw "Kein Ziel angegeben - Abbruch." }
|
|
}
|
|
}
|
|
|
|
if (-not (Test-Path $Ziel)) {
|
|
throw "Ziel nicht erreichbar: $Ziel - Samba-Share verbunden? Pfad korrekt?"
|
|
}
|
|
|
|
# Ein config-Verzeichnis ohne configuration.yaml ist mit hoher Wahrscheinlichkeit
|
|
# der falsche Ordner - lieber hier abbrechen als Dateien irgendwohin streuen.
|
|
if (-not (Test-Path (Join-Path $Ziel "configuration.yaml"))) {
|
|
throw "In $Ziel liegt keine configuration.yaml - ist das wirklich das config-Verzeichnis von HA?"
|
|
}
|
|
Gut "Ziel: $Ziel"
|
|
|
|
# ------------------------------------------------------- Zielordner prüfen
|
|
$zielOrdner = Join-Path $Ziel "custom_components\audi_dashboard"
|
|
$vorhandeneVersion = $null
|
|
if (Test-Path $zielOrdner) {
|
|
$zielManifest = Join-Path $zielOrdner "manifest.json"
|
|
if (-not (Test-Path $zielManifest)) {
|
|
throw "In $zielOrdner liegt keine manifest.json. Das ist nicht unser Ordner - Abbruch, es wird nichts angefasst."
|
|
}
|
|
$vorhandenesManifest = Get-Content $zielManifest -Raw | ConvertFrom-Json
|
|
if ($vorhandenesManifest.domain -ne "audi_dashboard") {
|
|
throw "$zielOrdner gehört zur Integration '$($vorhandenesManifest.domain)', nicht zu 'audi_dashboard' - Abbruch."
|
|
}
|
|
$vorhandeneVersion = $vorhandenesManifest.version
|
|
Info "bereits installiert: Version $vorhandeneVersion"
|
|
}
|
|
|
|
# ----------------------------------------------------------------- Kopieren
|
|
Schritt "Integration kopieren"
|
|
if ($Pruefen) {
|
|
if ($vorhandeneVersion) { Info "würde ersetzen: $zielOrdner (Version $vorhandeneVersion -> $version)" }
|
|
else { Info "würde anlegen: $zielOrdner (Version $version)" }
|
|
Info "würde sonst nichts anfassen - keine configuration.yaml, keine Fahrzeugdaten"
|
|
} else {
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $Ziel "custom_components") | Out-Null
|
|
if (Test-Path $zielOrdner) {
|
|
# Die Prüfung oben hat bestätigt, dass das unser Ordner ist.
|
|
Remove-Item $zielOrdner -Recurse -Force
|
|
}
|
|
Copy-Item $quelle $zielOrdner -Recurse -Force
|
|
# Übersetzte Reste einer früheren Fassung gehören nicht ins Ziel.
|
|
Get-ChildItem $zielOrdner -Recurse -Directory -Filter "__pycache__" |
|
|
ForEach-Object { Remove-Item $_.FullName -Recurse -Force }
|
|
|
|
# Rücklesen: liegt im Ziel wirklich das, was gemeint war?
|
|
$kontrolle = Join-Path $zielOrdner "manifest.json"
|
|
if (-not (Test-Path $kontrolle)) {
|
|
throw "Nach dem Kopieren fehlt $kontrolle - die Installation ist unvollständig."
|
|
}
|
|
$geschrieben = (Get-Content $kontrolle -Raw | ConvertFrom-Json).version
|
|
if ($geschrieben -ne $version) {
|
|
throw "Nach dem Kopieren steht Version '$geschrieben' statt '$version' im Ziel - die Installation ist unvollständig."
|
|
}
|
|
$anzahl = (Get-ChildItem $zielOrdner -Recurse -File).Count
|
|
Gut "custom_components\audi_dashboard (Version $version, $anzahl Dateien)"
|
|
}
|
|
|
|
# --------------------------------------------------------------- Restliste
|
|
if (-not $vorhandeneVersion) {
|
|
[void]$restliste.Add("Home Assistant neu starten: Einstellungen -> System -> Neu starten. (Beim ersten Start ladt HA die Abhaengigkeit pypdf nach - das kann eine Minute dauern.)")
|
|
[void]$restliste.Add("Integration hinzufuegen: Einstellungen -> Geraete & Dienste -> Integration hinzufuegen -> 'Audi Dashboard'. Danach steht 'Mein Audi' in der Seitenleiste.")
|
|
[void]$restliste.Add("In der App: Einstellungen -> Fahrzeug einrichten -> Setup - Sensoren zuordnen. Im Auslieferstand ist KEIN Sensor vorbelegt; zwingend fuer die Fahrterkennung ist der Zuendungs-/ACC-Sensor (binary_sensor, meist vom Teltonika FMM003). Ein Neustart ist dafuer nicht mehr noetig - Aenderungen wirken sofort.")
|
|
} else {
|
|
[void]$restliste.Add("Home Assistant neu starten: Einstellungen -> System -> Neu starten. (Oder kuerzer: Einstellungen -> Geraete & Dienste -> Audi Dashboard -> Neu laden.)")
|
|
}
|
|
|
|
# Bewusst nicht automatisch eingefügt: der recorder-Block ist eine Entscheidung
|
|
# über den Plattenplatz der Instanz (ein Jahr Fahrzeugverlauf sind grob 1-1,5 GB,
|
|
# siehe Kopf von recorder_snippet.yaml), und viele Instanzen haben bereits einen
|
|
# eigenen recorder:-Block mit anderen Einstellungen. Zusammenführen ist Handarbeit.
|
|
[void]$restliste.Add("ZEITKRITISCH - Datenaufbewahrung: den Block aus recorder_snippet.yaml in die configuration.yaml uebernehmen. Home Assistant loescht Sensor-Verlaeufe sonst nach 10 Tagen; was weg ist, laesst sich auch mit 'Daten importieren aus Home Assistant' nicht mehr nachtragen. Je frueher der Block drin ist, desto mehr Vergangenheit bleibt erhalten. VORHER Einstellungen -> System -> Speicher pruefen: ein Jahr Verlauf braucht grob 1-1,5 GB. Bei wenig freiem Platz (SD-Karte, kleine eMMC) mit purge_keep_days: 90 anfangen - Details im Kopf der Datei.")
|
|
[void]$restliste.Add("Optional, sobald die Sensoren zugeordnet sind: Einstellungen -> Einrichten -> 'Daten importieren aus Home Assistant' holt Fahrten, Tankvorgaenge und Spannungswerte aus dem bereits aufgezeichneten HA-Verlauf nach.")
|
|
|
|
Write-Host ""
|
|
if ($Pruefen) {
|
|
Write-Host " Pruefmodus beendet - es wurde nichts geschrieben." -ForegroundColor Yellow
|
|
} else {
|
|
Write-Host " Die Integration ist installiert." -ForegroundColor Green
|
|
}
|
|
Write-Host ""
|
|
Write-Host " Das fehlt noch:" -ForegroundColor White
|
|
$nr = 1
|
|
foreach ($punkt in $restliste) {
|
|
Write-Host " $nr. $punkt"
|
|
$nr++
|
|
}
|
|
Write-Host ""
|
|
Write-Host " Fuer spaetere Updates reicht derselbe Aufruf noch einmal." -ForegroundColor White
|
|
Write-Host " Die Fahrzeugdaten unter audi_dashboard\ bleiben dabei unangetastet."
|
|
Write-Host ""
|