Files

119 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ninlight für Home Assistant
Lokale Home-Assistant-Integration für Lampen mit der [ninlight-Firmware](https://gitea.zukunpht.de/ninharp/ninlight-w600)
(migrierte Klyqa-Lampen auf WinnerMicro W600: GU10, E27, E14, G95). Keine Cloud, kein Konto –
HA spricht direkt mit der REST-API der Lampe auf Port 3333.
## Voraussetzungen
- Home Assistant 2026.9 oder neuer
- Lampen mit ninlight-Firmware im selben Netz
## Installation
Das Repo ist privat und nicht über HACS verfügbar. Den Ordner `custom_components/ninlight` nach
`<config>/custom_components/ninlight` der Home-Assistant-Instanz kopieren (z. B. per
`/usr/bin/scp -r` oder über das Samba-/SSH-Add-on) und Home Assistant neu starten. Für ein Update
denselben Ordner ersetzen und erneut neu starten.
## Einrichtung
Lampen werden per mDNS (`_ninlight._tcp`) gefunden und unter *Einstellungen → Geräte & Dienste*
angeboten. Alternativ „Integration hinzufügen → ninlight" und IP-Adresse oder
`ninlight-xxxx.local` eingeben.
Das Token-Feld ist mit dem **öffentlichen Vorgabe-Token** `aabbccddeeff0011223344` vorbelegt.
Solange eine Lampe dieses Token nutzt, kann jeder in deinem Netz sie neu konfigurieren, neu
starten, neu flashen oder auf Werkseinstellungen zurücksetzen (sie verliert dabei ihr WLAN und
fällt zurück in den Onboarding-Zugangspunkt); HA zeigt dafür einen Reparaturhinweis. Schalten und
Dimmen sind ohne `auth_all` ohnehin für jeden im Netz möglich – ein eigenes Token allein schützt
nicht davor.
Eigenes Token auf der Lampe setzen (`PUT /api/v1/system/settings` mit
`{"type":"token","token":"…"}`) und in HA über *Neu konfigurieren* eintragen. Willst du zusätzlich
das Schalten schützen, aktiviere `auth_all` auf der Lampe:
```
PUT /api/v1/system/settings
{"type": "auth", "all": true}
```
Mit aktiviertem `auth_all` verlangt jede Abfrage – auch lesende – das Token; ein falsches oder
fehlendes Token führt dann sofort zur Neuanmeldung.
Wechselt eine Lampe ihre IP, aktualisiert mDNS den Eintrag selbst (Identität ist die MAC).
Das gilt ungeprüft: Ein Gerät im selben Netz, das dieselbe MAC per mDNS ankündigt, übernimmt
damit den Host-Eintrag und kann so an Anfragen mit Token gelangen, die eigentlich an die echte
Lampe gehen (relevant nur in einem bereits kompromittierten Netz).
## Entitäten
| Entität | Art | Hinweis |
|---|---|---|
| Lampe | Licht | An/Aus, Helligkeit, Farbe (RGB-Lampen), Farbtemperatur, Übergang |
| Einblenden, Ausblenden, Standardübergang | Zahl (Konfiguration) | Millisekunden |
| Einschaltverhalten | Auswahl (Konfiguration) | letzter Zustand / ein / aus |
| Bei Änderung einschalten | Schalter (Konfiguration) | |
| Neustart | Taste (Konfiguration) | Werksreset wird bewusst nicht angeboten |
| Signalstärke | Sensor (Diagnose) | |
| IP-Adresse, freier Speicher, letzter Update-Fehler, letzter Start | Sensor (Diagnose) | standardmäßig deaktiviert |
| Firmware | Update | siehe unten |
## Verfügbarkeit
Kurze Aussetzer werden toleriert: Erst nach 3 fehlgeschlagenen Abfragen in Folge gilt die Lampe
als nicht verfügbar. Beim Standardintervall von 30 s und 10 s Timeout sind das 90–120 s (gemessen
an der G95: 90 s und 110 s). Fehlgeschlagene Schaltbefehle werden dagegen sofort als Fehler
gemeldet. Im HA-Debug-Log erscheinen tolerierte Fehlschläge als „poll failed (n/3)“ und trotzdem
mit „success: True“, weil der zuletzt bekannte Zustand weiterverwendet wird.
## Firmware-Updates
Home Assistant bietet Updates aus dem Ordner **`<config>/ninlight_firmware/`** an (wird beim
ersten Start angelegt). Dort `*_ota.img`-Dateien ablegen; Dateinamen sind egal. HA liest
Gerätetyp und Version aus dem Trailer des Images, prüft die Prüfsumme und bietet jeder Lampe nur
Images **ihres** Gerätetyps an, die **neuer** sind als ihre Firmware.
Die Lampe lädt das Image über reines `http://` direkt von Home Assistant, unter einer zufälligen
Adresse, die nur während dieses einen Updates gilt. Erreichen die Lampen die interne URL von HA
nicht über `http://` (z. B. HA hinter HTTPS oder in Docker auf macOS), in den Optionen der
Integration **„Adresse, unter der Lampen Home Assistant erreichen"** setzen, etwa
`http://192.168.1.50:8123`.
### WLAN-Sicherung – wichtig
Eine Lampe kennt ihr WLAN entweder aus **gespeicherten Einstellungen** oder nur aus der
**einkompilierten Firmware** (`GET /api/v1/system/settings` → `wifi.source`). Im zweiten Fall
würde ein Image **ohne** WLAN-Zugangsdaten die Lampe nach dem Update aus dem Netz werfen – sie
startet dann im Onboarding-Zugangspunkt.
Deshalb bietet HA einer solchen Lampe nur Images an, die die SSID ihres aktuellen WLANs enthalten.
Liegt ein neueres Image ohne diese Zugangsdaten im Ordner, erscheint stattdessen ein
Reparaturhinweis.
**Das Release-Archiv der Firmware enthält Images ohne Zugangsdaten.** Für Lampen, die ihr WLAN
aus der Firmware beziehen, eigene Images **mit** Zugangsdaten bauen (`config.local.cmake` im
Firmware-Repo).
Grenzen der Prüfung: geprüft wird die SSID, nicht das Passwort; und eine Heim-SSID, die zufällig
einem Text der Firmware gleicht (z. B. `ninlight-recovery`), würde fälschlich als vorhanden
erkannt.
## Diagnose
*Gerät → ⋮ → Diagnose herunterladen* liefert Zustand, Systeminfo und passende Firmware-Dateien.
Token, WLAN-Name, MAC und IP sind geschwärzt.
## Entwicklung
```bash
uv venv --python /opt/homebrew/bin/python3.14 .venv && uv pip install --python .venv/bin/python -r requirements_dev.txt
scripts/check.sh
```
Home Assistant 2026.9 braucht Python ≥ 3.14.2. Vor jedem Push `scripts/check.sh` laufen lassen –
das Repo liegt im Gitea ohne CI.
`tests_unit/` läuft ohne Home-Assistant-Instanz (HTTP-Client gegen einen lokalen Server,
Firmware-Logik), `tests/` gegen eine Test-Instanz.