Zigbee2MQTT Konfiguration
Übersicht
Zigbee2MQTT (z2m) ist eine Bridge zwischen dem Zigbee-Funknetz und dem MQTT-Broker. Es übernimmt ausschließlich Protokollübersetzung und Netz-Management. Die Automationslogik liegt im IO-Broker. Der Coordinator ist ein Sonoff Dongle-Max (Silicon Labs EFR32MG21, EmberZNet-Firmware), angebunden per TCP über das interne Netz.
Coordinator
| Gerät | Sonoff Dongle-Max |
| Protokoll | ember (EmberZNet) |
| Adresse | tcp://zb-dongle-max.mqtt.p21.net:6638
|
| Baudrate | 115200, rtscts: false |
MQTT
| Broker | zentraler Broker, internes Netz |
| Base-Topic | zigbee
|
| Protocol | MQTT 3.1.1 (Version 4) |
| Retain | deaktiviert (force_disable_retain: true)
|
Bridge-State wird automatisch auf zigbee/bridge/state publiziert
({"state":"online"} / {"state":"offline"}), nutzbar als LWT-Ersatz im IO-Broker.
Availability
| Aktive Geräte (netzbetrieben) | Timeout 3 min, Backoff aktiv, Pause bei >120 min |
| Passive Geräte (Batterie) | Timeout 240 min |
OTA-Updates
Automatische Update-Checks sind deaktiviert (disable_automatic_update_check: true).
Geräte-initiierte Anfragen werden von z2m mit "kein Image verfügbar" beantwortet,
kein Kontakt zu Drittservern. Manuelle Prüfung bei Bedarf per MQTT:
zigbee/bridge/request/device/ota_update/check
{"id": "friendly_name_des_geraets"}
Logging
Console-Logging abgeschaltet, nur File-Logging aktiv. Entlastet
den Docker-Logger bei den minütlichen z2m-Statusmeldungen erheblich. In der
configuration.yaml:
advanced:
log_output:
- file
Schlüsseldaten (Netzwerk)
Network Key, PAN ID und Extended PAN ID liegen im Klartext in
/var/www/bsp12-zigbee2mqtt/z2m-data/configuration.yaml.
Diese Datei ist sicherheitsrelevant und darf nicht öffentlich zugänglich sein.
TODO: Backup läuft über dirvish.
Zigbee2MQTT ↔ ioBroker: kritische Einstellungskombination
Symptom
Beim Setzen eines Wertes über Zigbee (beobachtet an occupied_heating_setpoint
eines SONOFF TRVZB) erscheint im ioBroker zuerst das Kommando ohne ACK, dann der
alte Wert mit ACK und erst danach der neue Wert mit ACK.
Ursache
Zwei z2m-Mechanismen greifen ineinander:
advanced.last_seen != disable— jeder empfangene Frame löst überonLastSeenChanged→publishEntityStateeinen Publish aus. Auch derwriteRsp, mit dem das Gerät das Schreiben quittiert.advanced.cache_state: true—publishEntityStatemischt den kompletten gecachten Zustand in jedes Payload.
Der writeRsp trifft ein, bevor convertSet zurückkehrt und den neuen Wert
in den Cache schreibt. Der last_seen-Publish transportiert deshalb den alten Wert.
Erst danach folgt der optimistische Publish mit dem neuen.
Nicht die Ursache und ohne Wirkung:
optimistic: false— der Geräte-Report folgt ohnehin ~10 ms später, die Reihenfolge alt→neu bleibt.debounce/throttle— greifen nur inreceive.tsfür Nachrichten vom Gerät. last_seen- und Set-Publishes laufen daran vorbei.
Korrekte Einstellung
advanced: last_seen: ISO_8601 cache_state: false availability: enabled: true
| Einstellung | Wirkung |
|---|---|
cache_state: false | Behebt das Problem. Publishes enthalten nur noch die tatsächlich geänderten Attribute. Der ioBroker aggregiert sie: Datenpunkte behalten ihren Wert, bis sie überschrieben werden. |
last_seen: ISO_8601 | Kann anbleiben. Wird für die „Last seen"-Spalte im z2m-Frontend und für die Adapter-Option alwaysUpdateAvailableState gebraucht.
|
availability.enabled | Liefert das available-Feld im Objektbaum. Ohne das zeigt der Adapter alle Geräte als offline. Einzige brauchbare Strategie für Aktoren (aktives Pingen, Default 10 min).
|
Folgen und Randbedingungen
cache_state_send_on_startuphängt ancache_stateund greift nicht mehr. Bestehende Datenpunkte behalten ihre Werte; nur frisch angelegte bleiben leer, bis das Gerät das Attribut meldet. Notfalls mit.../getnachhelfen.ts/lcder Datenpunkte werden dadurch aussagekräftiger: vorher hat jeder Full-State-Publish den Zeitstempel aller ~40 Datenpunkte hochgesetzt.- z2ms interner Cache bleibt unberührt —
state.set()läuft inpublishEntityStatevor dercache_state-Abfrage. Frontend undfiltered_cachearbeiten unverändert. last_seen: disablelöst das Symptom ebenfalls, kostet aber die Frontend-Spalte und legtalwaysUpdateAvailableStatestill. Nicht empfohlen.
Diagnose bei Wiederauftreten
log_level: debug setzen, Wert ändern, im Log die MQTT publish-Zeilen um den
writeRsp herum ansehen. Publishes ohne elapsed-Feld stammen nicht aus
dem Empfangspfad (receive.ts), sondern aus dem last_seen- oder Set-Pfad. Das
ist das Unterscheidungsmerkmal.
Geräte-Strategie
Netzbetriebene Geräte (Router) zuerst pairen, danach Endgeräte (Batterie).
Friendly Names nach Schema: raumname_funktion, z.B. wohnzimmer_heizung.
- Setpoint-Steuerung und Zeitpläne ausschließlich über IO-Broker
- Tuya-TRVs im Modus
heat, interner Schedule deaktiviert
Für ME167-Thermostate (Tuya TS0601): kein nativer externer Sensor-Support. Externe Temperaturregelung vollständig in IO-Broker implementieren.
Metadaten abrufen (ohne Neustart)
mosquitto_pub -h broker.mqtt.p21.net -t "zigbee/bridge/request/devices" -m ""
Antwort auf: zigbee/bridge/devices
