Selbst-Update-Sicherung, Service-Prognose ohne Servicebuch und Sicherheit neu gestaltet

- aktualisierung.py: Backup-Ordner verliert sein manifest.json beim Sichern,
  sonst laedt HA ihn nach einem Neustart als zweite audi_dashboard-Integration
  (Ursache des raetselhaften "gleicher Pfad"-Umbenennungs-Fehlers).
- service.ts/audi-dashboard-app.js: Uebersicht faellt jetzt wie Service schon
  auf die Fahrzeugmeldung zurueck, wenn kein Servicebucheintrag existiert;
  eigenes (kuerzeres) Oelwechsel-Intervall wird jetzt auch ohne Servicebuch-
  eintrag naeherungsweise aus der Herstellermeldung hochgerechnet, statt
  weiterhin unveraendert die Herstellervorgabe zu zeigen.
- Sicherheit neu gestaltet: vier Sammelzeilen (Fahrzeug verriegelt / Tueren
  und Klappen geschlossen / Fenster und Dach geschlossen / Kein Licht) statt
  einer flachen Liste, mit neuen Tuerschloss-, Dach- und Standlicht-Sensor-
  rollen, Kreis-Haekchen-Symbolen und einer Detailseite je Tuer/Motorhaube/
  Kofferraum in beiden Frontends.

Details, Verifikation und Sensor-Rollen in AGENTS.md (Abschnitte J/M/N).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-24 15:29:37 +02:00
co-authored by Claude Sonnet 5
parent 146f809e9b
commit 5a048488ea
23 changed files with 866 additions and 97 deletions
@@ -16,7 +16,11 @@ Dienstaufruf noch läuft. Deshalb strenger als install.ps1s
bis feststeht, dass der Download vollständig und plausibel ist.
2. Erst danach ein atomarer Tausch per os.rename, nicht Löschen+Kopieren:
der alte Ordner wird zu audi_dashboard_backup umbenannt statt gelöscht -
reversibel, falls das Update Probleme macht.
reversibel, falls das Update Probleme macht. Dessen manifest.json wird
dabei zu manifest.json.bak umbenannt: HA erkennt Integrationen an jedem
manifest.json unter custom_components/, unabhängig vom Ordnernamen -
ohne diesen Schritt lädt ein Neustart mit vorhandenem Backup-Ordner
eine zweite Integration mit derselben Domain.
3. Schlägt der zweite Rename fehl, wird der erste zurückgenommen, statt
einen halb ersetzten Ordner zurückzulassen.
4. Kein automatischer Reload oder Neustart. Ein Reload aus dem eigenen,
@@ -231,11 +235,29 @@ def entpacken_pruefen_tauschen(
f"Konnte den bestehenden Ordner nicht sichern: {fehler}"
) from fehler
# HA scannt JEDEN Ordner unter custom_components/ mit manifest.json als
# eigene Integration - nach der Domain im Manifest, nicht nach dem
# Ordnernamen. Ohne diesen Schritt wäre der Backup-Ordner beim nächsten
# Neustart eine zweite Integration mit domain "audi_dashboard": HA
# importiert dann auch deren dienste.py als eigenes Modul
# (custom_components.audi_dashboard_backup.dienste), dessen __file__ im
# Backup-Ordner liegt - INTEGRATIONSORDNER und _BACKUP_ORDNER fallen für
# diese Kopie auf denselben Pfad zusammen, und ihre Dienst-Registrierung
# kollidiert mit der echten Integration. Das Manifest bleibt als .bak
# erhalten, falls die Fassung zurückgerollt werden muss.
backup_manifest = os.path.join(backup_ordner, "manifest.json")
if os.path.isfile(backup_manifest):
os.rename(backup_manifest, backup_manifest + ".bak")
try:
os.rename(staging_ordner, integrationsordner)
except OSError as fehler:
# Rollback: die alte Fassung zurückbenennen, statt HA ohne
# Integrationsordner dastehen zu lassen.
# Rollback: erst das Manifest wiederherstellen, dann die alte
# Fassung zurückbenennen - sonst stünde HA mit einem Ordner ohne
# manifest.json da.
backup_manifest_bak = backup_manifest + ".bak"
if os.path.isfile(backup_manifest_bak):
os.rename(backup_manifest_bak, backup_manifest)
os.rename(backup_ordner, integrationsordner)
raise AktualisierungsFehler(
f"Tausch fehlgeschlagen, alte Fassung wiederhergestellt: {fehler}"