We start a new series of posts about ESP8266/ESP32, where we are going to see communication through the MQTT protocol, which as we know is very suitable for IoT applications.
For those of you who are not familiar with MQTT, I refer you to this series of posts where we have already talked a lot about it. In a very summarized form, we mention that it is one of the multiple communication protocols under the Publisher/Subscriber pattern, very suitable for low-resource processors.
On the other hand, in this post we saw the Pubsub library, as the most popular for implementing MQTT in the Arduino environment. We already anticipated that we would talk about them again in the ESP8266/ESP32 section.
To start this series of posts with a simple example, to lose the fear. Don’t be intimidated by the acronyms and terms. The truth is that communication through MQTT is simple and robust. Precisely there lies much of its success and popularity.
Just as we did with Ajax and Websockets at the time, we are going to start with a simple application that receives a numerical value. In this first example, receiving the value of millis() is enough to check the communication.
To continue with this tutorial you will need to have a MQTT broker installed, or access to one of the multiple cloud services. Here is a post on how to install Mosquitto on your computer.
And, as in the rest of the posts about ESP8266/ESP32 we are going to divide the code into different files, grouped by functions, and trying to make some of them reusable between projects without any modification.
Our main sketch is simple and easy to understand. There are some function calls defined in the files, which we will see next.
But, in summary, in the setup we initiate the WiFi and MQTT communication. On the other hand, in the ‘loop’, we manage the messages received by MQTT, while sending the value of ‘millis()‘. Simple.
#include <WiFi.h>
#include <SPIFFS.h>
#include <PubSubClient.h>
#include "config.h" // Replace with your network data
#include "MQTT.hpp"
#include "ESP32_Utils.hpp"
#include "ESP32_Utils_MQTT.hpp"
void setup(void)
{
Serial.begin(115200);
SPIFFS.begin();
ConnectWiFi_STA(true);
InitMqtt();
}
void loop()
{
HandleMqtt();
PublisMqtt(millis());
delay(1000);
}
On the other hand, the file “ESP32_Utils_MQTT.hpp” contains generic functions for MQTT communication. Like the other ‘Utils’ files we have used, it is intended to contain code that you can reuse between projects with little or no modification.
Here we have these functions for InitMqtt(), ConnectMqtt(), and HandleMqtt()
void InitMqtt()
{
mqttClient.setServer(MQTT_BROKER_ADRESS, MQTT_PORT);
SuscribeMqtt();
mqttClient.setCallback(OnMqttReceived);
}
void ConnectMqtt()
{
while (!mqttClient.connected())
{
Serial.print("Starting MQTT connection...");
if (mqttClient.connect(MQTT_CLIENT_NAME))
{
SuscribeMqtt();
}
else
{
Serial.print("Failed MQTT connection, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void HandleMqtt()
{
if (!mqttClient.connected())
{
ConnectMqtt();
}
mqttClient.loop();
}
Finally, in the ‘MQTT.hpp’ file we have defined the functions that are specific to your project. These functions are “the essence” of the project, and we will have to adapt them according to the characteristics of the project.
So, we have the definitions of the broker address, the port (default 1883 is fine), and the client name. Remember that two clients with the same name should not connect to the same broker.
On the other hand, we have the SuscribeMqtt
function that subscribes the ESP8266/ESP32 to the topics we want to listen to. The PublisMqtt
function sends a message via MQTT, in this case simply a long number. Finally, the OnMqttReceived
function is executed when receiving a message via MQTT and, in this example, simply displays the content through the serial port.
const char* MQTT_BROKER_ADRESS = "192.168.1.150";
const uint16_t MQTT_PORT = 1883;
const char* MQTT_CLIENT_NAME = "ESP8266Client_1";
WiFiClient espClient;
PubSubClient mqttClient(espClient);
void SuscribeMqtt()
{
mqttClient.subscribe("hello/world");
}
String payload;
void PublisMqtt(unsigned long data)
{
payload = "";
payload = String(data);
mqttClient.publish("hello/world", (char*)payload.c_str());
}
String content = "";
void OnMqttReceived(char* topic, byte* payload, unsigned int length)
{
Serial.print("Received on ");
Serial.print(topic);
Serial.print(": ");
content = "";
for (size_t i = 0; i < length; i++) {
content.concat((char)payload[i]);
}
Serial.print(content);
Serial.println();
}
Result
To check that everything works correctly, we upload all the code to our ESP8266/ESP32. If everything has gone well, we will see the value of ‘Millis()’ in the Serial console.
It doesn’t seem very impressive, because we are more than used to seeing the ‘millis’ value, but let’s think for a moment about what is happening. In reality, every second the ESP32 is sending the value of ‘Millis()’ to the broker and it distributes it to the connected clients.
In this mini example we only have one connected client, which is also the sender. It receives the message, processes it, and displays it through the serial port. A rather complicated way to show the ‘millis’ value, but a very good way to check that MQTT communication is working.
Now you could connect more ESP8266/ESP32 and they would all receive the value that we have emitted (almost) simultaneously. And, of course, they could all emit their own messages. A quite powerful concept. And it wasn’t complicated at all, right? That’s the beauty of notification services.
Of course, sending a number is not very interesting. But, now that we know how to send and receive data via MQTT, and we have verified that our MQTT network is working, which is the first step before doing something more complicated.
In the next post we will see how to perform this process asynchronously, and in the following one we will improve it by sending a Json file containing more relevant information. Until next time!
Download the code
All the code from this post is available for download on Github.
Version for ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Version for ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples