Smart Home lokal · Teil 5 von 8
Zigbee im Alltag: Was nach dem Koppeln kommt
Anlernen dauert Sekunden. Danach kommen Bindungen, die Erfolg melden und nicht schalten, Fühler, die nur ganze Grad kennen, und eine Lampe, die 33 Stunden fehlt, ohne dass es auffällt.
Am Morgen nach dem großen Firmware-Update blieb die Küche dunkel. Der Bewegungsmelder war online, meldete jede Bewegung, und Zigbee2MQTT listete seine Bindung an die Deckenlampen unverändert auf. Nur ging das Licht nicht an. Im Flur war es umgekehrt: Der Melder schaltete sein Licht, meldete aber keine Bewegung mehr.
Damals hingen 25 Geräte an unserem Sonoff Dongle Plus MG24. Das Anlernen war selten das Problem.
Bewegungsmelder direkt an die Lampe
Im Flur und in der Küche schalten IKEA-Melder (TRÅDFRI E1745) ihre Lampen per Zigbee-Bindung, ohne Server. Der Melder schickt OnWithTimedOff, die Lampe zählt selbst herunter und dimmt sanft hoch.
Am ersten Tag schien das nicht zu funktionieren, obwohl Zigbee2MQTT jeden Schritt bestätigte. Die Geräteoptionen des Melders standen auf {}. Ohne occupancy_timeout hing er über zwei Stunden auf occupancy: on fest. Für ihn war der Raum durchgehend belegt, also schickte er bei neuer Bewegung kein neues Einschaltkommando. Seitdem gehört das zum Anlernen jedes IKEA-Melders:
zigbee2mqtt/bridge/request/device/options
{"id":"<Gerät>","options":{"occupancy_timeout":60}}
Bevor die Ursache gefunden war, hatte Claude die Bindung für unzuverlässig gehalten und ersatzweise eine Automation gebaut. Am nächsten Morgen zeigte das Protokoll beide am Werk:
+0 s Melder: occupancy=true, requested_brightness_percent=30
+0 s Flur: brightness=203 ← Automation, sofort auf 80 %
+0 s Flur: brightness=1 ← Bindung, beginnt sanft
+5 s Flur: brightness=203 ← Automation überschreibt das Hochdimmen
Die Automation ist seitdem abgeschaltet. Die Regel: nie Bindung und Automation auf dieselbe Lampe.
Eine zweite Falle erwischte uns zweimal: Zigbee2MQTT antwortet mit status: ok, auch wenn nur ein Teil gelungen ist:
{"clusters":["genLevelCtrl"], "failed":["genOnOff"], "status":"ok"}
genLevelCtrl allein bewirkt nichts, denn die Lampe steht auf execute_if_off: false und verwirft Helligkeitsbefehle, solange sie aus ist. Seitdem lesen wir failed mit und zählen: Ein funktionierender Melder hat bei uns vier Bindungseinträge.
Batteriegeräte hören nur im Aufwachmoment zu
Ein Batteriegerät wacht kurz auf, sendet und schläft weiter. Bindungen, Optionen, Meldeschwellen, Firmware: Jeder Befehl erreicht es nur in diesen Sekunden. ROUTE_ERROR_INDIRECT_TRANSACTION_EXPIRY heißt deshalb nicht „defekt“, sondern: Das Gerät hat die bereitliegende Nachricht nie abgeholt.
Beim Melder hilft Wiederholen, während jemand vor ihm mit der Hand wedelt. Beim RODRET-Funkschalter scheiterten 32 blinde Bindungsversuche mit „Delivery failed“, weil er nur für einen Bruchteil einer Sekunde aufwacht. Die Lösung war, auf den Tastendruck zu warten:
# blockiert bis zur ersten Nachricht des Geräts, also bis zum Tastendruck
M=$(mosquitto_sub -t 'zigbee2mqtt/Schalter 1' -C 1)
# unmittelbar danach den Bindungsbefehl absetzen
# (zigbee2mqtt/bridge/request/device/bind)
Beide Cluster saßen in der ersten Runde. Dieses Muster nutzen wir seither für jede Konfiguration an Batteriegeräten. Was weckt, hängt vom Modell ab: beim RODRET der Tastendruck, beim Bodenfeuchte-Sensor der Geräteknopf, beim IKEA-Melder Bewegung.
Beim Melder ausdrücklich nicht der Knopf. Am 29.08. notierte Claude, ein Druck auf den Knopf im Batteriefach wecke ihn zuverlässiger als Vorbeigehen. Am nächsten Morgen setzte genau dieser Druck den Melder zurück, und er verließ das Netz. Der Knopf löst Touchlink aus, dazu mehr beim Kopplungsfenster.
Firmware: was sie brachte und was sie kostete
Mitte September liefen sechs unserer damals acht Hue-Lampen mit Firmware von 2020. Hue-Lampen sind Router, und ein Router mit altem Zigbee-Stack zieht die Funkwege aller Geräte hinter ihm mit. Also aktualisierten wir alle acht nacheinander, Dekolicht zuerst, Küche, Flur und Eingang zuletzt: rund 36 Minuten je Lampe, fünf Stunden insgesamt, danach alle auf 1.122.2.
Der Nutzen: In den fünf Stunden stand eine einzige Fehlerzeile im Protokoll, am Vortag waren es dutzende pro Stunde. Die Probe danach: 16 Schaltbefehle, 16 Quittungen. Ob das auch die Ausfälle der Eingangslampe erklärt (siehe unten), wissen wir nicht. Gerade sie hatte vorher schon den neuesten Stand im Haus.
Die Batteriegeräte wollten wir zunächst auslassen: Die Aktualisierung dauert lange, kostet Batterie, und unsere Heizungssteuerung setzt ein bestimmtes Verhalten der Thermostat-Firmware voraus. Am Nachmittag fingen wir trotzdem an. Der erste Versuch am RODRET endete mit Device didn't respond to OTA request. Mit dem Lauschtrick ging es: Beim Wohnzimmerthermostat kam nach zwölf Minuten ein Lebenszeichen, das Skript stieß die Aktualisierung im selben Moment an. Eine Stunde später war sie durch, die Heizung lief währenddessen normal.
Beim Sonoff TRVZB (1.3.0 auf 1.4.4) blieb alles Tragende erhalten, geprüft per Sicherung vorher und Vergleich nachher. Der Gewinn: vier Felder, die vorher nicht lesbar waren, etwa smart_temperature_control. Das Verhalten zwischen auto und heat, auf das die Steuerung baut, war unverändert (mehr dazu in Teil 3).
In der Nacht folgten die übrigen Batteriegeräte, darunter die drei IKEA-Melder von 2.0.022 (2019) auf 24.4.5 (2022). Einen messbaren Gewinn bei ihnen haben wir nicht festgehalten. Den Preis sahen wir am Morgen.
Die Bindungsliste ist nur die Sicht von Zigbee2MQTT
Der Sprung hatte bei zwei Meldern Einträge aus der Bindungstabelle gelöscht, und nicht dieselben. Die letzte Schaltung der Küchenlampen lag 90 Sekunden vor dem Start der Aktualisierung des Küchenmelders. Zigbee2MQTT zeigte trotzdem alle Einträge an. Die Liste ist seine eigene Buchführung, nicht der Speicher des Geräts.
Im Flur trennte eine Probe „erkennt nichts“ von „meldet nichts“: Lampe von Hand ausschalten, durch den Flur gehen. Das Licht ging an, bei null Meldungen in Zigbee2MQTT. Sensor und Funk waren in Ordnung, nur der Weg zum Koordinator fehlte.
Beim Neubinden des Flurmelders fiel das übliche Startsignal aus, sein Meldekanal war ja das Kaputte. Also lauschte das Skript auf die Flurlampe: Schaltet sie, hat der Melder eben gesendet. In der Küche gingen beim ersten Anlauf sechs von sechs Bindungen daneben, beim dritten saßen alle.
Dann die zweite Überraschung: Die Bindung an die Zigbee-Gruppe der Küchenlampen meldete Successfully bound cluster 'genOnOff' to 'Kueche Decke', und das Licht blieb dunkel. Die Gruppe selbst war intakt, direkt geschaltet gingen beide Lampen an. Gelöst hat es der Weg, der im Flur trägt: jede Lampe einzeln, Gerät an Gerät. Beide gingen in derselben Sekunde an und nach 180 Sekunden aus. Den Versatz, dessentwegen wir ursprünglich die Gruppe gewählt hatten, gab es nicht.
Meldeschwellen: die flache Linie, die keine war
Am 21.09. verlief die Temperatur im Gästezimmer von 14:31 bis 15:20 schnurgerade. Nicht das Zimmer stand still, sondern der Fühler: Er hatte die nächste ganze Gradmarke nicht erreicht.
| Fühler | Modell | Meldeschwelle |
|---|---|---|
| Eingang, Küche, Schlafzimmer, Wohnzimmer | SNZB-02B | 0,2 K |
| Gästezimmer | SNZB-02P | 1,0 K |
| Essbereich | SNZB-02D | 1,0 K |
Schlimmer: Seit dem Vortag regelte das Gästezimmerventil nach diesem Fühler (mehr in Teil 3). Es erfuhr die Raumtemperatur in Ganzgradstufen. Die Umstellung:
zigbee2mqtt/bridge/request/device/configure_reporting
{"id":"Klima Gästezimmer","endpoint":1,
"cluster":"msTemperatureMeasurement","attribute":"measuredValue",
"minimum_report_interval":30,"maximum_report_interval":1800,
"reportable_change":20}
reportable_change zählt in Hundertstel Grad, 20 sind 0,2 K. Das Feld endpoint ist Pflicht. Fehlt es, antwortet Zigbee2MQTT nur mit Invalid payload, ohne das fehlende Feld zu nennen; Claude fand es erst im Quelltext (bridge.js). Beide Fühler erwischten wir mit dem Lauschtrick beim ersten Anlauf. Die Wirkung war sofort sichtbar: 20,7 → 20,8 °C, ein Schritt, der vorher unsichtbar geblieben wäre.
Verfügbarkeit: 33 Stunden weg, und niemand merkte es
Am Abend des 12.09. ging das Licht am Eingang nicht an. Der Melder war es nicht: Er hatte den ganzen Tag über gemeldet, und die Automation, die dort schaltet, hatte alles richtig gemacht. 97 Funkbefehle an die Lampe scheiterten an dem Tag mit „Delivery failed“, darunter vier Einschaltbefehle nach Einbruch der Dunkelheit. Als sie 19 Sekunden nach dem letzten verlorenen Befehl zurückkam, blieb sie wegen power_on_behavior: off dunkel. Ob sie ausgesteckt war, bleibt offen: „kein Strom“ und „nicht erreichbar“ sehen im Protokoll gleich aus.
Die eigentliche Lücke: Home Assistant zeigte 33 Stunden lang „aus“ an. light.turn_on schreibt nach MQTT und gilt damit als erledigt. Seit dem 13.09. steht in der Zigbee2MQTT-Konfiguration:
availability:
enabled: true
active:
timeout: 10 # Router werden alle 10 Minuten angepingt
passive:
timeout: 1500 # Batteriegeräte gelten nach 25 h Schweigen als offline
Batteriegeräte werden nur beobachtet, ein Ping würde Batterie kosten. 25 Stunden sind großzügig: Die längste beobachtete Funkstille war ein Melder über Nacht, rund 11 Stunden. Die Einstellung verlangt einen Neustart des Containers.
Der erste Durchlauf fand sofort etwas: Decke Schlafzimmer war offline, 95 Fehlschläge standen im Protokoll, der erste vom 29.08. Zigbee2MQTT protokolliert jeden verlorenen Befehl als error, aber Containerprotokolle liest niemand. Jetzt steht so eine Lampe auf unavailable.
Außerdem fasst die Automation am Eingang nach. Bis zu drei Versuche, nach jedem wartet sie, bis die Lampe selbst den neuen Zustand meldet:
- repeat:
sequence:
- action: light.turn_on
target:
entity_id: light.lampe_eingang
continue_on_error: true
- wait_template: "{{ is_state('light.lampe_eingang', 'on') }}"
timeout: "00:00:12"
continue_on_timeout: true
until:
- condition: or
conditions:
- condition: state
entity_id: light.lampe_eingang
state: "on"
- condition: template
value_template: "{{ repeat.index >= 3 }}"
12 Sekunden, weil Zigbee2MQTT selbst bis zu 10 Sekunden lang wiederholt. Am 12.09. hätte der zweite Versuch die Lampe erwischt. Dieselbe Schleife sitzt im Ausschaltzweig, dazu mode: queued, damit kein Ausschaltbefehl verfällt, während ein Durchlauf läuft. Gegen eine tatsächlich unerreichbare Lampe getestet: 37 Sekunden, dann Ende.
Hue-Lampen ohne Bridge umziehen
Die Hue-Lampen hingen an einer Bridge 1.0 ohne Sicherheitsupdates. Der ursprüngliche Plan: die Bridge übergangsweise in Home Assistant einbinden, die Lampen später umziehen. Wir haben widersprochen. Beim Umzug hätten sich alle Entitäts-IDs geändert und jede Automation auf light.hue_… wäre gebrochen: doppelte Arbeit mit eingebautem Bruch.
Eine Hue Lux kostete über eine Stunde. Sechs Anlernversuche über den Lichtschalter brachten null Beitrittsversuche im Protokoll, auch nach dem Löschen in der Hue-App, bei abgeschalteter Bridge und in 30 cm Abstand zum Koordinator. Die Rücksetzung über die Seriennummer auf dem Sockel, bei geöffnetem Netz, wirkte nach sechs Sekunden:
zigbee2mqtt/bridge/request/action
{"action":"philips_hue_factory_reset","params":{"serial_numbers":["<vom Sockel>"]}}
Das Löschen in der App setzt eine Lampe nur zurück, wenn die Bridge sie in diesem Moment erreicht. Sonst verschwindet nur der Eintrag, und das sieht aus wie ein gelungener Reset. Bei Hue ist die Seriennummer deshalb unser erster Griff.
Der Stick, der sich im Sekundentakt zurücksetzte
Bevor das erste Gerät angelernt war, kostete uns der Stick über zwei Stunden: rund 260 Kernel-Meldungen pro Minute, unbind/bind auf usb-serial, jeder Zugriff endete mit bad file descriptor. Verdächtigt wurde die Firmware 8.0.2, die in Fehlerberichten als problematisch gilt. Zweimal neu geflasht, dann vier USB-Steckplätze, Hub, Verlängerung, Energiesparen, ModemManager. Alles ohne Wirkung.
Die Ursache lief auf demselben Server: das Mining-Programm cgminer. Es sucht auf allen USB-Anschlüssen nach Minern, und der MG24 meldet sich als CP210x (10c4:ea60), ein Chip, der auch in Miner-Hardware steckt. cgminer probierte den Stick durch und setzte ihn dabei jedes Mal zurück. Der Hinweis stand früh in /etc/udev/rules.d/01-cgminer.rules. Claude hatte die Datei gesehen und verworfen, weil sie nur Zugriffsrechte setzt.
Der Beweis: cgminer mit kill -STOP angehalten, null Meldungen; fortgesetzt, wieder rund 200. Seitdem ist cgminer per systemd-Ergänzung auf seinen eigenen Miner beschränkt (--usb 1:5). Die verdächtigte Firmware läuft einwandfrei.
Namen, Kennungen, Kopplungsfenster
Umbenennen ändert keine Entitäts-IDs. Zigbee2MQTT meldet ein Gerät bei Home Assistant an, bevor man es umbenennen kann, und die IDs entstehen aus der IEEE-Adresse (climate.0x…). Beim zweiten Thermostat haben wir 30 Entitäten einzeln über config/entity_registry/update nachgezogen.
Aus Umlauten werden Grundbuchstaben: „Büro“ wird buro, „Küche“ wird kuche. Nach dem Anlegen die tatsächliche ID auslesen, nie raten.
IDs hängen an Matter. Eine neue ID erzeugt in der Matter-Brücke einen neuen Endpunkt, und Alexa verliert das Gerät (mehr in Teil 1). Die IDs des Wohnzimmerthermostats haben wir erst geändert, als ohnehin eine Gerätesuche anstand. Bei einer WiZ-Lampe haben wir nur das Gerät umbenannt; für Alexa blieb es dasselbe Gerät.
Das Kopplungsfenster. permit_join nimmt höchstens 254 Sekunden, ein höherer Wert wird abgelehnt statt gekappt. Beim zweiten Thermostat öffneten wir gezielt über einen Router im Zielraum und schlossen danach mit {"time": 0}:
zigbee2mqtt/bridge/request/permit_join
{"time": 254, "device": "<Router im Zielraum>"}
Ein Endgerät behält den Vermittler, den es beim Beitritt findet. Den Eingangsmelder hatten wir am Server gekoppelt; seine Verbindungsgüte fiel an einem Tag von 108 auf 36, während die Lampe einen Meter daneben bei 184 lag. Direkt an einer Lampe zu koppeln, geht aber auch nicht: Der Knopf am IKEA-Melder löst Touchlink mit der nächstgelegenen Lampe aus, und beide verlassen das Netz. Darauf kam Claude erst durch unsere Beschreibung, was der Melder nach dem Knopfdruck tut. Am Eingang schaltet seitdem eine Automation.
Was wir mitnehmen
status: okist kein Beweis.failedmitlesen und nach jedem Firmware-Sprung jede Bindung im Betrieb testen.- IKEA-Melder: erst
occupancy_timeout, dann binden. Nie Bindung und Automation auf dieselbe Lampe. - Batteriegeräte im Aufwachmoment erwischen:
mosquitto_sub -C 1auf das Gerätetopic, dann sofort senden. Den IKEA-Melder weckt Bewegung, nicht der Knopf. - Meldeschwellen prüfen, bevor ein Ventil danach regelt. Bei
configure_reportingdenendpointnicht vergessen. availabilityeinschalten und wichtige Lichtautomationen auf die Rückmeldung der Lampe warten lassen.- Bei USB-Problemen zuerst fragen, wer sonst auf den Bus zugreift, bevor man Firmware flasht.