==== IM2: MQTT to subscribe to a topic to receive messages ====
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 M1 exercise. Both are part of the same scenario. This exercise shows how to subscribe to a topic to receive messages belonging to it.
=== Target group ===
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.
=== Prerequisites ===
== Liquid Crystal ==
For this library, you may refer to the [[en:iot-open:remotelab:ume:smartme:b1|B1 exercise]].
== DHT ==
For this library, you may refer to the [[en:iot-open:remotelab:ume:smartme:b2|B2 exercise]].
== Understand what Arduino Ethernet Shield is and how it works ==
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
[3] https://www.arduino.cc/en/Reference/Ethernet
== Understand what MQTT is and how it works. ==
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.
[4] https://shiftr.io
=== Scenario ===
This node, which acts as a subscriber, shows the value of temperature received by the other node that was initialized with the exercise M1.
=== Result ===
It will be possible to display the value of the temperature, measured from the sensors attached to the node where the M1 sketch had been previously launched, on the LCD attached to this node.
Start
This exercise is to be considered as closely related to the M1 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.
=== Steps ===
== Step 1 ==
Include the following libraries: LCD driver, MQTT, and Ethernet.
#include
#include
#include
== Step 2 ==
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). Then instantiate the EthernetClient and MQTTClient objects. Then declare the ''connect()'' and ''messageReceived()'' functions. In particular, in the ''connect()'' body there is a call to the ''subscribe()'' function, in order to subscribe to a specific topic. In the ''messageReceived()'' body the payload of the message (the temperature value, in this case) is written in the LCD display of the node.
// 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, 0xEF};
byte ip[] = {192, 168, 0, 99};
EthernetClient net;
MQTTClient client;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
// subscribe to the iotopenume topic
client.subscribe("/iotopenume");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
lcd.setCursor(14, 1);
lcd.print(payload);
}
== Step 3 ==
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 SUB");
Serial.begin(115200);
Ethernet.begin(mac, ip);
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
== Step 4 ==
Implement ''loop()'' to try connecting until success, as follows:
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
}
=== Result validation ===
Observe on your LCD display, its hosting node acting as a subscriber, the value sampled by the temperature sensor attached to the publisher, as soon as you start the M1 sketch on the latter.
=== Platformio.ini ===
[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
=== IM2_sub.cpp ===
#include
#include
#include
LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF};
byte ip[] = {192, 168, 0, 99};
EthernetClient net;
MQTTClient client;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/iotopenume");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
lcd.setCursor(14, 1);
lcd.print(payload);
}
void setup() {
lcd.begin(16, 2);
lcd.print("Temp. *C");
lcd.setCursor(0,1);
lcd.print("MQTT SUB");
Serial.begin(115200);
Ethernet.begin(mac, ip);
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
}