WomoNET-Protokoll
Das WomoNET-Netzwerk verwendet MQTT als primäres Protokoll für die Kommunikation zwischen verschiedenen Geräten. Diese Einrichtung ermöglicht effizienten und flexiblen Datenaustausch innerhalb des Netzwerks.
Struktur
Die MQTT-Topics im WomoNET-Netzwerk sind systematisch in die folgenden Hauptkategorien gegliedert:
c (config)
conf (Konfiguration)
Dieses Topic speichert Konfigurationseinstellungen, einschließlich Benutzeroberflächeneinstellungen, Geräteparametern und anderen wichtigen Konfigurationen. Das Hauptmerkmal dieses Topics ist, dass die Einstellungen persistent sind, was bedeutet, dass sie auch nach einem Systemneustart erhalten bleiben.
- ui: Enthält UI-Layout von der WomoNET.app. Layouts werden als JSON für jedes verfügbare Layout geschrieben
- driver: Kann verwendet werden, um Konfigurationen für Treiber zu speichern
dev (Virtuelle Geräte, Auto-Discovery)
Dieses Topic ist für Treiber reserviert, um ihre Auto-Discovery-Konfiguration zu veröffentlichen. Die Konfigurationsdaten für die Geräteerkennung werden hier definiert, wie unten detailliert beschrieben.
s (state/Zustand)
Jeder MQTT-Client innerhalb des WomoNET-Netzwerks hat ein dediziertes Zustands-Topic, wo er Nachrichten veröffentlicht, die seinen aktuellen Zustand oder Daten widerspiegeln. Alle Daten müssen menschenlesbare UTF-8-Daten sein. Numerische Werte müssen als UTF-8-String gesendet werden. Dezimaltrennzeichen ist . (Punkt). Wir parsen mit Dart’s double.tryParse.
Zustandsupdates und Befehle sollten QoS 1 verwenden.
Struktur
Der Zustandsbaum ist wie folgt strukturiert: s/<client_id>/<device_id>/<object_id>/[set/]<state/value/command>, wobei:
client_idist die MQTT-Client-IDdevice_idist die Kennung des virtuellen Gerätsobject_idist die Objekteinheit eines Typ-Wertsset(optional) ist eine Konstante, die nur bereitgestellt wird, wenn dies ein Befehl iststate/value/commandist der tatsächliche Zustand, Wert oder Befehl
Offene Fragen
- TODO Fehlerbehandlung: Wir könnten
s/error/<dev-id>für Fehlermeldungen einführen - TODO Geräte gehen Offline: Last Will Messages für Clients. Verfügbarkeit für Gruppen aktiv pushen? Ideen:
- Behaltene Auto-Discovery-Nachrichten löschen
available_tfür jeden Auto-Discovery-Typ
Auto-Discovery
Die Konfigurationsdaten müssen als MQTT-Nachrichten in einem spezifischen JSON-Format veröffentlicht werden. Jede Entität benötigt einen eindeutigen Topic-Namen und eine JSON-Konfiguration. Das Topic-Format ist c/dev/<client_id>/<device_id>/<type>/<entity>, wobei:
<client_id>ist die MQTT-Client-ID (global eindeutig)<device_id>ist eine Kennung für das virtuelle Gerät (Treiber-Ebene). Diese ID muss für den Client eindeutig sein, um Kollisionen zu vermeiden<type>ist der Typ der Entität. Siehe unten für verfügbare Typen<entity>ist der Name der Entität. Er muss für alle Entitäten des gegebenen Typs dieses virtuellen Geräts eindeutig sein
Beim Veröffentlichen von Auto-Discovery-Konfigurationen muss das retain-Flag für die MQTT-Nachricht gesetzt werden.
Auto-Discovery ist anders organisiert als bei Home Assistant: Wir verwenden dev_id und dann type anstatt umgekehrt. Dies ermöglicht es uns, WidgetGroups in der App für jede dev_id zu verwenden.
Verfügbare Typen
toggle
Eine schaltbare Einheit, die ein- oder ausgeschaltet werden kann.
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der aktuelle Zustand publiziert wird, nur true und false sind erlaubt |
cmd_t | Topic, auf dem Befehle zum Setzen des Toggle-Zustands empfangen werden. false, 0, off (alle groß-/kleinschreibungsunabhängig) werden als false interpretiert, alles andere als true. Wenn allow_timed true ist, wird das Setzen dieses Werts einen laufenden Timer abbrechen |
allow_timed | true oder false, gibt an, ob der Wert zeitgesteuert ausgelöst werden kann, indem ein CSV-String geschrieben wird, der den Zustand und die Dauer in Millisekunden repräsentiert (z.B. true,5000, Ausgang für 5000 Millisekunden einschalten). Wenn der zeitgesteuerte Zustand bereits der gewünschte Zustand ist (z.B. true,5000 wird gesendet, aber der Zustand ist bereits true), wird der Befehl ignoriert |
actuator
Ein Aktuator, der in zwei Richtungen geschaltet werden kann, z.B. schieben/ziehen, vorwärts/rückwärts und hat auch einen neutralen Stopp-Zustand. Wichtig: Der Treiber muss sicherstellen, dass die Bewegung automatisch stoppt, wenn keine gültigen Nachrichten mehr empfangen werden.
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der numerische Wert des Aktuatorzustands publiziert wird. Kann 1 (schieben/vorwärts), 0 (neutral/stopp) oder -1 (ziehen/rückwärts) sein |
cmd_t | Topic, auf dem Befehle zum Setzen des Aktuatorzustands empfangen werden. Kann 1 (schieben/vorwärts), 0 (neutral/stopp) oder -1 (ziehen/rückwärts) sein. Wenn allow_timed true ist, wird das Setzen dieses Werts einen laufenden Timer abbrechen |
allow_timed | Optional (Standard: false). true oder false, gibt an, ob der Wert zeitgesteuert ausgelöst werden kann, indem ein CSV-String geschrieben wird, der den Zustand und die Dauer in Millisekunden repräsentiert (z.B. -1,5000, Richtung auf Ziehen für 5000 Millisekunden setzen). Wenn der zeitgesteuerte Zustand bereits der gewünschte Zustand ist (z.B. -1,5000 wird gesendet, aber der Zustand ist bereits -1), wird der Befehl ignoriert |
binary
Ein boolescher Sensor mit den Zuständen an und aus.
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der aktuelle Zustand publiziert wird, nur true und false sind erlaubt |
sensor
Ein Sensor, der einen Wert veröffentlicht.
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der Wert publiziert wird. Der Wert ist UTF-8 (z.B. 42.1234 oder heating) |
unit_of_measurement | Optional. Gibt die Einheit des Sensorwerts für Anzeigezwecke an. Beispiele sind °C für Temperatur, % für Luftfeuchtigkeit, m/s für Geschwindigkeit, kWh für Energie, etc. Wenn nicht angegeben, wird der Wert als einheitenlos behandelt. Verwende standardisierte Einheiten (SI), wann immer möglich, um Kompatibilität zu gewährleisten |
mode
Auswählbare Optionen für ein Dropdown-Menü.
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der aktuelle Modus publiziert wird. Der Wert ist ein UTF-8-String, der die aktuelle Auswahl darstellt (z.B. heat, cool, auto, etc.) |
cmd_t | Topic, auf dem Befehle zur Änderung des Modus empfangen werden. Der Wert sollte ein UTF-8-String sein, der einer der auswählbaren Optionen entspricht (z.B. heat, cool, off, etc.). HINWEIS: Für Übersetzungen könnten wir gängige englische Optionen definieren und Übersetzungen über eine Lookup-Tabelle bereitstellen. |
option_t | Topic, auf dem die Liste der verfügbaren Modi publiziert wird, bereitgestellt als JSON-Array von Strings (z.B. ["off", "heat", "cool", "auto"]). Benutzeroberflächen sollten die Reihenfolge der Optionen respektieren. Dieses Topic sollte mit gesetztem retain-Flag veröffentlicht werden |
slider
Ein steuerbarer Stufenwert (Schieberegler in der UI), der zwischen einem Minimal- und Maximalwert mit einer bestimmten Strittgröße geändert werden kann, z.B. zur Steuerung von Heizungs-/Kühltemperaturen, Lichtdimmern, Stromverbrauch, Ladegerätausgang, …
| Name | Beschreibung |
|---|---|
state_t | Topic, auf dem der aktuelle Wert publiziert wird |
cmd_t | Topic, auf dem Befehle zum Setzen des Zielwerts empfangen werden |
min_value | Der Minimalwert für den Schieberegler |
max_value | Der Maximalwert für den Schieberegler |
step_size | Die Größe eines Schritts, z.B. 0.5 |
unit_of_measurement | Optional. Gibt die Einheit des Schieberegler-Werts für Anzeigezwecke an. Beispiele sind °C für Temperatur, % für Prozent, A für Strom, W für Leistung, etc. Wenn nicht angegeben, wird der Wert als einheitenlos behandelt. Verwende standardisierte Einheiten (SI), wann immer möglich, um Kompatibilität zu gewährleisten |
Example Structure
c/
├── conf/
│ ├── ui/
│ │ ├── 1 = "{ layout JSON }"
│ │ ├── main = "{ layout JSON }"
│ │ └── heater_only = "{ layout JSON }"
│ └── driver/
│ ├── core-gpio = "{ driver configuration JSON }"
│ └── core-adc = "{ driver configuration JSON }"
└── dev/
├── womonet-core-123.../
│ ├── adc/
│ │ └── sensor/
│ │ ├── vin0 = "{'unit_of_measurement': 'V', 'state_t': 's/womonet-core-123.../adc/0/state'}"
│ │ ├── vin1 = "{'unit_of_measurement': 'V', 'state_t': 's/womonet-core-123.../adc/1/state'}"
│ │ └── ...
│ ├── extrelay/
│ │ └── toggle/
│ │ ├── relay0 = "{'state_t': 's/womonet-core-123.../extrelay/0/state', 'cmd_t': 's/womonet-core-123.../extrelay/0/set/state', 'allow_timed': true}"
│ │ ├── relay1 = "{'state_t': 's/womonet-core-123.../extrelay/1/state', 'cmd_t': 's/womonet-core-123.../extrelay/1/set/state', 'allow_timed': true}"
│ │ └── ...
│ ├── truma-d4e-651.../
│ │ ├── mode/
│ │ │ └── heat = "{'state_t': 's/womonet-core-123.../truma-d4e-651.../heat/state', 'cmd_t': 's/womonet-core-123.../truma-d4e-651.../heat/set/state', 'option_t': 's/womonet-core-123.../truma-d4e-651.../heat/options'}"
│ │ ├── sensor/
│ │ │ ├── current_temp = "{'state_t': 's/womonet-core-123.../truma-d4e-651.../current_temp/state'}"
│ │ │ └── boiler_temp = "{'state_t': 's/womonet-core-123.../truma-d4e-651.../boiler_temp/state'}"
│ │ └── slider/
│ │ └── target_temp = "{'state_t': 's/womonet-core-123.../truma-d4e-651.../target_temp/state', 'cmd_t': 's/womonet-core-123.../truma-d4e-651.../target_temp/set/state', 'min_value': 16, 'max_value': 36, 'step_size': 0.5}"
│ └── ...
└── womonet-power-524.../
├── toggle/
│ └── pump = "{'state_t': 's/womonet-power-524.../pump/state', 'cmd_t': 's/womonet-power-524.../pump/set/state'}"
├── actuator/
│ ├── step = "{'state_t': 's/womonet-power-524.../step/state', 'cmd_t': 's/womonet-power-524.../step/set/state', 'allow_timed': true}"
│ ├── awning = "{'state_t': 's/womonet-power-524.../awning/state', 'cmd_t': 's/womonet-power-524.../awning/set/state'}"
│ ├── valve0 = "{'state_t': 's/womonet-power-524.../valve0/state', 'cmd_t': 's/womonet-power-524.../valve0/set/state', 'allow_timed': true}"
│ └── valve1 = "{'state_t': 's/womonet-power-524.../valve1/state', 'cmd_t': 's/womonet-power-524.../valve1/set/state', 'allow_timed': true}"
└── ...
s/
├── womonet-core-123.../
│ ├── adc/
│ │ ├── 0/
│ │ │ └── state = "1.33"
│ │ ├── 1/
│ │ │ └── state = "0.452"
│ │ └── ...
│ ├── extrelay/
│ │ ├── 0/
│ │ │ ├── state = "ON"
│ │ │ └── set/
│ │ │ └── state (writable only, no retain)
│ │ ├── 1/
│ │ │ ├── state = "OFF"
│ │ │ └── set/
│ │ │ └── state (writable only, no retain)
│ │ └── ...
│ ├── truma-d4e-651.../
│ │ ├── heat/
│ │ │ ├── state = "heating"
│ │ │ ├── options = "[\"off\", \"heating\", \"venting\"]"
│ │ │ └── set/
│ │ │ └── state (writable only, no retain)
│ │ ├── current_temp/
│ │ │ └── state = "18.62"
│ │ └── target_temp/
│ │ ├── state = "22.0"
│ │ └── set/
│ │ └── state (writable only, no retain)
│ └── ...
└── womonet-power-524.../
├── pump/
│ ├── state = "ON"
│ └── set/
│ └── state (writable only, no retain)
├── step/
│ ├── state = "0"
│ └── set/
│ └── state (writable only, no retain)
└── ...
