From 5ac410a4169a562ad7f53f79de656b51e88a832e Mon Sep 17 00:00:00 2001 From: ninharp Date: Tue, 22 Sep 2026 17:48:53 +0200 Subject: [PATCH] feat: Werks-Token im Einrichtungsdialog vorbelegen Die Firmware antwortet im Auslieferungszustand und nach jedem Werksreset mit dem oeffentlichen Werks-Token aabbccddeeff0011223344 - genau wie ninlight. Wie ha-ninlight belegt die Integration es deshalb im Dialog vor, beim manuellen Einrichten, beim Fund per mDNS und in den Texten zur Token-Erneuerung. --- custom_components/ninstrip/config_flow.py | 7 +- custom_components/ninstrip/const.py | 5 ++ custom_components/ninstrip/strings.json | 65 ++++++++++++++----- .../ninstrip/translations/de.json | 65 ++++++++++++++----- .../ninstrip/translations/en.json | 4 +- 5 files changed, 109 insertions(+), 37 deletions(-) diff --git a/custom_components/ninstrip/config_flow.py b/custom_components/ninstrip/config_flow.py index 8a41d2b..e0ef057 100644 --- a/custom_components/ninstrip/config_flow.py +++ b/custom_components/ninstrip/config_flow.py @@ -23,6 +23,7 @@ from .api import NinstripAuthError, NinstripClient, NinstripError, NinstripRespo from .const import ( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL, + DEFAULT_TOKEN, DOMAIN, MAX_SCAN_INTERVAL, MIN_SCAN_INTERVAL, @@ -94,7 +95,7 @@ class NinstripConfigFlow(ConfigFlow, domain=DOMAIN): data_schema=vol.Schema( { vol.Required(CONF_HOST, default=self._host): str, - vol.Required(CONF_TOKEN): str, + vol.Required(CONF_TOKEN, default=DEFAULT_TOKEN): str, } ), errors=errors, @@ -117,7 +118,7 @@ class NinstripConfigFlow(ConfigFlow, domain=DOMAIN): async def async_step_discovery_confirm( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: - """Das Token steht einmalig auf der seriellen Konsole - es muss von Hand herein.""" + """Vorbelegt mit dem Werks-Token - ein frisch onboardetes Geraet antwortet damit.""" errors: dict[str, str] = {} if user_input is not None: info, errors = await self._async_probe(self._host, user_input[CONF_TOKEN]) @@ -125,7 +126,7 @@ class NinstripConfigFlow(ConfigFlow, domain=DOMAIN): return await self._async_finish(self._host, user_input[CONF_TOKEN], info) return self.async_show_form( step_id="discovery_confirm", - data_schema=vol.Schema({vol.Required(CONF_TOKEN): str}), + data_schema=vol.Schema({vol.Required(CONF_TOKEN, default=DEFAULT_TOKEN): str}), description_placeholders={"name": self._discovered_name, "host": self._host}, errors=errors, ) diff --git a/custom_components/ninstrip/const.py b/custom_components/ninstrip/const.py index bfd6b21..f6a3188 100644 --- a/custom_components/ninstrip/const.py +++ b/custom_components/ninstrip/const.py @@ -6,6 +6,11 @@ from typing import Final DOMAIN: Final = "ninstrip" +# Oeffentliches Werks-Token der Firmware (NL_DEFAULT_TOKEN), dasselbe wie bei +# ninlight. Ein Geraet im Auslieferungszustand und nach jedem Werksreset +# antwortet damit - deshalb belegt der Einrichtungsdialog es vor. +DEFAULT_TOKEN: Final = "aabbccddeeff0011223344" + CONF_SCAN_INTERVAL: Final = "scan_interval" DEFAULT_PORT: Final = 3333 diff --git a/custom_components/ninstrip/strings.json b/custom_components/ninstrip/strings.json index d462575..e7c5103 100644 --- a/custom_components/ninstrip/strings.json +++ b/custom_components/ninstrip/strings.json @@ -3,18 +3,25 @@ "step": { "user": { "title": "ninstrip hinzufügen", - "description": "Adresse und API-Token des Geräts. Das Token wird beim ersten Start einmalig auf der seriellen Konsole ausgegeben; ein Werksreset erzeugt ein neues.", - "data": { "host": "Adresse", "token": "API-Token" } + "description": "Adresse und API-Token des Geräts. Im Auslieferungszustand und nach einem Werksreset gilt das Werks-Token, das bereits eingetragen ist. Wer ein eigenes gesetzt hat, trägt es hier ein.", + "data": { + "host": "Adresse", + "token": "API-Token" + } }, "discovery_confirm": { "title": "ninstrip gefunden", "description": "{name} unter {host}. Bitte das API-Token eingeben.", - "data": { "token": "API-Token" } + "data": { + "token": "API-Token" + } }, "reauth_confirm": { "title": "Token erneuern", - "description": "Das Gerät unter {host} weist das gespeicherte Token ab. Nach einem Werksreset hat es ein neues.", - "data": { "token": "API-Token" } + "description": "Das Gerät unter {host} weist das gespeicherte Token ab. Nach einem Werksreset gilt wieder das Werks-Token.", + "data": { + "token": "API-Token" + } } }, "error": { @@ -32,24 +39,50 @@ "step": { "init": { "title": "Einstellungen", - "data": { "scan_interval": "Abfrageabstand (Sekunden)" } + "data": { + "scan_interval": "Abfrageabstand (Sekunden)" + } } } }, "entity": { - "select": { "preset": { "name": "Szene" } }, - "button": { "restart": { "name": "Neu starten" } }, + "select": { + "preset": { + "name": "Szene" + } + }, + "button": { + "restart": { + "name": "Neu starten" + } + }, "sensor": { - "rssi": { "name": "WLAN-Signal" }, - "uptime": { "name": "Laufzeit" }, - "free_heap": { "name": "Freier Speicher" }, - "power_scale": { "name": "Leistungsbegrenzung" } + "rssi": { + "name": "WLAN-Signal" + }, + "uptime": { + "name": "Laufzeit" + }, + "free_heap": { + "name": "Freier Speicher" + }, + "power_scale": { + "name": "Leistungsbegrenzung" + } } }, "exceptions": { - "auth_failed": { "message": "Das Gerät hat das Token abgelehnt." }, - "device_busy": { "message": "Das Gerät ist beschäftigt - vermutlich läuft eine Aktualisierung." }, - "request_failed": { "message": "Das Gerät hat die Anfrage abgewiesen: {message}" }, - "cannot_connect": { "message": "Das Gerät ist nicht erreichbar." } + "auth_failed": { + "message": "Das Gerät hat das Token abgelehnt." + }, + "device_busy": { + "message": "Das Gerät ist beschäftigt - vermutlich läuft eine Aktualisierung." + }, + "request_failed": { + "message": "Das Gerät hat die Anfrage abgewiesen: {message}" + }, + "cannot_connect": { + "message": "Das Gerät ist nicht erreichbar." + } } } diff --git a/custom_components/ninstrip/translations/de.json b/custom_components/ninstrip/translations/de.json index d462575..e7c5103 100644 --- a/custom_components/ninstrip/translations/de.json +++ b/custom_components/ninstrip/translations/de.json @@ -3,18 +3,25 @@ "step": { "user": { "title": "ninstrip hinzufügen", - "description": "Adresse und API-Token des Geräts. Das Token wird beim ersten Start einmalig auf der seriellen Konsole ausgegeben; ein Werksreset erzeugt ein neues.", - "data": { "host": "Adresse", "token": "API-Token" } + "description": "Adresse und API-Token des Geräts. Im Auslieferungszustand und nach einem Werksreset gilt das Werks-Token, das bereits eingetragen ist. Wer ein eigenes gesetzt hat, trägt es hier ein.", + "data": { + "host": "Adresse", + "token": "API-Token" + } }, "discovery_confirm": { "title": "ninstrip gefunden", "description": "{name} unter {host}. Bitte das API-Token eingeben.", - "data": { "token": "API-Token" } + "data": { + "token": "API-Token" + } }, "reauth_confirm": { "title": "Token erneuern", - "description": "Das Gerät unter {host} weist das gespeicherte Token ab. Nach einem Werksreset hat es ein neues.", - "data": { "token": "API-Token" } + "description": "Das Gerät unter {host} weist das gespeicherte Token ab. Nach einem Werksreset gilt wieder das Werks-Token.", + "data": { + "token": "API-Token" + } } }, "error": { @@ -32,24 +39,50 @@ "step": { "init": { "title": "Einstellungen", - "data": { "scan_interval": "Abfrageabstand (Sekunden)" } + "data": { + "scan_interval": "Abfrageabstand (Sekunden)" + } } } }, "entity": { - "select": { "preset": { "name": "Szene" } }, - "button": { "restart": { "name": "Neu starten" } }, + "select": { + "preset": { + "name": "Szene" + } + }, + "button": { + "restart": { + "name": "Neu starten" + } + }, "sensor": { - "rssi": { "name": "WLAN-Signal" }, - "uptime": { "name": "Laufzeit" }, - "free_heap": { "name": "Freier Speicher" }, - "power_scale": { "name": "Leistungsbegrenzung" } + "rssi": { + "name": "WLAN-Signal" + }, + "uptime": { + "name": "Laufzeit" + }, + "free_heap": { + "name": "Freier Speicher" + }, + "power_scale": { + "name": "Leistungsbegrenzung" + } } }, "exceptions": { - "auth_failed": { "message": "Das Gerät hat das Token abgelehnt." }, - "device_busy": { "message": "Das Gerät ist beschäftigt - vermutlich läuft eine Aktualisierung." }, - "request_failed": { "message": "Das Gerät hat die Anfrage abgewiesen: {message}" }, - "cannot_connect": { "message": "Das Gerät ist nicht erreichbar." } + "auth_failed": { + "message": "Das Gerät hat das Token abgelehnt." + }, + "device_busy": { + "message": "Das Gerät ist beschäftigt - vermutlich läuft eine Aktualisierung." + }, + "request_failed": { + "message": "Das Gerät hat die Anfrage abgewiesen: {message}" + }, + "cannot_connect": { + "message": "Das Gerät ist nicht erreichbar." + } } } diff --git a/custom_components/ninstrip/translations/en.json b/custom_components/ninstrip/translations/en.json index 45c80b0..b330a84 100644 --- a/custom_components/ninstrip/translations/en.json +++ b/custom_components/ninstrip/translations/en.json @@ -3,7 +3,7 @@ "step": { "user": { "title": "Add ninstrip", - "description": "Host and API token of the device. The token is printed once on the serial console at first boot; a factory reset creates a new one.", + "description": "Host and API token of the device. A factory-new or factory-reset device uses the default token, which is prefilled. If you set your own, enter it here.", "data": { "host": "Host", "token": "API token" @@ -18,7 +18,7 @@ }, "reauth_confirm": { "title": "Renew token", - "description": "The device at {host} rejects the stored token. After a factory reset it has a new one.", + "description": "The device at {host} rejects the stored token. After a factory reset the default token applies again.", "data": { "token": "API token" }