Internet of Things/Protocollen/MQTT
MQTT (MQ Telemetry Protocol)
- MQTT stands for MQ Telemetry Transport. It is a publish/subscribe, extremely simple and lightweight messaging protocol, designed for constrained devices and low-bandwidth, high-latency or unreliable networks. The design principles are to minimise network bandwidth and device resource requirements whilst also attempting to ensure reliability and some degree of assurance of delivery. These principles also turn out to make the protocol ideal of the emerging “machine-to-machine” (M2M) or “Internet of Things” world of connected devices, and for mobile applications where bandwidth and battery power are at a premium.
publish/subscribe: client-broker-client
Bij MQTT verloopt de communicatie van berichten in twee stappen:
- een client "publiceert" een bericht naar een broker onder een bepaald onderwerp (topic)
- de broker stuurt dit bericht door naar alle clients die geabonneerd zijn op dit onderwerp.
Voorbeeld:
- de (NodeRed) servers A en B abonneren zich op het topic Tx=
node/1234/sensors
- de sensornode 1234 publiceert het bericht Ma=
{"temperature": 21.7}
naar het topic Tx=node/1234/sensors
- de broker stuurt dit bericht Ma met het genoemde topic Tx naar de servers A en B.
Eigenschappen
Deze publish/subscribe-methode heeft de volgende eigenschappen:
- ontkoppeling van bron- en doel-clients van berichten
- een client publiceert naar een onderwerp, zonder kennis over geabonneerde clients
- het onderwerp fungeert als een "abstract adres" voor de communicatie
- de communicatie tussen bron- en doel-clients is N-M
- meerdere clients kunnen op eenzelfde onderwerp geabonneerd zijn;
- meerdere clients kunnen naar eenzelfde onderwerp publiceren;
- 1-0, 1-1, 1-N, N-1, N-M zijn allemaal mogelijk
- de berichten worden "gepusht" van bron- naar doel-client
- in tegenstelling tot HTTP, waar er sprake is van "pull".
De koppeling tussen de verschillende clients verloopt indirect, via het topic.
- Dit kun je vergelijken met het gebruik van "call backs" of event handlers: in een toepassing definieer je een handler-functie voor het afhandelen van een event. Het onderliggende systeem roept deze handler-functie als de bewuste event optreedt. Op de plaats van het signaleren van de event is alleen de event bekend, niet de handler(s) voor deze event.
Merk op dat een client zowel "publisher" als "subscriber" kan zijn. Dit gebruiken we ook in de IoT-keten: een node is "publisher" van de eigen sensor-data, en "subscriber" van de data voor aansturing van de eigen actuatoren.
Verbindingen en berichten
Om de overhead per bericht klein te houden gebruikt MQTT bi-directionele verbindingen tussen broker en clients. Een client moet zich eerst aanmelden bij de broker, en de verbinding tussen client en broker tot stand brengen. Pas daarna zijn "publish" en "subscribe" acties mogelijk. Door allerlei oorzaken kan de verbinding tussen client en broker onderbroken worden. Het is daarom verstandig om in de client regelmatig te controleren of deze verbinding nog bestaat, en deze zonodig opnieuw te openen.
Door het gebruik van deze verbindingen kan de overhead per bericht klein blijven, wat voor IoT-toepassingen belangrijk is. De actieve verbindingen leggen wel een permanent beslag op de resources van de broker: deze moet voor de betreffende toepassingen goed gedimensioneerd zijn.
MQTT over Websockets
De nieuwere MQTT-brokers ondersteunen ook MQTT via websockets (ws of wss protocol). Op basis van dit websocket-protocol zijn er MQTT-libraries voor JavaScript in de browser. Dit betekent dat een webtoepassing in een browser direct gebruik kan maken van MQTT, zonder tussenkomst van een webserver (zoals een NodeRed server). Dit vind je onder meer terug bij MQTT-tools die als webpagina werken.
In de toekomst zal het MQTT-protocol wellicht direct door de browsers ondersteund worden.
QoS (quality of service)
In een IoT-keten speelt de betrouwbaarheid van de sensor-data en van de berichten een rol. De vereiste betrouwbaarheid hangt af van de toepassing en van de sensoren. Bij MQTT kun je de quality of service (QoS) instellen, op de volgende niveaus:
- QOS=0: bericht wordt ten hoogste 1 maal afgeleverd;
- "best effort", zoals in het internet en in het web.
- QOS=1: bericht wordt ten minste 1 maal afgeleverd;
- de ontvanger van een bericht stuurt een "acknowledgement" naar de verzender ("handshake");
- als de verzender niet op tijd deze bevestiging ontvangt, verstuurt deze het bericht opnieuw;
- dit kan betekenen dat er duplicaten van een bericht aankomen.
- QOS=2: bericht wordt precies 1 maal afgeleverd.
- in dit geval is een "dubbele handshake" nodig.
Elk volgend QoS-niveau heeft een grotere betrouwbaarheid, maar dit gaat ten koste van extra berichten (bandbreedte) en extra vertraging (door het wachten op de extra berichten).
Veiligheid
MQTT berichten kunnen versleuteld verstuurd worden. Het normale MQTT gebruikt TCP als basis; de versleutelde versie van MQTT gebruikt TLS (Transport Layer Security, voorheen SSL). Bij MQTT over Websockets kan de versleutelde versie gebruikt worden (wss in plaats van ws).
Hoe gebruiken wij MQTT in de IoT-keten?
We gebruiken MQTT voor de berichten tussen de sensor/actuator-nodes en de (NodeRed) webservers. Ook de communicatie met de webtoepassing (in de browser) gebruikt de MQTT-berichten, die door NodeRed via het websockets protocol verstuurd worden.
- De huidige MQTT broker ondersteunt nog geen websockets; in een volgende versie wordt dit wel ondersteund, en kan de webtoepassing ook rechtstreeks met de MQTT broker communiceren.
In een uitgebreide versie van de IoT-keten gebruiken we een lokale hub, met MQTT en NodeRed, naast de publieke broker/servers. In dat geval gebruiken we MQTT ook voor het verkeer tussen de lokale hub en de publieke MQTT-broker.
Topic adresseert node
We gebruiken de MQTT-topics voor het adresseren van nodes. Er is geen andere manier om deze nodes te adresseren: deze hoeven geen onderdeel te zijn van het (publieke) internet. In sommige gevallen gebruiken deze nodes zelfs geen internet-protocol.
Sensor/actuator-nodes communiceren als volgt met de MQTT-broker:
- node
xxxx
publiceert de lokale sensoren naar topicnode/xxxx/sensors
; - node
xxx
abonneert zich op het topicnode/xxxx/actuators
.
Hierin is xxxx
de identificatie van de node. We gebruiken daarvoor bijvoorbeeld het laatste deel van het MAC-adres.
De webserver (NodeRed) is hieraan complementair:
- de webserver abonneert zich op alle sensor-berichten van alle nodes:
node/+/sensors
- de webserver publiceert actuator-berichten naar de betreffende actuator-topics.
Voor de communicatie van de MQTT-berichten tussen de NodeRed-webserver en de toepassing in de browser gebruiken we websockets. Via de websocket sturen we de MQTT-berichten voorzien van het MQTT-topic. Dit betekent dat de webtoepassing voor MQTT (enigszins) vergelijkbaar is met de sensor/actuator-nodes.
- We maken in de webtoepassing nog geen gebruik van een subscribe-mogelijkheid: net als in de NodeRed-webserver krijgt de webtoepassing alle sensor-berichten van alle nodes.
Alternatief: topic adresseert sensor/actuator
De keuze die we gemaakt hebben om topics overeen te laten komen met nodes is één van de mogelijkheden.
- een nadeel van deze aanpak is dat een message vaak nog geïnterpreteerd moet worden: je moet bijvoorbeeld uitzoeken welke sensoren in een bepaald bericht aanwezig zijn.
Een alternatief is om topics nog specifieker te kiezen: een topic adresseert een sensor, of een eigenschap van een "ding". Je krijgt dan topics als:
node/1234/sensors/button0
home/livingroom/temperature
JSON
We gebruiken het JSON-formaat voor de MQTT-berichten. Dit formaat is eenvoudig te interpreteren voor mens en computer. Je kunt het gebruiken voor het versturen van data, voor het opslaan hiervan in een database, of voor het verwerken in een toepassing.
In de JSON-berichten gebruiken we de volgende velden:
- nodeid: de identificatie van de node
- sensorX: de sctuele waarde van sensor X
- localtime: de waarde van een lokale msec-timer in de node
- actuatorY: de in te stellen waarde voor actuator Y
- topic: het bijbehorende MQTT-topic (in de websockets-communicatie).
Enkele voorbeelden van topics/berichten:
topic: node/e1bd/sensors - {"id":"e1bd","sensor1":677,"localtime":402000000}
topic: node/4d62/sensors - {"id":"4d62","sensor0":1,"sensor2":0,"localtime":181236299}
topic: topic:node/e1bd/actuators - {"led0": 1}
Er zijn veel andere indelingen mogelijk: de keuze die we hier gemaakt hebben is niet essentieel.
Voorbeeld-clientcode
Voorbeelden van client-code voor Arduino en ESP8266 zijn te vinden op GitHub:
- https://github.com/eelcodijkstra/iot2016/blob/master/arduinonode.ino
- https://github.com/eelcodijkstra/iot2016/blob/master/esp8266node.ino
Software: brokers en clients
Mosquitto
Mosquitto is een open-source implementatie van een MQTT-broker. Mosquitto is beschikbaar voor Linux, Windows, OS X. De nieuwste versies van Mosquitto ondersteunen ook MQTT over Websockets (ws en wss protocol). Onderdeel van mosquitto zijn ook de command-line clients mosquitto_pub
en mosquitto_sub
die vooral voor test-doeleinden handig kunnen zijn.
Paho client
Het Eclipse Paho-project biedt MQTT client software voor verschillende talen en platformen, onder andere Python.
Ook MQTT-SN clients en gateways zijn onderdeel van dit project, maar deze verkeren nu nog in een experimenteel stadium.
- http://www.eclipse.org/paho/
- Python client: https://github.com/eclipse/paho.mqtt.python
- Embedded/Arduino client: https://eclipse.org/paho/clients/c/embedded/
PubSubClient
PubSubClient is een Open Source Arduino-library voor een eenvoudige MQTT-client. Hiermee kan een Arduino berichten met lokale sensordata publiceren naar een broker, en zich abonneren op berichten voor de lokale actuatoren.
- Omdat een Arduino beperkte mogelijkheden heeft, zijn ook de mogelijkheden van deze MQTT-client beperkt: (i) encryptie is niet mogelijk; (ii) QoS is beperkt tot niveau 0 (best effort).
MQTT diensten (publieke brokers)
Er zijn allerlei IoT-diensten beschikbaar "in the cloud". Een onderdeel van een dergelijke dienst is een MQTT broker. Voor de eenvoudigste (gratis) versie van een dergelijke dienst is vaak een publieke MQTT-broker beschikbaar.
Meer informatie
- MQTT standaard: http://mqtt.org/
- MQTT in de praktijk: http://www.redbooks.ibm.com/redbooks/pdfs/sg248054.pdf
- MQTT tutorials: http://www.hivemq.com/mqtt-essentials/