MQTT is one of the most commonly used protocols in IoT projects. It stands for Message Queuing Telemetry Transport. In addition, it is designed as a lightweight messaging protocol that provides publish/subscribe operations to exchange data between parties. This exercise is to be considered as closely related to the M2 exercise. Both are part of the same scenario. This exercise shows how to publish a message as a client.
This hands-on lab guide is intended for master students. Other target groups may benefit from it only if they follow it after having dealt with all the exercises proposed which belong to lower levels of difficulty.
For this library, you may refer to the B1 exercise.
For this library, you may refer to the B2 exercise.
The Arduino Ethernet Shield V1 allows an Arduino board to connect to the internet. It is based on the Wiznet W5100 [1] ethernet chip (datasheet [2]). The Wiznet W5100 provides a network (IP) stack capable of both TCP and UDP-based communication. It supports up to four simultaneous socket connections. Use the Ethernet library [3] to write sketches that connect to the Internet using the shield. The ethernet shield connects to an Arduino board using long wire-wrap headers which extend through the shield. This keeps the pin layout intact and allows another shield to be stacked on top.
[1] http://www.wiznet.co.kr/Sub_Modules/en/product/Product_Detail.asp?cate1=5&cate2=7&cate3=26&pid=1011
[2] http://www.wiznet.co.kr/UpLoad_Files/ReferenceFiles/W5100_Datasheet_v1.2.2.pdf
MQTT (Message Queue Telemetry Transport) is a standard (SO/IEC PRF 20922) machine-to-machine (M2M) communication protocol for the Internet of Things smart objects and devices. MQTT is a simple messaging protocol, designed for constrained devices with low-bandwidth. So, it’s the perfect solution for Internet of Things applications. This publish/subscribe messaging pattern requires a message broker. The broker is responsible for distributing messages to interested clients based on the topic of a message. So a client must connect to a broker in order to: publish messages specifying a topic so that other clients that have subscribed to that topic will be able to receive those messages; receive messages subscribing to a specific topic.
This exercise uses shiftr.io [4]. Shiftr.io is a web-based visualization for messages going through an MQTT broker. It is possible to use broker.shiftr.io directly as a public broker.
This node, which acts as a publisher, takes care of sampling the temperature value and sending it to other nodes, which serve as subscribers and were initialized as in exercise M2.
It will be possible to display the value of the temperature, measured from the sensors attached to this node of the lab, on the LCD display attached to another node of the lab, provided that in the latter node the M2 sketch has been previously launched. Start This exercise is to be considered as closely related to the M2 exercise. This means that if you want to reproduce a complete experiment, you have to book at least two nodes of the lab, and then you have to run both IM1 and IM2 sketches, one per node.
Include the following libraries: LCD driver, DHT, MQTT, and Ethernet.
#include <LiquidCrystal.h> #include <Ethernet.h> #include <MQTT.h> #include <DHT.h>
Instantiate the software controller component for the LCD display. Then assign to the ethernet interface a MAC and IP address, the latter valid for the internal laboratory network (192.168.0.0/24 in this case). Thus instantiate the EthernetClient and MQTTClient objects. Finally declare the connect() function.
// initialize the library with the numbers of the interface pins LiquidCrystal lcd(7, 6, 5, 4, 13, 2); byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; byte ip[] = {192, 168, 0, 98}; EthernetClient net; MQTTClient client; unsigned long lastMillis = 0; void connect() { Serial.print("connecting..."); while (!client.connect("arduino", "try", "try")) { Serial.print("."); delay(1000); } Serial.println("\nconnected!"); }
Initialize the display and the Ethernet connection with IP and MAC address. Then launch the connection() function and initialize the MQTT client with the shift.io broker. You can visualize your device stream, after a successful connection, here: https://shiftr.io/try.
We suggest doing all of the above in the setup() function, as follows:
void setup() { lcd.begin(16, 2); lcd.print("Temp. *C"); lcd.setCursor(0,1); lcd.print("MQTT PUB"); Serial.begin(115200); Ethernet.begin(mac, ip); client.begin("broker.shiftr.io", net); connect(); }
Implement the loop() function to detect the value of temperature from the DHT sensor and publish it as a message with the topic “iotopenume” every 1 second, as follows:
void loop() { client.loop(); if (!client.connected()) { connect(); } int t = dht.readTemperature(); String payload = String(t); // publish a message roughly every second. if (millis() - lastMillis > 1000) { lastMillis = millis(); Serial.println(payload); //publish to the iotopenume topic client.publish("/iotopenume", payload); lcd.setCursor(14, 1); lcd.print(payload); } }
It will be possible to display the value, sampled by the temperature sensor attached to this node, on the LCD display attached to the node you will use as a subscriber, as soon as you start the M2 sketch on the latter.
[env:uno] platform = atmelavr board = uno framework = arduino lib_ldf_mode=deep+ lib_compat_mode=strict lib_deps = DHT sensor library@1.3.0 Adafruit Unified Sensor@1.0.3 Ethernet@2.0.0 MQTT@2.4.3 lib_deps_external = https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7
#include <Ethernet.h> #include <MQTT.h> #include <DHT.h> #include <LiquidCrystal.h> #define DHTPIN 8 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); LiquidCrystal lcd(7, 6, 5, 4, 13, 2); byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; byte ip[] = {192, 168, 0, 98}; EthernetClient net; MQTTClient client; unsigned long lastMillis = 0; void connect() { Serial.print("connecting..."); while (!client.connect("arduino", "try", "try")) { Serial.print("."); delay(1000); } Serial.println("\nconnected!"); } void setup() { lcd.begin(16, 2); lcd.print("Temp. *C"); lcd.setCursor(0,1); lcd.print("MQTT PUB"); Serial.begin(115200); Ethernet.begin(mac, ip); client.begin("broker.shiftr.io", net); connect(); } void loop() { client.loop(); if (!client.connected()) { connect(); } int t = dht.readTemperature(); String payload = String(t); // publish a message roughly every second. if (millis() - lastMillis > 1000) { lastMillis = millis(); Serial.println(payload); client.publish("/iotopenume", payload); lcd.setCursor(14, 1); lcd.print(payload); } }