EM2019WSP11/Implementierungsdetails

Aus Verteilte Systeme - Wiki
Zur Navigation springen Zur Suche springen

MQTT

Zigbee2mqtt nutzt für jedes Gerät ein Topic mit der Struktur "zigbee2mqtt/<GeräteID>", die Daten werden dabei im JSON-Format veröffentlicht. Beispielsweise würde die Information eines Thermometers folgendermaßen codiert werden.

{"temperature":21.4}

Der Wassermelder wurde mit zigbee2mqtt eingebunden und nutzt entsprechend das Format. Der BME680 ist kein Zigbee-Gerät und ist dementsprechend nicht auf diese Struktur angewiesen. Um die Implementierung möglichst übersichtlich zu gestalten, wurde sich trotzdem daran orientiert. Die Daten werden aber über das Topic /bme680/json veröffentlicht. Um ein Gerät, das seine Daten mit Hilfe von MQTT kommuniziert, in openHAB nutzen zu können, sind sowohl ein Thing als auch Items nötig, die Verbindung wird über Channel hergestellt. Hier zunächst exemplarisch die Thing-Definition des BME680.

Thing mqtt:topic:bme680 "Air Quality Sensor" (mqtt:systemBroker:embedded-mqtt-broker){
    Channels:
        Type number : gas "Luftqualität" [stateTopic="/bme680/json", transformationPattern="JSONPATH:$.gas"]
}

In der ersten Zeile werden folgende Dinge spezifiziert:

  • Name des Things, um von Item angesprochen zu werden
  • Beschreibung, die in der Paper UI angezeigt wird
  • genutzter MQTT-Broker, in diesem Fall der Embedded Broker von openHAB selbst

Dann kann eine Reihe von Channels angegeben werden. Für jede Eigenschaft des JSON-Strings, die genutzt werden soll, wird einer erstellt. Ein Channel benötigt folgende Informationen:

  • ein von openHAB unterstützer Typ
  • Name des Channels
  • Beschreibung
  • MQTT-Topic und genutzte Eigenschaft des JSON-Strings

Ein Item hat folgende Struktur.

Number Gas_Value "Gas [%d]" <gas> {channel="mqtt:topic:bme680:gas"}

Es werden definiert:

  • Typ des Items
  • Name des Items
  • Beschreibung, die in der Paper UI angezeigt wird
  • Name des Icons der Paper UI
  • Der Channel für die Verbindung zum Thing

Der Channel muss nicht nochmal extra spezifiziert werden und ist sofort aktiv.

Scripting

Als Programmiersprache wird Jython verwendet, mehr dazu kann im Bereich Grundlagen gefunden werden. Das folgende Beispiel spezifiziert das Ereignis, dass das Fenster geöffnet wird. Regeln für andere Ereignisse würden sich in der genauen Implementierung natürlich davon unterscheiden, aber derselben Struktur folgen.

@rule("window opened")
@when("Item ZWaveNode004DCHZ110DoorWindowSensor_DoorWindowStatus changed from CLOSED to OPEN")
def window_opened(event):
    if (ir.getItem("Leak_State").state == OPEN):
        events.sendCommand("Lampe_Color", "240,100,100")
    else:
        events.sendCommand("Lampe_Color", "120,100,100")

Am Anfang wird immer mit Hilfe eines sogenannten Decoraters definiert, dass es sich bei der nachfolgenden Funktion um eine Regel handelt und ein Name vergeben.

@rule("window opened")

Als nächstes wird für die Regel mit einem weiteren Decorater ein Auslöser festgelegt. Im diesem Fall ändert sich der Zustand des Items von geschlossen zu geöffnet.

@when("Item ZWaveNode004DCHZ110DoorWindowSensor_DoorWindowStatus changed from CLOSED to OPEN")

Dann wird eine Funktion definiert, die nach dem Auslösen des Ereignisses ausgeführt wird. Diese bekommt immer ein Argument event übergeben, mit dem im Funktionsrumpf verschiedene Aktionen durchgeführt werden können.

def window_opened(event):

Am Ende folgt dann der eigentliche Funktionsrumpf. Bei diesem Beispiel werden entsprechend der Tabelle aus dem Abschnitt Feindesign die beiden weiteren Eigenschaften abgefragt und entsprechend die Farbe der Hue-Lampe geändert. Dabei kann man sehen, wie das Argument event der Funktion verwendet wird, um den Befehl zu senden. Die anzunehmende Farbe wird bei openHAB dabei als HSB-Wert angegeben. Der erste Wert gibt dabei eine Gradzahl an, die die Farbe auf dem Farbkreis definiert. Die weiteren Werte geben die Sättigung und Helligkeit der Farbe an.

if (ir.getItem("Leak_State").state == OPEN):
        events.sendCommand("Lampe_Color", "240,100,100")
    else:
        events.sendCommand("Lampe_Color", "120,100,100")