ESP8266 MQTT Client: Publish and subscribe

This tutorial covers how to develop an ESP8266 MQTT client to publish and subscribe to MQTT topics. Therefore, we will connect the ESP8266 to an MQTT broker and later we will create a NodeRed dashboard that visualizes using a dashbard sensor readings.

In this guide you will learn:

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

ESP8266 MQTT Client project overview

There are two different scenarios where we can use an ESP8266 MQTT client:

  1. to publish data
  2. to subscribe to an MQTT channel.

Publishing data via MQTT

In this scenario, the ESP8266 MQTT client connects to an MQTT broker running on a Raspberry Pi via MQTT protocol and publishes sensor readings. Using this information we will build a NodeRed dashboard to visualize sensor readings using charts. You can use the same project to connect to other MQTT broker, for example, the ESP8266 can connect to an IoT platform that supports MQTT protocol (Google Cloud, Ubitods, AWS IoT and so on).

Subscribing to an MQTT channel

In the second scenario, we will build a Node-RED UI to control a remote LED connected to the ESP8266. In this case, the ESP8266 subscribes to an MQTT channel to receive data.

Prerequisites

To follow this guide you must be familiar with the MQTT protocol.

Recommended:
MQTT Protocol Tutorial: Technical description, MQTT security
ESP32 MQTT client: Publish and Subscribe. HiveMQ and BME280 example

Moreover, you need the following components:

  • ESP8266
  • DHT11 sensor to read temperature and humidity
  • one LED

Optional components:

  • Raspberry Pi
  • Node-RED installed on yuor Raspberry PI
  • Mosquitto MQTT broker

How to publish data using ESP8266 via MQTT

To implement the first scenario where ESP8266 published data via MQTT, we can suppose that we want to publish DHT11 sensor readings to Mosquitto broker. Considering that we publish temperature and humidity, the ESP8266 publishes these two pieces of information using two different MQTT channels.

The picture below clarifies it:

ESP8266 MQTT publishing data to Mosquitto running on Raspberry Pi

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 ESP8266 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 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 wifiClient = 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;
 }
 
}

Code description

  • Line 3, we import the definitions to use the Pubsubclient.
  • Line 5, we define the MQTT broker IP address where the ESP8266 connects to.
  • Line 16, we create the PubSubClient MQTT client:
PubSubClient mqttClient(mqttServer, 1883, callback, wifiClient);

1883 is the MQTT broker port

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, the code handles the connection to the MQTT and the disconnection event.

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 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 data (such as commands).

In this scenario, we can suppose our device receives 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, we will send commands to the ESP8266 that subscribes to the command channel. In this case, the MQTT client receives data through the MQTT channel while in the first scenario the ESP8266 publishes data.

Now it should be clear the main difference between publishing data and subscribing to a channel.

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:

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.

Let us see how we can install and configure them.

Installing Mosquitto on Raspberry Pi using Docker

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 using Docker

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 runs 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

In this step, we create the Node-RED 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

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