Umstellung von pyscript auf eine eigene Integration mit Konfigurationsdialog: Einrichtung komplett ueber die Oberflaeche, kein YAML, Updates als Knopfdruck. Alle genannten Schnittstellen sind an der laufenden 2026.8.1-Instanz geprueft, nicht aus der Dokumentation uebernommen - inklusive Signaturen. Zur Verteilung festgehalten: HACS kann ausschliesslich GitHub und scheidet fuer das Gitea-Repository aus; App-Repositories akzeptieren zwar beliebige Git-URLs, Apps sind aber Docker-Container und damit der falsche Behaelter fuer eine Integration. Nativ bleibt die eigene UpdateEntity, deren Logik in updateverwaltung.py bereits zu grossen Teilen existiert. Dazu festgehalten, welche Befunde aus dem main-Review die Umstellung konstruktionsbedingt aufloest - vor allem die drei Setup-Menue-Fehler und die Token-Datei im Klartext.
12 KiB
DataMetric360 als native Home-Assistant-Integration
Stand: 2026-08-13. Vorhaben: Das HA-Backend von „pyscript-Skripte plus Dateien kopieren" auf eine eigene Integration mit Konfigurationsdialog umstellen — Einrichtung vollständig über die Oberfläche, kein YAML, Updates als Knopfdruck in HAs eigener Update-Liste.
Alle unten genannten Schnittstellen sind an der laufenden Instanz geprüft (Home Assistant
2026.8.1 im Container audi_ha_test), nicht aus der Dokumentation abgeschrieben. Die geprüften
Signaturen stehen jeweils dabei.
Verwandte Dokumente: homeassistant/INSTALL.md (heutiger, manueller Weg — bleibt gültig, bis diese
Umstellung steht), UMSETZUNGSPLAN.md, REVIEW_main_2026-08-13.md (die Fehler, die hier
konstruktionsbedingt verschwinden).
1. Was heute nötig ist — und was davon bleibt
| Heute | Nach der Umstellung |
|---|---|
| HACS installieren, darüber pyscript | entfällt |
drei Ordner nach /config/ kopieren (pyscript/, data/, www/) |
einmalig ein Ordner nach custom_components/ |
zwei Blöcke in configuration.yaml einfügen |
entfällt vollständig |
| Entity-IDs zuordnen | bleibt, aber als HA-Konfigurationsdialog statt als selbstgebautes Menü |
langlebiges Token in audi_dashboard/ha_token.txt ablegen |
entfällt ersatzlos |
pip install pypdf von Hand |
entfällt (manifest.json → requirements) |
| Neustart | einmalig, wie bei jeder Integration |
Updates über update.ps1 per Samba |
Knopfdruck in Einstellungen → System → Updates |
2. Die Bausteine, die HA dafür mitbringt
Alle in 2026.8.1 vorhanden und geprüft:
| Baustein | Ersetzt |
|---|---|
EntitySelector mit domain, device_class, multiple, reorder, exclude_entities |
das gesamte Setup-Menü (entitaeten.py + ~800 Zeilen JS) |
panel_custom.async_register_panel(...) |
den panel_custom-Block in configuration.yaml |
hass.http.async_register_static_paths([StaticPathConfig(url_path, path, cache_headers)]) |
Kopieren nach /config/www/ samt Cache-Busting-Stub |
ConfigEntry.add_update_listener(...) |
den „wirkt erst nach Neustart"-Hinweis bei den drei triggergebundenen Feldern |
async_track_state_change_event / async_track_time_interval / async_track_time_change |
@state_trigger / @time_trigger("period") / @time_trigger("cron") |
recorder.history.get_significant_states(...) |
den HTTP-Aufruf auf /api/history/period samt Token-Datei |
hass.async_add_executor_job(...) |
task.executor(io.open, ...) |
Store (homeassistant.helpers.storage) |
handgeschriebenes JSON-I/O (optional, siehe §6) |
HomeAssistantView / websocket_api.async_register_command |
die 16-KB-Attributgrenze für Fahrten und Tankvorgänge |
UpdateEntity (INSTALL, PROGRESS, BACKUP, RELEASE_NOTES) |
updateverwaltung.py als sichtbare Update-Entität |
Der wichtigste Einzelfund: EntitySelector kann exclude_entities. Die Duplikat-Prüfung wäre
damit keine wegklickbare Warnung mehr, sondern schlicht nicht anwählbar.
3. Aufbau
custom_components/datametric360/
├── manifest.json Abhängigkeiten, "config_flow": true, Version
├── const.py Rollen-Tabelle (heute FELDER in entitaeten.py)
├── config_flow.py Ersteinrichtung + Optionen (die 17 Sensor-Rollen)
├── __init__.py Dienste, Horcher, Zeitgeber, Panel, statische Dateien
├── update.py UpdateEntity gegen das eigene Gitea
├── api.py HomeAssistantView für die Companion-App (später)
└── www/ audi-dashboard-app.js, .css, badges/ — mitgeliefert
Konfigurationsdialog
Statt einer eigenen Katalogverwaltung reicht ein Schema. Skizze für zwei der 17 Rollen:
vol.Schema({
vol.Required("zuendung_sensor"): EntitySelector(
EntitySelectorConfig(domain=["binary_sensor"])
),
vol.Optional("tuer_sensoren", default=[]): EntitySelector(
EntitySelectorConfig(domain=["binary_sensor"], device_class=["door"],
multiple=True, reorder=True)
),
})
Suche, Übersetzung, Gerätezuordnung und Mehrfachauswahl kommen von HA. Die vier Türpositionen werden zu einer sortierbaren Mehrfachauswahl — die Reihenfolge ersetzt die heutigen festen Positionsfelder.
Panel und Dateien
await hass.http.async_register_static_paths([
StaticPathConfig("/datametric360", hass.config.path("custom_components/datametric360/www"),
cache_headers=False),
])
panel_custom.async_register_panel(
hass, frontend_url_path="datametric360", webcomponent_name="audi-dashboard-panel",
sidebar_title="Mein Audi", sidebar_icon="mdi:car-sports",
module_url=f"/datametric360/audi-dashboard-app.js?v={VERSION}",
)
Die Versionsnummer in der URL macht den Lade-Stub audi-dashboard-panel.js und
audi-dashboard-version.json überflüssig — das Cache-Problem löst sich, weil die Integration ihre
eigene Version kennt.
Das Frontend selbst bleibt unangetastet. Alle 3.873 Zeilen audi-dashboard-app.js laufen
weiter; nur das Setup-Menü darin wird überflüssig.
4. Übersetzung der pyscript-Eigenheiten
Mechanisch, kein Neuentwurf. Die Fachlogik — Fahrterkennung, Tankerkennung, Beleg-Parser, Reifenzähler, Prognose — geht nahezu unverändert mit.
| pyscript | Integration |
|---|---|
@service def audi_dashboard_x() |
hass.services.async_register(DOMAIN, "x", handler, schema) |
@state_trigger(f"{SENSOR}") |
async_track_state_change_event(hass, [sensor], handler) |
@time_trigger("period(now, 20 seconds)") |
async_track_time_interval(hass, handler, timedelta(seconds=20)) |
@time_trigger("cron(0 4 * * *)") |
async_track_time_change(hass, handler, hour=4, minute=0, second=0) |
task.unique() + task.sleep() |
asyncio.Task merken und bei Bedarf cancel() |
task.executor(io.open, …) |
hass.async_add_executor_job(...) |
state.set("pyscript.x", …) |
eigene Entität oder HomeAssistantView (siehe §6) |
subprocess.run(shell_beleg_parser.py) |
pypdf direkt importieren, in einem Executor-Job |
urllib.request auf /api/history/period |
recorder.history.get_significant_states(...) |
Die letzte Zeile ist die wichtigste: Sie beseitigt zwei Befunde auf einmal — den blockierenden
Aufruf, den HA seit 2026.8 abbricht (siehe REVIEW_main_2026-08-13.md, und derselbe Fehler wurde
im Branch umsetzung-datametric360 bereits behoben), und die Token-Datei im Klartext.
5. Installation und Updates
Hier liegt der eigentliche Knackpunkt, deshalb ausführlich.
HACS scheidet aus
HACS spricht ausschließlich mit GitHub. Anfragen, auch GitLab, Gitea oder Codeberg zuzulassen, gibt
es seit Jahren; umgesetzt sind sie nicht. Das Repository liegt auf gitea.nothaft.cloud — HACS ist
damit kein Weg, außer man spiegelt nach GitHub.
„App" ist der falsche Behälter
App-Repositories (früher Add-ons) akzeptieren beliebige Git-URLs, auch selbst gehostete; nötig
ist nur eine repository.yaml im Wurzelverzeichnis. Das ist die einzige Stelle, an der Gitea
nativ mitspielen würde.
Inhaltlich passt es trotzdem nicht: Apps sind Docker-Container neben Home Assistant. Eine Integration muss im HA-Prozess laufen, um Entitäten anzulegen, Dienste zu registrieren und ein Panel einzuhängen. Eine App kann das nicht.
(Es gäbe den Trick, eine winzige App zu bauen, die nichts weiter tut, als die Integration nach
custom_components/ zu schreiben — dann käme auch die Erstinstallation aus dem eigenen Gitea. Ein
Docker-Container für einen einmaligen Kopiervorgang ist das aus meiner Sicht nicht wert; der
Vollständigkeit halber notiert.)
Der native Weg: eigene UpdateEntity
UpdateEntity lässt die Integration ihre Updates selbst melden — sichtbar in Einstellungen →
System → Updates, derselben Liste wie HA-Kern und Apps. Geprüfte Möglichkeiten:
UpdateEntityFeature: INSTALL, SPECIFIC_VERSION, PROGRESS, BACKUP, RELEASE_NOTES
async_install(version: str | None, backup: bool, **kwargs) -> None
BACKUP gibt es genau für das, was updateverwaltung.py heute von Hand macht: vor dem Einspielen
den alten Code sichern.
Die Logik ist bereits vorhanden. updateverwaltung.py klont flach, vergleicht Versionen,
sichert nach code_backups/ und ersetzt die Dateien. Das wandert nahezu unverändert in
async_install(). Neu sind nur zwei Eigenschaften:
@property
def installed_version(self) -> str: return VERSION # aus manifest.json
@property
def latest_version(self) -> str | None: return self._neueste # aus Gitea
Für latest_version empfiehlt sich statt der heutigen Zeitstempel-Zahl aus
audi-dashboard-version.json ein Git-Tag. Gitea bietet eine GitHub-kompatible Schnittstelle:
GET https://gitea.nothaft.cloud/api/v1/repos/paul/audi-app/releases/latest
Ein einzelner HTTP-Aufruf, kein Klonen. In HA steht dann „1.4.0 → 1.5.0" statt einer nichtssagenden
Zahl, und die Release-Beschreibung lässt sich über release_notes direkt anzeigen.
Was bleibt
Die Erstinstallation bleibt ein einmaliges Kopieren des Ordners nach custom_components/. Für
Integrationen aus Nicht-GitHub-Quellen gibt es keinen nativen Installationsweg. Jedes weitere
Update ist danach ein Knopfdruck.
6. Datenhaltung — bewusst zu entscheiden
Zwei Möglichkeiten, beide vertretbar:
Store(.storage/datametric360): atomar, versioniert, mit Migrationspfad. Nachteil: für Menschen nicht mehr lesbar, und die heutige Sicherung überbackup.pymüsste neu gedacht werden.- JSON-Dateien behalten unter
/config/audi_dashboard/, gelesen über Executor-Jobs. Nachteil: kein Migrationspfad. Vorteil: Fahrten und Tankvorgänge bleiben von Hand einsehbar und mit den bestehenden Sicherungen kompatibel.
Empfehlung: Dateien behalten. Bei einem Fahrzeugprofil, einem Fahrtenbuch und einer Tankhistorie ist Lesbarkeit mehr wert als Migrationskomfort — und die vorhandene Sicherungslogik bleibt gültig.
Unabhängig davon: Fahrten und Tankvorgänge gehören nicht in Entitäts-Attribute (16-KB-Grenze,
siehe frontend_veroeffentlichung.py), sondern hinter einen HomeAssistantView. Das ist zugleich
die saubere Schnittstelle für die Companion-App, die heute Attribut-Blobs auslesen muss.
7. Was dabei konstruktionsbedingt verschwindet
Aus REVIEW_main_2026-08-13.md:
- Befund 1 (Speichern mit leerem Katalog löscht alle Zuordnungen) — der Konfigurationsdialog validiert serverseitig, ein leeres Formular kommt gar nicht durch.
- Befunde 2 und 5 (Zurücksetzen wirkungslos bzw. zu stark) — die
setattr-Override-Ebene entfällt komplett; HA verwaltet Optionen selbst. - Befunde 3 und 4 (falsche Vorbelegung, beliebige Sensoren) — HAs Entity-Picker schlägt nichts
vor, der Nutzer wählt;
exclude_entitiesverhindert Doppelbelegung. - Befund 7 (kaputte
entitaeten.jsonlegt das Panel lahm) — die Datei existiert nicht mehr. - Der Neustart-Zwang bei den drei triggergebundenen Feldern —
add_update_listenerlädt die Integration neu und registriert die Horcher dabei mit den neuen Entity-IDs.
Nicht gelöst werden dadurch: die Frontend-Befunde (Standort-Dauerfeuer, Barrierefreiheit,
.navmarke) — das Frontend bleibt ja unverändert.
8. Aufwand und Reihenfolge
Realistisch einige Tage, nicht Wochen — der Großteil ist Umschreiben von Dekoratoren.
- Zuerst die drei Setup-Fehler roh fixen (etwa eine Stunde). Sonst läuft die Instanz bis zur Umstellung mit einem Datenverlust-Pfad.
- Gerüst aufsetzen:
manifest.json,config_flow.py, Panel- und Dateiregistrierung. Die pyscript-Skripte laufen dabei zunächst unverändert weiter. - Logik Datei für Datei herüberziehen, beginnend mit
fahrtabschluss_logik.py— dort verschwinden Token und blockierender Aufruf zuerst. update.pygegen das Gitea-Repository.api.pyfür die Companion-App, sobald diese so weit ist.
Was dabei zu beachten ist
- Neuladen im laufenden Betrieb entfällt. pyscript lädt bei jeder Dateiänderung neu; eine Integration braucht einen Neustart oder ein Neuladen. Beim Entwickeln spürbar, im Betrieb egal.
- Die Companion-App liest heute
pyscript.audi_dashboard_*. Werden daraus eigene Entitäten oder ein eigener Endpunkt, ändert sich die TabelleENTITAETENincompanion-app/src/api/types.ts— eine Datei, überschaubar. shell_beleg_parser.pywandert mit in die Integration. Heute liegt er unter/config/audi_dashboard/und wird von keinem Update-Pfad ausgeliefert (siehe Review) — als Teil des Integrationsordners löst sich das mit.