Zum Inhalt springen
labkompass

Logbuch#smart-home#shelly#webos#architektur#control-center

Die Haus-Säule steht — an fünf echten Shellys gebaut, nicht am Reißbrett

Von Niclas Hennrich · veröffentlicht · geschehen am


BuildIm Einsatz

Selbst gebaut und in Betrieb genommen. Gehört zum Vorhaben HomeOS — Control Center mit drei Säulen.

Shellys gelesen, ohne Cloud
5
Fehler im eigenen Code, durch Tests gefunden
4
Faktor Wattminuten → Wattstunden bei Gen 1
60

Kurz zur Einordnung: HomeOS ist mein selbst gebautes Control Center fürs Homelab. Es ist aus dem Infrastruktur-NOC gewachsen und soll drei Säulen tragen: Infrastruktur, Haus (Smart Home) und Family (Haushalt). Seit ich Home Assistant wieder abgebaut hatte, war die Haus-Säule ein Versprechen ohne eine Zeile Code. Das hier ist der Tag, an dem sie entstanden ist.

Was ich wollte: Die Smart-Home-Säule gegen echte Geräte bauen, nicht als Vorratsmodell. Im Netz standen fünf Shelly-Steckdosen mit Leistungsmessung aus zwei Protokollgenerationen — Gen 2 spricht JSON-RPC, Gen 1 eine ältere REST-Schnittstelle — und ein Fernseher mit webOS. Alles sollte unter derselben Oberfläche laufen wie das Monitoring, ohne dass sich die Datenmodelle vermischen.

Modell nach dem ersten Gerät, nicht davor. Die erste Antwort einer Shelly hat das Datenmodell entschieden: Eine Steckdose ist ein Gerät, liefert aber gleichzeitig Schalter, Leistung, Energie, Spannung, Strom und Gerätetemperatur. Also Gerät und Entity (eine einzelne Funktion) getrennt — erst das macht „alles, was Leistung misst" zu einer Abfrage. Auf dem Reißbrett wäre mir das nicht aufgefallen, an der echten Nutzlast sofort. Der Adapter kennt keine Datenbank, die Datenbank keinen Hersteller — „Shelly" steht in genau einer Datei.

Zwei Generationen kosten wenig — mit einer Falle. Der Unterschied zwischen Gen 1 und Gen 2 sind zwei Lesefunktionen und eine Einheit. Die Einheit hat es in sich: Gen 2 liefert den Energiezähler in Wattstunden, Gen 1 in Wattminuten. Faktor 60. Wer das übersieht, bekommt für die alte Steckdose einen Sechzigfach-Wert und merkt es erst, wenn eine Jahresauswertung nicht aufgeht. Umgerechnet wird jetzt an genau einer Stelle, der Rohwert bleibt als Attribut erhalten. Ein funktionierendes Gerät zu ersetzen, um sich das zu sparen, wäre die teurere Lösung gewesen.

Vier Fehler im eigenen Code, alle durch Tests gefunden. Der teuerste: Eine dimmbare Lampe hat Helligkeit und Farbtemperatur, mein Entity aber nur einen Zahlenwert. Beide bekamen ihn — die Farbtemperatur meldete 65 Kelvin. So ein Wert fällt in keinem Diagramm auf und verdirbt jede Auswertung still. Seither gilt: Ein Entity hat genau einen primären Messwert; alles Weitere steht unter dem Namen seiner Fähigkeit in den Attributen. Ein Regressionstest hält das fest.

Die Tests laufen gegen aufgezeichnete echte Antworten der Geräte, nicht gegen ausgedachte Beispiele. Ein selbst geschriebenes Beispiel bestätigt nur die Annahme, die man ohnehin hatte. Wichtig dabei: die Erwartung aus der Aufzeichnung ableiten statt Momentanwerte einzufrieren — sonst prüft der Test den Mitschnitt und nicht den Code. So wird aus dem Gen-1-Zählerstand von 28.396 Wattminuten im Test 473,27 Wh, und der Test weiß, warum.

Der Fernseher. webOS-Adapter selbst geschrieben, Pairing am Gerät bestätigt, seither werden Zustand, Lautstärke, Quelle und Stummschaltung live gelesen. Zwei Lehren: Der Client-Key, der beim Pairing entsteht, muss zuerst gesichert werden. Beim ersten Versuch hing er an einer Folgeabfrage, die mit 401 scheiterte — und war weg. Er entsteht aus einer körperlichen Handlung am Gerät und ist nicht beliebig oft zu haben. Und: Rechte sind Entwurf, nicht Fehlersuche. Der Adapter erbittet nur die Berechtigungen, zu denen HomeOS eine Fähigkeit kennt; einen Hinweis einblenden, der von selbst verschwindet, darf er — einen Alert, der stehen bleibt, nicht.

Nebenbei hat der Fernseher eine Fehlannahme aus meiner Geräteinventur aufgeklärt: Was ich für eine doppelte DHCP-Lease gehalten hatte, sind zwei Interfaces — LAN und WLAN — mit je eigener MAC. Dass die ARP-Tabelle meines Macs für beide dieselbe MAC zeigte, ist das übliche Verhalten eines Linux-Geräts, das ARP-Anfragen für alle seine Adressen über jedes Interface beantwortet. webOS ist Linux. Die Aufräumaufgabe „doppelte Lease" entfällt; das echte Thema sind zwei Anschlüsse, die beide antworten.

Ein Kommentar ist kein Zustand. Die ARP-Tabelle des Firewall-Exporters galt seit dem Netzwerk-Ausbau als eingeschaltet — in der Doku, im Compose-Kommentar, im Journal. Das Flag fehlte trotzdem; der Exporter loggte bei jedem Start arp collector disabled. Aufgefallen ist es erst, als die Geräte-Discovery dieselbe Quelle brauchte. Wer eine Einstellung dokumentiert, sollte im selben Zug prüfen, ob sie wirkt.

Was ausdrücklich nicht geht: Geschaltet wird nichts. Bis Freigabekette, Aktions-Allowlist und Audit stehen, erreicht kein API-Pfad ein Gerätekommando. Auch die neue Automations-Engine (WENN … UND … DANN, mit Haltezeit und Sperrfrist) darf ein Kommando beschreiben, aber nicht ausführen — die Ablehnung landet als Ereignis im Strom statt still zu verschwinden. Regeln werden abgeschaltet angelegt; Einschalten ist eine zweite Handlung.