Files
audi-app/custom_components/audi_dashboard/config_flow.py
T
tobias 8c96d9b78e Zugaenge: die Dienste-Token aus App und Panel bedienbar (2026.9.3.8)
Die Token liegen seit jeher in entry.options, geschrieben vom Options-Flow
unter Einstellungen -> Geraete & Dienste -> Konfigurieren. Der Weg bleibt und
ist der Rueckfall, wenn die App den Server nicht erreicht - genau der Fall, in
dem ein abgelaufener Token auffaellt. Erreichbar ist er aber nur ueber HAs
eigene Weboberflaeche; die iOS-App zeigt keine Konfigurationsdialoge. Die neue
Kachel ist die Bedienflaeche dafuer, kein zweiter Speicherort.

Der Wert kommt nie zurueck: veroeffentlicht werden nur "gesetzt/nicht gesetzt"
und die letzten vier Zeichen (unter zwoelf Zeichen Laenge gar nichts). Auch das
Protokoll bekommt ihn nicht, und das Panel leert das Eingabefeld sofort nach
dem Absenden.

Bewusst NICHT im Fahrzeugprofil: sicherung.py sichert fahrzeugprofil.json, und
"Backup exportieren" laedt es als Datei auf das Geraet - ein Token dort wanderte
in jede Sicherung und jede weitergegebene Datei.

Ein Dienst statt zwei: zugang_setzen(dienst, token), leerer Text loescht. In der
App nicht ueber die Warteschlange - ein Stunden spaeter nachgereichter Token
ueberschriebe womoeglich einen inzwischen eingetragenen neuen.

CONF_FLESPI_TOKEN ist neu und noch ohne Leser; der Flespi-Weg zum Auslesen der
Geraetekonfiguration ist damit vorbereitet, aber nicht gebaut.

Verifiziert: py_compile auf sechs Backend-Dateien, Panel als Modul geparst,
companion-app tsc sauber und 179/179, audi_ha_test auf 2026.9.3.8 sauber
gestartet. Live am laufenden Panel der ganze Kreis, Container hinterher wie
vorgefunden: Wegwerf-Token gesetzt -> "gesetzt . ...0000", der Wert selbst
taucht in den veroeffentlichten Attributen nirgends auf (darauf geprueft),
ueber die Sicherheitsabfrage geloescht -> wieder "nicht gesetzt", der
Gitea-Token unberuehrt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 15:08:55 +02:00

89 lines
3.6 KiB
Python

"""Einrichtung über die Oberfläche (Einstellungen -> Geräte & Dienste ->
Integration hinzufügen -> Audi Dashboard).
Bewusst ohne Eingabefelder im Ersteinrichtungs-Schritt. Es gäbe genau eine
Sache zu fragen - welche Entität welche Rolle im Fahrzeug spielt -, und die
gehört nicht hierher: die Zuordnung wird im Setup-Menü der App selbst
vorgenommen, wo neben jedem Feld steht, wofür es gebraucht wird und was
passiert, wenn es leer bleibt. Sie hier abzufragen hieße, dieselbe Auswahl an
zwei Stellen zu pflegen - und die schlechtere von beiden zuerst zu zeigen.
Eine einzige Instanz, erzwungen über single_config_entry in manifest.json:
die App gehört zu genau einem Fahrzeug, und alle Bestände liegen unter einem
festen Pfad.
Der OptionsFlow unten ist die einzige Ausnahme: ein Gitea-Zugriffstoken für
das Selbst-Update (siehe aktualisierung.py) - ein echtes Geheimnis, das
deshalb in HAs eigenem, verschlüsseltem Config-Entry-Speicher landet
(entry.options), nicht in configuration.yaml.
"""
from __future__ import annotations
from typing import Any
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.core import callback
from homeassistant.helpers import selector
from .const import CONF_FLESPI_TOKEN, CONF_GITEA_TOKEN, DOMAIN
class AudiDashboardConfigFlow(ConfigFlow, domain=DOMAIN):
"""Ein Bestätigungsschritt, mehr braucht es nicht."""
VERSION = 1
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
if user_input is None:
return self.async_show_form(step_id="user")
return self.async_create_entry(title="Audi Dashboard", data={})
@staticmethod
@callback
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow:
return AudiDashboardOptionsFlow()
class AudiDashboardOptionsFlow(OptionsFlow):
"""Einstellungen -> Geräte & Dienste -> Audi Dashboard -> Konfigurieren.
Zwei Felder, beide freiwillig: der Gitea-Token fürs Selbst-Update und der
flespi-Token fürs Auslesen der Geräte-Konfiguration. Leer lassen schaltet
die jeweilige Funktion ab (aktualisierung.py verlangt einen nicht-leeren
Token, sonst gibt es eine verständliche Fehlermeldung statt eines
unbehandelten Fehlers).
Dieser Weg bleibt der Rückfall neben der Kachel „Zugänge" in App und Panel
(siehe zugaenge.py): er ist der einzige, der auch dann trägt, wenn die App
den Server gerade nicht erreicht - genau der Fall, in dem ein abgelaufener
Token auffällt. Beide schreiben in dieselben entry.options, es gibt keinen
zweiten Wahrheitsort."""
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
return self.async_show_form(
step_id="init",
data_schema=self.add_suggested_values_to_schema(
vol.Schema({
vol.Optional(CONF_GITEA_TOKEN, default=""): selector.TextSelector(
selector.TextSelectorConfig(type=selector.TextSelectorType.PASSWORD)
),
vol.Optional(CONF_FLESPI_TOKEN, default=""): selector.TextSelector(
selector.TextSelectorConfig(type=selector.TextSelectorType.PASSWORD)
),
}),
self.config_entry.options,
),
)