Deutsch   English 

13. MQTT Communication


MQTT (Message Queuing Telemetry Transport) is a widely used communication protocol that provides data exchange over the Internet. MQTT is a useful alternative to HTTP communication, especially for communication with microcontrollers and mobile devices where resources are scarce. MQTT also communicates via TCP, but very economically. In contrast to HTTP requests, which require a lot of data for the protocol header, the MQTT overhead is only a few bytes. In addition, clients do not need a fixed IP address and can be both sender and receiver. An MQTT client can publish information on a freely chosen topic. Other clients can subscribe to these topics. The central component of MQTT is a so-called MQTT broker, which manages the communication. The publisher sends his information to the broker, who forwards it to all subscribers. There is no automatic feedback to the publisher as to whether and who has actually read the information. The data is sent to the broker in real time and the broker forwards it immediately to the subscribers. This means that the data is not stored by the broker, as is the case with most cloud application.

Typically, the publisher is a microcontroller that collects measurement data, such as air temperature or other parameters of a system. It publishes the data periodically or triggered by specific event and the information can be retrieved by any number of subscribers. MQTT brokers can be found on the Internet, providing their services free of charge. For example, you can use the following hosts:

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

The connection to one of these servers is established via a WLAN access point (SSID/password required)).

 


Example 1
: mbRobot as a publisher
The mbRobot with a built-in LinkUp publishes the distance to an object measured with its ultrasonic sensor. The information is retrieved from the MQTT broker with a smartphone or a PC.

Mqtt1.py is creates the connection to the broker "broker.hivemq.com" via an access point and publishes the measured distance under the topic /ch/mbrobot every 5 seconds.

# 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))
    delay(5000)
► Copy to clipboard
 

 

Explanations of the program code:
mqtt.broker(host): Defines the properties of the broker (here only the IP address)
mqtt.connect(): Logs on to the broker
topic = "/ch/mbrobot":The topic name can be chosen arbitrarily. The prefix "/ch/" reduces the probability that this topic name already exists for the broker
mqtt.publish(topic, "Distance: " + str(dist)) The message is published under the selected topic

You can use an MQTT client application as a subscriber, which is installed on a PC or smartphone, e.g.

 

To retrieve the data with a smartphone or PC, select the same broker and subscribe to the /ch/mbrobot topic with Add Subscriber.

 

MQTTBox

 

Example 2: mbRobot as subscriber
The mbRobot can subscribe to a topic using the subscribe() function, for example, in a remote control system to control the robot from anywhere on the Internet. As demonstration, the two LEDs of the mbRobot are switch on/off by commands sent via the Internet. The topic /ch/lamp is used. If the payload is "on", the two red LEDs are turned on, if it is "off", they are turned off.   

The micro:bit periodically calls the function mqtt.receive() in a loop, which returns the MQTT message as a tuple (topic, payload). Both are None if no message has arrived. (If several messages have arrived since the last call, they are stored in a receive buffer and the "oldest" message is returned for each call.)

# 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)
    delay(1000) 
► Copy to clipboard
 

Explanations of the program code:
topic, payload = mqtt.receive(): The system periodically checks whether a message was received
if topic != None: If a message was received, something will be done
sleep(1000): Check only every second to prevent high system load (same as with sensor polling)


   


Use MQTT Dash on a smartphone as remote control. You create a connection to the same broker and publish the payload "on" or "off" under the topic /ch/lamp

 

 

Example 3: Using a PIR motion detector and MQTT for monitoring

The mbRobot publishes the message ALARM under the topic /ch/pir, if it detects a movement with its PIR motion detector. A smartphone client subscribes to the same topic and picks up the alarm message. With some MQTT client apps an acoustic signal or vibration can be enabled when an alarm is received.

The PIR motion detector is connected to the micro:bit with three F-F jumper cables on the P2 as in example 4 in the chapter Push Messages (make sure you have the correct cabling).

The "ALARM" notification is only published if the PIR sensor has detected a movement (voltage measurement delivers more than 500), i.e. if the state has changed from IDLE to ALARM.  If there is no more movement, the voltage drops back to a value below 200 after about 10 seconds and the state is reset to IDLE.

 

# 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" 
        mqtt.publish(topic, state)
        play(JUMP_DOWN)              
    delay(500)
► Copy to clipboard
 

Explanations of the program code:

pitch(1000, 100): After the connection is established, a short beep will be played to indicate that the alarm is active
state = "IDLE": A state variable is used which describes whether the alarm has just been triggered (ALARM) or whether the sensor is in detection mode (IDLE)
v = pin2.read_analog(): Returns the sensor value (two voltage levels)
mqtt.publish(topic, state):Publishes the current state
play(JUMP_UP): For demonstration purposes a short melody is played when the alarm is triggered (in case of a real monitoring system one would probably omit this line)


Example 4: Publish temperature and humidity (simple weather station)
The simple system consists of a micro:bit, a LinkUp (ESP32 microcontroller) and a Sensirion temperature and humidity sensor. The micro:bit starts a MQTT client on the LinkUp, which periodically publishes the sensor data temp and humi. To read this data, an MQTT client on a PC, tablet or smartphone subscribes these two topics.

The program has a "robust" structure, i.e. if the connection is lost, the system attempts to re-establish the connection. The connection status and the current data is shown on the micro:bit display. Tests have shown that this program runs for weeks without human intervention.

# Mqtt4.py

from microbit import *
import mqtt, rtc, gc
import sht

host = "broker.hivemq.com"

while True:
    try:
        gc.collect()
        display.show('L')     
        if mqtt.connectAP("raspilink", "aabbaabbaabb"):
            display.show('B')      
            mqtt.broker(host)
            if mqtt.connect():
                while True:
                    display.show(Image.ARROW_E)
                    temp, humi = sht.getValues() 
                    tme = rtc.get()
                    payload_date = "%d.%d\n%02d:%02d" %(tme[2], tme[1], tme[3], tme[4])
                    if not (mqtt.publish("/ch/home/date", payload_date) and 
                            mqtt.publish("/ch/home/temp", "%.1f" % temp) and 
                            mqtt.publish("/ch/home/humi", "%.1f%%" % humi)):
                        display.show('e')
                        sleep(3000)
                        break
                    sleep(2000)
                    s = " : : %.1f - %.1f" % (temp, humi)
                    for _ in range(3):
                        display.scroll(s)
            else:
                display.show('b')
                sleep(3000)
        else:
            display.show('l')
            sleep(3000)
    except:
        display.show('z')
        sleep(3000)
► Copy to clipboard

Explanations of the program code:

gc.collect(): The garbage collector releases unused resources (avoids memory overflow)
sht.getValues() : Returns a tuple with temperature (in degrees Celsius) and humidity (in percent)
mqtt.publish("/ch/temp", "%.1f" % temp): Formatted output rounded to one decimal place
try-except: Any error is caught and the program restarts the communication