Jython

13. MQTT-Kommunikation


MQTT
(Message Queuing Telemetry Transport) ist ein weit verbreitetes Kommunikationsprotokoll, das die Datenübertragung in Form von Nachrichten über das Internet ermöglicht. MQTT ist eine sinnvolle Alternative zur HTTP-Kommunikation, insbesondere für die Kommunikation mit Microcontroller und mobilen Geräten, bei denen die Ressourcen knapp sind. MQTT kommuniziert auch über TCP, aber sehr sparsam. Im Unterschied zu HTTP-Requests, die viele Daten für den Protokoll-Header brauchen, beträgt der MQTT Overhead nur einige wenige Bytes. Zudem benötigen Clients keine feste IP-Adresse und können sowohl Sender wie Empfänger sein. Ein MQTT-Clients kann zu einem frei gewählten Thema (Topic) Informationen publizieren (publish). Andere Clients können diese Topics abonnieren (subscribe). Die zentrale Komponente von MQTT ist ein sogenannter MQTT-Broker, der die  Kommunkation verwaltet. Der Publisher sendet seine Informationen an den Broker, der sie an alle abonnierten Subscriber weiter leitet. Es gibt keine automatische Rückmeldung an den Publisher, ob und wer die Information tatsächlich gelesen hat. Die Daten werden in Echtzeit zum Broker gesendet und dieser leitet sie an die Subscriber weiter. Die Daten bleiben also nicht beim Broker gespeichert, wie dies in einer Cloundanwendung der Fall ist.

In der Regel ist der Publisher ein Microcontroller, der Messdaten sammelt, beispielsweise die Lufttemperatur oder andere Zustandsparameter eines Systems. Er publiziert die Informationen periodisch oder bei einem bestimmten Ereignis und diese können von beliebig vielen Subscribern abholt werden.

Im Internet findet man MQTT-Broker, die ihre Dienste gratis zur Verfügung stellen. Man kann z. B. folgende Hosts verwenden:

test.mosquitto.orgm2m.eclipse.org, broker.hivemq.com

Man erstellt die Verbindung zu einem dieser Server über einen WLAN-Accesspoint (SSID/Passwort erforderlich).

 


Beispiel 1
: Der mbRobot als Publisher

Der mbRobot publiziert die Distanz zu einem Objekt, die er mit seinem Ultraschallsensor misst. Die Daten können beim MQTT-Broker mit einem Smartphone oder einem PC abgeholt werden.

Das Programm Mqtt1.py wird im TigerJython editiert (ssid und password eingeben) und ausgeführt. Der mbRobot erstellt über einen Accesspoint die Verbindung zum Brocker "broker.hivemq.com" und publiziert unter dem Topic "/ch/mbrobot" alle 5 Sekunden, die gemessene Distanz.

# Mqtt1.py
import mqtt
from microbit import *
from mbrobot import *

host = "broker.hivemq.com" 
topic = "/ch/mbrobot"

