ESP8266 MQTT Client: Publish and subscribe

This tutorial covers how to develop and use an ESP8266 MQTT client to publish and subscribe to MQTT channels. In more detail, this ESP8266 tutorial will develop an ESP8266 MQTT client that connects to Mosquitto MQTT broker running on Raspberry Pi. Next, we will use Node-red (running on Raspberry Pi) to create a dashboard that visualizes the data. Moreover in this project, we will explore:

  • how to publish data using MQTT from ESP8266
  • how to subscribe to an MQTT channel using ESP8266

Firstly, in the first scenario, the ESP8266 connects to DHT11 to acquire temperature and humidity. These sensor readings are sent to the MQTT broker (Mosquitto) using two MQTT channels. Therefore, ESP8266 publishes data through MQTT channels.

Secondly, in this scenario, the ESP8266 subscribes to the MQTT channel and receives data. In this context, to make things simple, the ESP8266 will control a LED using the commands received.

If you are new to MQTT, before going on, please read this tutorial: “MQTT Protocol Tutorial: Technical description, MQTT security“.

ESP8266 MQTT Client Publishing data

In this first step, we will analyze how to publish sensor readings from ESP8266 to Mosquitto (the MQTT broker). The picture below shows this scenario:

ESP8266 MQTT publishing data to Mosquitto running on Raspberry Pi

In this case, the ESP8266 acts as an MQTT client that publishes sensor readings to the MQTT broker. Therefore, the ESP8266 uses two different channels to publish data. Next, using Node-red we will build a Node-red UI dashboard that visualizes the data acquired by the sensor. Node-red and Mosquitto run on the Raspberry Pi. You can access the dashboard using a browser as we will see later.

Implementing the MQTT client using PubsubClient library

Once we have a big picture of the scenario where we want to use our ESP8266, we can start coding the ESP8266 MQTT client. To simplify the client development we will use the PubsubClient library. Therefore, you have to import it into your project. The code is shown below:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

IPAddress mqttServer(192,168,1,142);
const char *SSID = "your_ssid";
const char *PWD = "your_wifi_pwd";
long lastime = 0;
 
void callback(char* topic, byte* payload, unsigned int length) {
 Serial.println("Callback");
 Serial.println((char) payload[0]);
}

WiFiClient wifiCliient = WiFiClient();
PubSubClient mqttClient(mqttServer, 1883, callback, wifiCliient);
 
void connectToWiFi() {
 Serial.print("Connecting to ");
 Serial.println(SSID);
  WiFi.begin(SSID, PWD);
  while (WiFi.status() != WL_CONNECTED) {
   Serial.print(".");
   delay(500);
   // we can even make the ESP32 to sleep
 }
 
 Serial.print("Connected - ");
 //Serial.println(WiFi.localIP);
}
 
void reconnect() {
 Serial.println("Connecting to MQTT Broker...");
 while (!mqttClient.connected()) {
     Serial.println("Reconnecting to MQTT Broker..");
     String clientId = "ESP8266Client-";
     clientId += String(random(0xffff), HEX);
    
     if (mqttClient.connect(clientId.c_str())) {
       Serial.println("Connected.");
       // subscribe to topic      
     }
 }
}
 
void setup() {
 Serial.begin(9600);
 connectToWiFi();
}
 
void loop() {
 
 if (!mqttClient.connected())
   reconnect();
  mqttClient.loop();
 
 
 // Publishing data to MQTT
 long now = millis();
 if(now - lastime > 10000) {
   Serial.println("Publishing data..");
   // read temperature from sensor
   mqttClient.publish("/esp8266/temperature", data);
   // read humidity from sensor
   mqttClient.publish("/esp8266/humidity", data);
   lastime = now;
 }
 
}

Let us analyze the code. In line 3, we import the definitions to use the Pubsubclient. Next in line 5, it is necessary to define the MQTT broker IP address. We will see later how to install the MQTT broker on Raspberry Pi. Then, in line 16, we define the MQTT client:

PubSubClient mqttClient(mqttServer, 1883, callback, wifiCliient);

where 1883 is the MQTT port and the callback is the function to call when the ESP8266 receives a message through the MQTT. By now we can skip it, we will use this option later when the ESP8266 will subscribe the to MQTT channel. In the reconnect() method, we handle the connection to the MQTT and the disconnection event. Finally, in line 63 and 65, we publish data acquired by the DHT11 sensor, using two different MQTT channels:

  • /esp8266/temperature
  • /esp8266/humidity

Connecting ESP8266 to DHT11 and publish data

Once, the ESP8266 MQTT client to publish data is ready, we can focus our attention on connecting the ESP8266 to the DHT11 sensor to acquire temperature and humidity.

#include <Adafruit_Sensor.h>
#include <DHT.h>

#define DHT_TYPE DHT11
#define DHT_PIN D5

DHT dht(DHT_PIN, DHT_TYPE);
char data[100];

void reconnect() {
 Serial.println("Connecting to MQTT Broker...");
 while (!mqttClient.connected()) {
     Serial.println("Reconnecting to MQTT Broker..");
     String clientId = "ESP8266Client-";
     clientId += String(random(0xffff), HEX);
    
     if (mqttClient.connect(clientId.c_str())) {
       Serial.println("Connected.");
       // subscribe to topic  
	   mqttClient.subscribe("/esp8266/commands");	   
     }
 }
}

