In this tutorial, we will create a setup that allows a MKR 1000 WiFi board to send data to another MKR1000 board, using MQTT (Message Queuing Telemetry Transport). The sender device, simply publishes a message to a broker service, which then can be subscribed to by a receiver device.
The data we will send is simply random readings from the analog inputs on the MKR 1000 WiFi board, but can easily be replaced by any sensor. This tutorial uses the broker test.mosquitto.org, an open-source service, free to use by anyone.
This tutorial uses the ArduinoMqttClient and WiFi101 libraries.
The goals of this project are:
The MQTT protocol was first introduced in 1999, as a light-weight publish and subscribe system. It is particularly useful for devices with low-bandwidth, where we can send commands, sensor values or messages over the Internet with little effort.
A basic explanation on how it works is that a node, for example and Arduino with a Wi-Fi module, sends a payload to a broker. A broker is a kind of "middle-point" server, that essentially stores payloads sent to it, in something called topics. A topic, is a definition of what type of data it contains, it could for example be "basement humidity" or "living room temperature". Another node can then subscribe to this information, from the broker, and voilĆ , data has been moved from Node A to Node B over the Internet.
There are several different ways this can be practiced, with many different layers of security depending on what type of broker and setup we use. For example, if we are dealing with non-sensitive data, such as temperature of a specific location, we are not too concerned on who might get access to it. But there's cases where data needs to be protected, for example in Social Media messaging services.
One way to protect the data is for example, by using a token, something that is quite common when working with various IoT services. For instance, if we are publishing something to a broker, anyone that has the URL, e.g. randombroker.org/randomtopic can subscribe to it. But if we add a unique token on both sides, they wouldn't be able to. These tokens could for example be Z6ACuLwr5T, which is not exactly something easy to guess.
MQTT is quite the interesting topic, and if you wish to read more about it, check out the links below:
This tutorial requires no external circuit. It does however, require two MKR1000 boards (one publisher and one subscriber).
We will now go through the steps required to setup one board as a publisher, and one as a subscriber. The following steps will be needed:
First, let's make sure we have the drivers installed. If we are using the Web Editor, we do not need to install anything. If we are using an offline editor, we need to install it manually. This can be done by navigating to Tools > Board > Board Manager.... Here we need to look for the Arduino SAMD boards (32-bits ARM Cortex M0+) and install it.
Now, we need to install the libraries needed. If we are using the Web Editor, there is no need to install anything. If we are using an offline editor, simply go to Tools > Manage libraries.., and search for ArduinoMqttClient and WiFi101 and install them both.
Now let's take a look at some important functions used in the sketches:
WiFiClient wifiClient
- creates a Wi-Fi client.MqttClient mqttClient(wifiClient)
- connects the Wi-Fi client to the MQTT client.WiFi.begin(ssid, pass)
- connects to local Wi-Fi network. mqttClient.connect(broker, port)
- connects to broker (and port).mqttClient.poll()
- keeps the connection alive, used in the loop()
. mqttClient.beginMessage(topic)
- creates a new message to be published.mqttClient.print()
- prints the content of message between the (). mqttClient.endMessage()
- publishes the message to the broker.mqttClient.subscribe(topic)
- subscribes to a topic. mqttClient.available()
- checks if any messages are available from the topic.mqttClient.read()
- reads the incoming messages.arduino_secrets.h
that we can store our Wi-Fi credentials in. To create a tab in the offline editor, click the arrow symbol underneath the Serial Monitor symbol, and click on the "New tab" option.Then, name the file "arduino_secrets.h".
SECRET_SSID
(network name) and SECRET_PASS
(password) needs to be replaced by your own credentials.1#define SECRET_SSID ""2#define SECRET_PASS ""
Note: The char
,topic[]
andtopic2[]
, created here may be used by someone else. If we change this, we will also need to change the name of the topic we subscribe to in the subscriber sketch.topic3[]
1#include <ArduinoMqttClient.h>2#include <WiFi101.h>3#include "arduino_secrets.h"4
5///////please enter your sensitive data in the Secret tab/arduino_secrets.h6char ssid[] = SECRET_SSID; // your network SSID (name)7char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)8
9WiFiClient wifiClient;10MqttClient mqttClient(wifiClient);11
12const char broker[] = "test.mosquitto.org";13int port = 1883;14const char topic[] = "real_unique_topic";15const char topic2[] = "real_unique_topic_2";16const char topic3[] = "real_unique_topic_3";17
18//set interval for sending messages (milliseconds)19const long interval = 8000;20unsigned long previousMillis = 0;21
22int count = 0;23
24void setup() {25 //Initialize serial and wait for port to open:26 Serial.begin(9600);27 while (!Serial) {28 ; // wait for serial port to connect. Needed for native USB port only29 }30
31 // attempt to connect to Wifi network:32 Serial.print("Attempting to connect to WPA SSID: ");33 Serial.println(ssid);34 while (WiFi.begin(ssid, pass) != WL_CONNECTED) {35 // failed, retry36 Serial.print(".");37 delay(5000);38 }39
40 Serial.println("You're connected to the network");41 Serial.println();42
43 Serial.print("Attempting to connect to the MQTT broker: ");44 Serial.println(broker);45
46 if (!mqttClient.connect(broker, port)) {47 Serial.print("MQTT connection failed! Error code = ");48 Serial.println(mqttClient.connectError());49
50 while (1);51 }52
53 Serial.println("You're connected to the MQTT broker!");54 Serial.println();55}56
57void loop() {58 // call poll() regularly to allow the library to send MQTT keep alives which59 // avoids being disconnected by the broker60 mqttClient.poll();61
62 unsigned long currentMillis = millis();63
64 if (currentMillis - previousMillis >= interval) {65 // save the last time a message was sent66 previousMillis = currentMillis;67
68 //record random value from A0, A1 and A269 int Rvalue = analogRead(A0);70 int Rvalue2 = analogRead(A1);71 int Rvalue3 = analogRead(A2);72
73 Serial.print("Sending message to topic: ");74 Serial.println(topic);75 Serial.println(Rvalue);76
77 Serial.print("Sending message to topic: ");78 Serial.println(topic2);79 Serial.println(Rvalue2);80
81 Serial.print("Sending message to topic: ");82 Serial.println(topic2);83 Serial.println(Rvalue3);84
85 // send message, the Print interface can be used to set the message contents86 mqttClient.beginMessage(topic);87 mqttClient.print(Rvalue);88 mqttClient.endMessage();89
90 mqttClient.beginMessage(topic2);91 mqttClient.print(Rvalue2);92 mqttClient.endMessage();93
94 mqttClient.beginMessage(topic3);95 mqttClient.print(Rvalue3);96 mqttClient.endMessage();97
98 Serial.println();99 }100}
We will now program the subscriber device. For this, we need to create a new sketch, and create another
arduino_secrets.h
file. 1#include <ArduinoMqttClient.h>2#include <WiFi101.h>3#include "arduino_secrets.h"4
5///////please enter your sensitive data in the Secret tab/arduino_secrets.h6char ssid[] = SECRET_SSID; // your network SSID7char pass[] = SECRET_PASS; // your network password8
9WiFiClient wifiClient;10MqttClient mqttClient(wifiClient);11
12const char broker[] = "test.mosquitto.org";13int port = 1883;14const char topic[] = "real_unique_topic";15const char topic2[] = "real_unique_topic_2";16const char topic3[] = "real_unique_topic_3";17
18void setup() {19 //Initialize serial and wait for port to open:20 Serial.begin(9600);21 while (!Serial) {22 ; // wait for serial port to connect. Needed for native USB port only23 }24 // attempt to connect to Wifi network:25 Serial.print("Attempting to connect to SSID: ");26 Serial.println(ssid);27 while (WiFi.begin(ssid, pass) != WL_CONNECTED) {28 // failed, retry29 Serial.print(".");30 delay(5000);31 }32
33 Serial.println("You're connected to the network");34 Serial.println();35
36 Serial.print("Attempting to connect to the MQTT broker: ");37 Serial.println(broker);38
39 if (!mqttClient.connect(broker, port)) {40 Serial.print("MQTT connection failed! Error code = ");41 Serial.println(mqttClient.connectError());42
43 while (1);44 }45
46 Serial.println("You're connected to the MQTT broker!");47 Serial.println();48
49 // set the message receive callback50 mqttClient.onMessage(onMqttMessage);51
52 Serial.print("Subscribing to topic: ");53 Serial.println(topic);54 Serial.println();55
56 // subscribe to a topic57 mqttClient.subscribe(topic);58 mqttClient.subscribe(topic2);59 mqttClient.subscribe(topic3);60
61 // topics can be unsubscribed using:62 // mqttClient.unsubscribe(topic);63
64 Serial.print("Topic: ");65 Serial.println(topic);66 Serial.print("Topic: ");67 Serial.println(topic2);68 Serial.print("Topic: ");69 Serial.println(topic3);70
71 Serial.println();72}73
74void loop() {75 // call poll() regularly to allow the library to receive MQTT messages and76 // send MQTT keep alive which avoids being disconnected by the broker77 mqttClient.poll();78}79
80void onMqttMessage(int messageSize) {81 // we received a message, print out the topic and contents82 Serial.println("Received a message with topic '");83 Serial.print(mqttClient.messageTopic());84 Serial.print("', length ");85 Serial.print(messageSize);86 Serial.println(" bytes:");87
88 // use the Stream interface to print the contents89 while (mqttClient.available()) {90 Serial.print((char)mqttClient.read());91 }92 Serial.println();93 Serial.println();94}
If everything was successful during the upload, we now have a publisher and subscriber device. Next, we need to open the Serial Monitor for each board, one at a time. This will initialize the sketch. Since we can only have one Serial Monitor open at one time, we will need to switch the ports manually. Using only one computer can be a bit tedious, as we can never view the Serial Monitor of both devices at the same time.
In this tutorial, we are using two MKR 1000 WiFi boards. When switching between the ports, we can see them listed as COM12 and COM3.
When both devices have been initialized, they start connecting to the network. Now, let's open the Serial Monitor and keep it open for the publisher device.
We can now see that we are sending messages every 8 seconds (this interval can be changed at the top of the code). Each interval sends three messages, for each topic. Each topic contains the latest reading from an analog pin.
Now, let's open the subscriber device's Serial Monitor, and keep it open. If everything is successful, we can now see the analog values. This means, that we have successfully published three topics on one device, and subscribed to them using another device.
If the code is not working, there are some common issues we can troubleshoot:
arduino_secrets.h
tab.In this tutorial, we have created a very basic MQTT application, which allows data to flow from a publisher device, via a broker, to a subscriber device. This type of setup is commonly used in many Internet of Things (IoT) applications, and we encourage you to continue exploring the ArduinoMqttClient library. In this tutorial, in order to create a minimal working project we did not use any form of encryption. This is OK to use for just basic, non-private data, but if you are intending to use it for e.g. home automation, security systems and so on, it is strongly recommended to use more security layers.
The broker used in this tutorial, test.mosquitto.org provides some explanation on different forms of encryption, and what ports to use etc.