mqtt.connectAP("mySSID", "myPassword")
mqtt.broker(host)
mqtt.connect()
while True:
    dist = getDistance() 
    print(dist)
    mqtt.publish(topic, "Distance: " + str(dist))
    sleep(5000)
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:
mqtt.broker(host): Legt die Eigenschaften des Brokers fest (hier nur die IP Adresse
mqtt.connect(): Loggt sich beim Broker ein
topic = "/ch/mbrobot": Die Topic-Bezeichnung kann beliebig gewählt werden. Der Vorspann "/ch/" vermindert die Wahrscheinlichkeit, dass dieser Topicname beim Broker bereits existiert.
mqtt.publish(topic, "Distance: " + str(dist)) Aus dem Prefix mqtt. ist ersichtlich, dass der Befehl publish() aus dem Modul mqtt stammt.


Als Subscriber kann man eine MQTT-Client-Applikation verwenden, die auf einem PC oder Smartphone installiert wird, z.B. unter

Um die Daten mit einem Smartphone oder PC abzuholen, wählt man den gleichen Broker und abonniert mit Add Subscriber das Topic /ch/mbrobot.

 

MQTTBox

 

Beispiel 2: Der mbRobot als Subscriber

Der mbRobot kann sich mit der Funktion subscribe() ein Topic abonnieren. Damit kann beispielsweise eine Fernsteuerung eingerichtet werden, sodass man von irgendwo auf dem Internet dem Roboter Befehle senden kann. Im folgenden Programm wird das Topic /ch/lamp verwendet. Wenn die Payload "on" ist, werden die beiden roten LEDs eingeschaltet, wenn sie "off" ist, ausgeschaltet.  

Der micro:bit ruft in einer Schleife periodisch die Funktion mqtt.receive() auf, welche die MQTT-Message als Tupel (topic, payload) zuück gibt. Beide sind None, falls keine Message angekommen ist. (Sind seit dem letzten Aufruf mehrere Messages angekommen, so werden diese in einem Empfangsbuffer gespeichert und bei jedem Aufruf die "älteste" zurückgegeben.

# Mqtt2.py
import mqtt
from mbrobot import *
from microbit import *
host = "broker.hivemq.com"
topic = "/ch/lamp"

mqtt.connectAP("mySSID", "myPassword")
mqtt.broker(host)
mqtt.connect()
mqtt.subscribe(topic)
while True:
    topic, payload = mqtt.receive()
    if topic != None:
        if payload == "on":
            ledLeft.write_digital(1)
            ledRight.write_digital(1)
            display.show(Image.YES)
        elif payload == "off":
            ledLeft.write_digital(0)
            ledRight.write_digital(0)
            display.show(Image.NO)
    sleep(1000) 
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:
topic, payload = mqtt.receive(): Es wird periodisch geprüft, ob eine Message empfangen wurde
if topic != None: Nur falls eine Message empfangen wurde, wird etwas gemacht
sleep(1000): Man prüft jede Sekunde (nicht zu häufig wegen zu hoher Systembelastung, wie bei Sensor-Polling)


 


Für die Fernsteuerung verwendet man z. Bsp. den MQTT Snooper auf einem Smartphone. Man erstellt eine Verbindung zum gleichen Brocker und publiziert unter dem Topic "/ch/lamp" den Payload "on" bzw. "off".

 

Beispiel 3: PIR-Bewegungsdetektor und MQTT zur Überwachung einsetzen

Der mbRobot publiziert unter dem Topic /"ch/pir" ALARM wenn er mit seinem PIR-Bewegungsdetektor eine Bewegung detektiert. Der Smartphone-Client abonniert beim Broker das gleiche Topic und kann die Alarm-Meldung abholen. Wenn am Smartphone der Benachrichtigungston eingeschaltet ist, ertönt beim Alarm auch ein akustisches Signal.

Der PIR-Bewegungsdetector ist am micro:bit mit drei F-F-Jumperkabeln am P2 angeschlossen so wie im Beispiel 4 im Kapitel Push Nachrichten (unbedingt die richtige Verkabelung achten).

Die Benachrichtigung "ALARM" wird nur dann publiziert, wenn der PIR-Sensor eine Bewegung detektiert hat (Spannungsmessung liefert mehr als 500) , d.h. wenn der state von IDLE auf ALARM gewechselt hat.  Falls keine Bewegung mehr stattfindet, fällt die Spannung nach ca. 10 Sekunden wieder auf einen Wert unter 200 und der state wird wieder auf IDLE gesetzt.

 

# MQTT3.py
import mqtt
from microbit import *
from music import *

host = "broker.hivemq.com" 
topic = "/ch/pir"
mqtt.connectAP("mySSID", "myPassword")
mqtt.broker(host)
mqtt.connect()
pitch(1000, 100)
state = "IDLE"
while True:
    v = pin2.read_analog()    
    if v > 500 and state =="IDLE":
        state = "ALARM"
        mqtt.publish(topic, state)
        play(JUMP_UP)       
    if v < 200 and state == "ALARM":    
        state = "IDLE"            
    sleep(500)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

pitch(1000, 100): Nachdem die Verbindung aufgebaut wurde, wird ein kurzer Ton abgespielt, um anzuzeigen, dass die Alarmeinrichtung aktiv ist
state = "IDLE": Es wird eine Zustandsvariable verwendet, die beschreibt, ob der Alarm eben ausgelöst wurde (ALARM) oder der Sensor sich im Detektionsmodus (IDLE) befindet
v = pin2.read_analog(): Gibt den Sensorwert zurück (zwei Spannungspegel)
mqtt.publish(topic, state): Publiziert den aktuellen state
play(JUMP_UP): Beim Alarm wird eine kurze Melodie abgespielt (bei einer "echten" Überwachung müsste man wohl diese Zeile weglassen)