void setup() {
 Serial.begin(9600);
 connectToWiFi();
 dht.begin();
 Serial.println("DHT11 sensor....");
}

void loop() {
 
 if (!mqttClient.connected())
   reconnect();
  mqttClient.loop();
  
 // Publishing data to MQTT
 long now = millis();
 if(now - lastime > 10000) {
   Serial.println("Publishing data..");
   float temp = dht.readTemperature();
   float hum = dht.readHumidity();
   sprintf(data, "%f", temp);
   Serial.println(data);
   mqttClient.publish("/esp8266/temperature", data);
   sprintf(data, "%f", hum);
   Serial.println(hum);
   mqttClient.publish("/esp8266/humidity", data);
   lastime = now;
 }
}

The code above completes the development fo the ESP8266 MQTT client. This client publishes the DHT11 sensor readings using two different MQTT channels. Moreover, it sends data every 10 seconds.

How to develop the ESP8266 MQTT client to subscribe to MQTT channel

In this second part of this ESP8266 tutorial, we will analyze how to develop an ESP8266 MQTT client that subscribes to an MQTT channel so that the ESP8266 can receive commands. In this scenario, we will these commands to control an LED turning it on or off. Later, we will develop the dashboard using Node-red running on Raspberry Pi to command the LED. Therefore, the picture below shows the scenario we want to develop:

ESP8266 MQTT client that subscribes to the MQTT channel

As described in the picture above, trough the dashboard built using Node-red and Mosquitto we will send commands to the ESP8266 that subscribes to the command channel. In this case, ESP8266 MQTT client receives data through the MQTT channel while in the first scenario the ESP8266 MQTT client sends data.

The code is almost the same as shown in the previous scenario. Anyway, in this context, it is necessary to implement the callback function that is invoked when the ESP8266 receives data through the MQTT channel. Therefore, it is necessary to implement the function callback. In this method, we will implement the logic to turn on or off the LED connected to the ESP8266. The code is trivial. It is necessary to implement the callback method:

void callback(char* topic, byte* payload, unsigned int length) {
 Serial.println("Callback");
 Serial.println((char) payload[0]);
  // using payload[0] == 't' or 'f' turn or off the LED
}

How to develop a Node-red UI dashboard to publish and receive data through MQTT

Finally, in this last part of this project, we will implement a Node-red UI dashboard. This dashboard will receive data published by the ESP8266 MQTT client on the channels /esp8266/temperature and /esp8266/humidity. Conversely, the Node-red UI dashboard publishes data to the /esp8266/commands channel where the ESP8266 MQTT client is subscribed. As stated before, the Node-red and Mosquitto run on Raspberry Pi. Let us see how we can install and configure them.

Installing Mosquitto on Raspberry Pi

The Mosquitto installation is very simple. We will use Docker to install it:

sudo docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto 

It will run the Mosquitto MQTT broker that listens on port 1883.

Installing Node-red on Raspberry Pi

Next, we have to install Node-red. In the same way, we did before, we use Docker:

sudo docker run -p 1880:1880 nodered/node-red -v /home/pi/.node-red:/data

Node-red will run on port 1880. Then, open your browser and connect to the Node-red interface. Before connecting the Node-red to the MQTT broker, we have to import the dashboard UI nodes. You can do it using the Palette menu.

Creating Node-red UI

Once, the Node-red is installed, we can create the flow that should look like the one shown in the picture below:

Node-Red MQTT flow with ESP8266

Below the file json to import that creates the flow shown above:

{"id":"62754c3f.ea8df4","type":"ui_chart","z":"43827484.221c5c","name":"Temperature","group":"6ce5a9c7.9482d8","order":0,"width":0,"height":0,"label":"Temperature","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"40","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":630,"y":380,"wires":[[]]},{"id":"6ce5a9c7.9482d8","type":"ui_group","z":"","name":"Control","tab":"3f223f3f.02ae8","disp":true,"width":"6","collapse":false},{"id":"3f223f3f.02ae8","type":"ui_tab","name":"Tab 1","icon":"dashboard","order":1}]

As you can see from the picture above there are three UI nodes:

  • Switch that will use to command the LED
  • A gauge that will show the humidity
  • Chart that will show the temperature

Moreover, there are three different nodes:

  • a node that publishes data (from the switch) to /esp8266/commands where the MQTT client is subscribed
  • two MQTT channels where the ESP8266 MQTT client publishes data coming from DHT11 sensor.

Next, let us deploy the flow to the Node-red server and let us show the UI dashboard. The result is:

Node-red UI dashboard from data sent using ESP8266 MQTT client

Wrapping up

In conclusion, at the end of this tutorial, you, hopefully, gained knowledge about how to develop the ESP8266 MQTT client. We saw how to connect the ESP8266 to the MQTT broker and how to use the ESP8266 to subscribe to MQTT channels. Moreover, we discovered that we can use the ESP8266 MQTT client to publish data coming from sensors. In the end, this tutorial covered how to build a Node-red UI dashboard that connects to the MQTT broker to visualize data.

LEAVE A REPLY

Please enter your comment!
Please enter your name here