nomos system nomos system

Geräteprofil · MQTT-Vorlagen

MQTT-Vorlagen für eigene Geräte

Diese Profile sind Vorlagen, keine Gerätetreiber. Sie sprechen kein bestimmtes Gerät an, sondern legen fest, welche Topics nomos liest und schreibt. Damit daraus ein funktionierendes Gerät wird, muss auf der anderen Seite etwas sein, das sich an dieselben Topics hält:

Wer eine Vorlage importiert und nichts weiter tut, bekommt ein Gerät, das in der App sichtbar ist und nichts tut. Das ist kein Fehler, sondern der Zweck: die Vorlage ist die nomos-Hälfte der Verbindung.

Das Schema

Alle Vorlagen nutzen dieselbe Struktur, dieselbe, die auch Tasmota verwendet. <Topic> ist das MQTT-Topic, das beim Anlegen des Geräts eingetragen wird:

Richtung Topic Beispiel
nomos liest einen Wert stat/<Topic>/<WERT> stat/wohnzimmer_lampe/POWER
nomos schreibt einen Befehl cmnd/<Topic>/<BEFEHL> cmnd/wohnzimmer_lampe/POWER
Lebenszeichen tele/<Topic>/LWT Online bzw. Offline

Einrichtung

  1. In den nomos-Einstellungen unter Skills → MQTT den Broker eintragen, falls das noch nicht geschehen ist
  2. Skills → Add-ons: die passende Vorlage importieren
  3. Gerät anlegen und ein MQTT-Topic vergeben — ein Name, den sonst niemand verwendet, z. B. wohnzimmer_lampe
  4. Die Gegenstelle einrichten, siehe Mit Node-RED zum Leben erwecken

Nutzlasten

Die Nutzlast ist immer der nackte Wert, kein JSON:

Datentyp Was nomos akzeptiert Was nomos sendet
Ja/Nein 1/0, ON/OFF, true/false, Online/Offline, open/close 1 oder 0
Zahl 21.5, 80 — Punkt als Dezimaltrennzeichen dieselbe Schreibweise
Text beliebig der gewählte Wert aus der Liste

Werte sollten retained veröffentlicht werden. Sonst steht das Gerät in nomos nach einem Neustart leer da, bis sich der Wert das nächste Mal ändert.

Mit Node-RED zum Leben erwecken

Für ein schaltbares Gerät braucht es drei Knoten:

  1. mqtt in auf cmnd/<Topic>/POWER — hier kommt an, was nomos schalten will (1 oder 0).
  2. Ein Knoten, der das Gerät tatsächlich schaltet — je nach Gerät ein http request, ein TCP-Knoten, eine Palette des Herstellers.
  3. mqtt out auf stat/<Topic>/POWER, retained — die Rückmeldung an nomos.

Entscheidend ist der dritte Schritt: nomos glaubt nur dem, was auf stat/… zurückkommt. Ein Flow, der nur Befehle entgegennimmt, lässt den Schalter in der App zurückspringen.

Meldet das Gerät seinen Zustand von sich aus (Taster am Gerät, Rückmeldung des Herstellers), veröffentlichen Sie ihn auf demselben stat/…-Topic — dann stimmt die App auch nach einer Handbedienung.

Das Lebenszeichen liefert der Broker selbst: Im mqtt-broker-Knoten unter Birth, Close und Will jeweils das Topic tele/<Topic>/LWT eintragen, mit der Nutzlast Online für Birth und Offline für Close und Will. Danach zeigt nomos das Gerät als nicht erreichbar, sobald der Flow nicht mehr läuft.

Ein Beispiel zum Abwandeln

Der folgende Flow bedient die Vorlage Switch für ein Gerät, das sich über HTTP schalten lässt. Er ist ein Gerüst, kein fertiger Treiber: Die Stellen, die von Ihrem Gerät abhängen, sind im Flow markiert.

JSON zum Einfügen
[{"id":"nomos_mqtt_beispiel","type":"tab","label":"MQTT-Vorlage: Schalter","disabled":false,"info":""},{"id":"nomos_mqtt_beispiel_broker","type":"mqtt-broker","name":"nomos Broker","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"tele/wohnzimmer_lampe/LWT","birthQos":"0","birthRetain":"true","birthPayload":"Online","birthMsg":{},"closeTopic":"tele/wohnzimmer_lampe/LWT","closeQos":"0","closeRetain":"true","closePayload":"Offline","closeMsg":{},"willTopic":"tele/wohnzimmer_lampe/LWT","willQos":"0","willRetain":"true","willPayload":"Offline","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"nomos_mqtt_beispiel_in","type":"mqtt in","z":"nomos_mqtt_beispiel","name":"nomos schaltet","x":150,"y":100,"wires":[["nomos_mqtt_beispiel_settings"]],"topic":"cmnd/wohnzimmer_lampe/POWER","qos":"0","datatype":"auto-detect","broker":"nomos_mqtt_beispiel_broker","nl":false,"rap":true,"rh":0,"inputs":0},{"id":"nomos_mqtt_beispiel_tick","type":"inject","z":"nomos_mqtt_beispiel","name":"alle 30 Sekunden","x":150,"y":200,"wires":[["nomos_mqtt_beispiel_settings"]],"props":[{"p":"payload"}],"repeat":"30","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"","payloadType":"date"},{"id":"nomos_mqtt_beispiel_settings","type":"function","z":"nomos_mqtt_beispiel","name":"Einstellungen","x":370,"y":150,"wires":[["nomos_mqtt_beispiel_split"]],"func":"// Die beiden Zeilen, die zu Ihrer Anlage gehoeren:\nflow.set(\"topic\", \"wohnzimmer_lampe\");            // MQTT-Topic des Geraets in nomos\nflow.set(\"device\", \"http://192.168.1.50\");        // Adresse Ihres Geraets\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[]},{"id":"nomos_mqtt_beispiel_split","type":"switch","z":"nomos_mqtt_beispiel","name":"Befehl oder Abfrage?","x":580,"y":150,"wires":[["nomos_mqtt_beispiel_command"],["nomos_mqtt_beispiel_stateurl"]],"property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"cmnd/","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2},{"id":"nomos_mqtt_beispiel_command","type":"function","z":"nomos_mqtt_beispiel","name":"Befehl an das Geraet","x":800,"y":100,"wires":[["nomos_mqtt_beispiel_send"]],"func":"// nomos hat geschaltet: cmnd/<Topic>/POWER mit 1 oder 0.\n// ---- anzupassen: die Adressen, mit denen Ihr Geraet schaltet ----------------\nconst value = String(msg.payload).trim();\nconst on = value === \"1\" || value.toLowerCase() === \"on\" || value.toLowerCase() === \"true\";\n\nmsg.method = \"GET\";\nmsg.url = flow.get(\"device\") + (on ? \"/on\" : \"/off\");\nmsg.payload = \"\";\n// -----------------------------------------------------------------------------\n\nmsg.wanted = on ? 1 : 0;        // was nomos erwartet, fuer die Rueckmeldung\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[]},{"id":"nomos_mqtt_beispiel_send","type":"http request","z":"nomos_mqtt_beispiel","name":"schalten","x":1000,"y":100,"wires":[["nomos_mqtt_beispiel_publish"]],"method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[]},{"id":"nomos_mqtt_beispiel_stateurl","type":"function","z":"nomos_mqtt_beispiel","name":"Zustand abfragen","x":800,"y":200,"wires":[["nomos_mqtt_beispiel_read"]],"func":"// Regelmaessig nachsehen, was das Geraet wirklich tut - sonst stimmt die App nicht\n// mehr, sobald jemand am Geraet selbst schaltet.\n// ---- anzupassen: die Adresse, unter der Ihr Geraet seinen Zustand meldet -----\nmsg.method = \"GET\";\nmsg.url = flow.get(\"device\") + \"/status\";\n// -----------------------------------------------------------------------------\nmsg.payload = \"\";\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[]},{"id":"nomos_mqtt_beispiel_read","type":"http request","z":"nomos_mqtt_beispiel","name":"nachlesen","x":1000,"y":200,"wires":[["nomos_mqtt_beispiel_publish"]],"method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[]},{"id":"nomos_mqtt_beispiel_publish","type":"function","z":"nomos_mqtt_beispiel","name":"Rueckmeldung an nomos","x":1190,"y":150,"wires":[["nomos_mqtt_beispiel_out"]],"func":"// Antwort des Geraets in den Zustand uebersetzen, den nomos liest.\n// nomos glaubt nur dem, was auf stat/... zurueckkommt.\nconst topic = flow.get(\"topic\");\n\n// ---- anzupassen: wie Ihr Geraet seinen Zustand meldet ------------------------\n// Vorgesehen sind die ueblichen Formen: true/false, \"on\"/\"off\", 1/0, oder ein\n// JSON-Dokument mit einem Feld, das den Zustand traegt.\nconst FELD = \"on\";              // Name des Feldes, falls JSON zurueckkommt\n\nlet state = null;\nconst body = msg.payload;\nif (typeof body === \"object\" && body !== null) {\n    state = body[FELD];\n} else {\n    state = body;\n}\n// -----------------------------------------------------------------------------\n\nconst text = String(state).trim().toLowerCase();\nlet on;\nif (state === true || text === \"1\" || text === \"on\" || text === \"true\") { on = 1; }\nelse if (state === false || text === \"0\" || text === \"off\" || text === \"false\") { on = 0; }\nelse if (msg.wanted !== undefined) {\n    // Das Geraet hat nichts Verwertbares geantwortet. Nach einem Schaltbefehl gilt\n    // dann, was geschaltet wurde - beim naechsten Nachsehen wird es richtiggestellt.\n    on = msg.wanted;\n} else {\n    node.warn(\"Zustand nicht erkannt: \" + JSON.stringify(body));\n    return null;\n}\n\nreturn { topic: \"stat/\" + topic + \"/POWER\", payload: on, retain: true };\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[]},{"id":"nomos_mqtt_beispiel_out","type":"mqtt out","z":"nomos_mqtt_beispiel","name":"an nomos","x":1400,"y":150,"wires":[],"topic":"","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"nomos_mqtt_beispiel_broker"}]

Nach dem Import sind drei Dinge einzutragen:

  1. Im Knoten Einstellungen das MQTT-Topic des Geräts in nomos und die Adresse Ihres Geräts. Beide Zweige laufen durch diesen Knoten — er ist die einzige Stelle mit Ihren Daten.
  2. Im Knoten Befehl an das Gerät die beiden Adressen, mit denen Ihr Gerät ein- und ausschaltet, und im Knoten Zustand abfragen die Adresse, unter der es seinen Zustand meldet.
  3. Im Knoten Rückmeldung an nomos nur dann etwas, wenn Ihr Gerät seinen Zustand anders meldet als üblich. Erkannt werden true/false, on/off und 1/0 — als nackter Wert oder als Feld in einem JSON-Dokument.

Der Flow tut dreierlei: Er nimmt Befehle auf cmnd/… entgegen, er meldet den Zustand auf stat/… zurück, und er sieht alle 30 Sekunden nach, was das Gerät wirklich tut — damit die App auch dann stimmt, wenn jemand am Gerät selbst schaltet. Antwortet das Gerät auf einen Schaltbefehl nichts Verwertbares, gilt vorläufig der geschaltete Wert; das nächste Nachsehen stellt ihn richtig. Das Lebenszeichen setzt der Broker-Knoten, wie im Absatz davor beschrieben.

Für eine andere Vorlage bleibt das Gerüst dasselbe, es kommen nur Topics dazu — bei einem Dimmer etwa BRIGHTNESS, bei einer Beschattung POSITION und STOP.

Welche Vorlage welche Topics nutzt

Alle Vorlagen lesen zusätzlich tele/<Topic>/LWT als Erreichbarkeit.

Licht

Vorlage nomos liest nomos schreibt
Light Switch stat/<Topic>/POWER cmnd/<Topic>/POWER
Dimmer POWER, BRIGHTNESS POWER, BRIGHTNESS
Color Temperature POWER, BRIGHTNESS, CT POWER, BRIGHTNESS, CT
RGB POWER, BRIGHTNESS, RED, GREEN, BLUE dieselben

Schalten und Lüften

Vorlage nomos liest nomos schreibt
Switch POWER POWER
Fan POWER, FANSPEED POWER, FANSPEED

Beschattung, Türen, Schlösser

Vorlage nomos liest nomos schreibt
Window Covering POSITION, ANGLE POSITION, ANGLE, STOP
Door, Garage Door OPENED OPEN, CLOSE
Lock LOCKED LOCK, UNLOCK

Heizung

Vorlage nomos liest nomos schreibt
Thermostat (Heating) MODE, SETPOINT, POWER, dazu tele/<Topic>/STATUS mit den JSON-Feldern IsHeating, IsCooling, Temperature MODE, SETPOINT
Thermostat (Heating/Cooling) wie oben, zusätzlich SETPOINTCOOLING MODE, SETPOINT, SETPOINTCOOLING

Die Betriebsart ist eine Zahl: 0 Auto, 1 Heizen, 2 Kühlen, 3 Standby, 4 Eco, 5 Gebäudeschutz.

Sensoren (nur lesend)

Vorlage Topic
Temperature stat/<Topic>/TEMPERATURE
Humidity stat/<Topic>/HUMIDITY
CO2 stat/<Topic>/CO2
Light stat/<Topic>/LIGHT
Motion stat/<Topic>/MOTION
Contact stat/<Topic>/CONTACT
Binary stat/<Topic>/POWER
Smoke stat/<Topic>/SMOKE
Water stat/<Topic>/WATER
Rain stat/<Topic>/RAIN
Wind stat/<Topic>/WINDSTRENGTH
Power stat/<Topic>/POWER (W) und stat/<Topic>/ELECTRIC (kWh)
Alarm stat/<Topic>/ARMED und stat/<Topic>/ALARM

Multimedia

Vorlage nomos liest nomos schreibt
TV POWER, INPUT, VOLUME, MUTE POWER, VOLUME, MUTE, VOLUP/VOLDOWN, CHUP/CHDOWN, INPUT1–INPUT3, die Navigationstasten (UP, DOWN, LEFT, RIGHT, ENTER, RETURN, EXIT, HOME, MENU, GUIDE, INFO), die Farbtasten und die Ziffern 0–9
Blu-Ray POWER POWER, Transport (PLAY, PAUSE, STOP, NEXT, PREV, FFORWARD, REWIND, REPEAT), Navigation, Farbtasten, Ziffern
Multiroom POWER, VOLUME, MUTE, INPUT1–INPUT6 dieselben
Mute/Volume VOLUME, MUTE VOLUME, MUTE

Weitere

Vorlage nomos liest nomos schreibt
Camera MOTION UP, DOWN, LEFT, RIGHT, ZOOMIN, ZOOMOUT
Security System SECURITY SECURITY

Hinweise