How to MQTT?

How to use ESP8266 with MQTT Cloud

Support us by sharing

ESP8266 Publish/subscribe to Cloud | MQTT is a blog of HOW TO MQTT series.

In which we will discuss how we can use ESP8266 to subscribe and publish data on a MQTT cloud.

we already explained the local mqtt broker made up of raspberry pi to make communication between ESP8266 and Raspberry pi.

In this blog, we will do the same thing we did last time. But we will use MQTT cloud instead of a local MQTT broker.

We will start this blog by discussing some information about MQTT topics and the best practice to use it.

MQTT TOPICS

 In our previous blogs we discussed what topic is, the MQTT broker uses the topic of a message to decide which client receives which message.

we used single word topics such as “temp” to receive and send messages but this is not a good practice if you have 100s of sensors at different places as it will be hard to differentiate the data.

MQTT TOPIC Levels and Seperator

The recommended way to manage and differentiate the data is to use topic levels.

So, Let me explain the topic levels.

Consider, you need to retrieve data from 3 houses. Each house has 2 rooms. Each room is equipped with 2 temperature sensors.

If we decide the topic names as temperature1, temperature 2 etc. It will be hard to differentiate the data and you will need to remember which topic represents which temperature sensor of which house.

So to remove this complexity, we can use topic levels and we can describe our topic in the following ways,


home1/room1/temp1
home1/room1/temp2
home1/room2/temp1
.
.
.
.
home3/room2/temp2

In that way, it is very easy to differentiate the topics. Also, it will be easy if we will need to add more topics.

“/” is used to seperate the topic levels and “home1”, “room1”, and “temp1” are the different topic levels.

Wildcards in MQTT Topics

Wildcards are another important thing we can use in MQTT Topics.

Let’s take another example. If we have hundered of devices, it will be take hundred lines of code just to subscribe to the topics.

So, wildcards comes into the game and makes our work easier. Let me explain how in the following paragraphs.

There are two types of Wildcards.

  1. Single Level
  2. Multi Level

Single level Wildcard

We use single level wildcards using “+” sign.

For example, if you subscribe to home1/+/temp1. It will subscribe to the following topics.

home1/room1/temp1
home1/room2/temp1
home1/room3/temp1

home1/+/temp1 means the first temperature sensor of first house in all the rooms.

So, subscribe to one topic and you will get subscription to 3 topics. Fair deal , isn’t ?

If not, we can use the multilevel wildcard.

Multi level Wildcards

For multilevel wildcards, we use “#”.

For example, if you subscribe to home1/#. It will subscribe to the following topics.

home1/room1/temp1
home1/room1/temp2
home1/room2/temp1
.
.
.
home1/room3/temp2

That means, subscribing to home1/# will help us subscribe to all the temperature sensors in all the rooms of home1.

Sounds easy and good , right ?

Here are few more tips to consider while defining the MQTT topics.

Tips to use MQTT Topics in a best way

  1. Never start with leading forward slash.
    home/room1, is good practice but /home1/room1 is not.
  2. Never use spaces in topics.
  3. Keep the topic short and concise.
  4. Use only ASCII characters, don’t use non printable characters.
  5. Don’t just subscribe to #. It sounds easy but don’t be lazy.
  6. Use specific topics not general one. It will help you to differentiate the topics.

We discussed MQTT topics because we will need this information while using the MQTT cloud.

Local MQTT broker VS MQTT broker on cloud

I have been using Local Mqtt broker and MQTT broker on cloud alot in this blog.

So, before starting i think it will be better to explain the difference between them.

Local MQTT Broker, which we used in last project is a MQTT broker within the network. That means, All the devices and things should be in the same network.

Local MQTT broker

Whereas, On the other hand, MQTT broker on cloud is a broker on cloud. That means, It does not matter where you are . You will just need internet connection to connect to the broker.

It does not matter where your ESP8266 and MQTT cloud is.

esp8266 mqtt cloud
Mqtt broker on cloud

Talking about the cloud services, there are so many clouds available in the market.

But for this video we will use RYC1001 MQTT IoT cloud by REYAX Technologies.

REYAX RYC1001 MQTT IoT Cloud

As we have already discussed, RYC1001 is a product of REYAX Technologies.

RYC1001 MQTT cloud, which we are using in our esp8266 project
RYC1001 Cloud by REYAX Technologies

REYAX Technologies has been making IoT Products, you can check that by visiting their website.

REYAX Technologies, maker of RYC1001 MQTT cloud
REYAX Technologies

Here are few reasons to use REYAX RYC1001 MQTT IoT Cloud,

  1. Built on stable AWS service.
  2. Database to store, search and modify data.
  3. Low cost access to the cloud.

The next question is, How we are going to use RYC1001 Cloud in our project.

And here is the answer in form of the operation flow of our project.

How we will use RYC1001 MQTT Cloud in our ESP8266 project

The first thing is to buy the RYC1001 cloud and they will provide you some credentials.

After you got the credentials, you can follow the following steps,

  1. Set MQTT url and communication port.
  2. Set username , password, and client id.
  3. Connect and login.
  4. ESP8266 will subscribe to api/command/<network id>/# to receive command to turn on and off LED.
  5. ESP8266 will read DHT11 data and publish it on api/request.
  6. Python, which we are using to test our publish subscribe will subscribe to api/notification/<network id>/# to receive DHT11 notifications , published by esp8266 on topic api/request.
  7. In python, we will publish the command for turning on and off the led on the topic api/request.

Another question arises.

ESP8266 is publishing data on api/request which is received by python on the topic api/notification/<network id>/#.

Python is publishing the data on api/request that is the same topic, but the esp8266 receives that data on api/command/<network id>/# , How ?

The answer is because the message format differs.

We are sending and recieving the data in JSON format.

Obviously, we can use single word topic like last time. But that is not a good practice and then we will not be able to get database benifits of the cloud.

The following message format will explain the point i have mentioned above.

ESP8266 is publishing message in this format

{
  "action": "notification/insert",
  "deviceId": "<device Id>",
  "notification": {
    "notification": "temperature",
    "parameters": {
      "temp": "temp value",
      "humi": "humidity value"
    }
  }
}

Esp8266 publish above data on topic api/request.

In the above JSON code, we can see action is notification/insert.

Cloud will insert the data in database. Also, it will publish a message on api/notification/<network id> topic, which will recieve by python.

Python is publishing message in this format

{
  "action": "command/insert",
  "deviceId": "<deviceId>",
  "command": {
    "command": "LED_control",
    "parameters": {
      "led": "<status>"
    }
  }
}

Python Publishes data on topic api/request as well.

In the above code, the action is command/insert.

So the data will be added to cloud database and cloud will publish message on api/command/<network id>.

Which will recieved by ESP8266 to control the LED. Because it is subscribing to it.

GUI for esp8266 mqtt cloud
GUI on Python which shows recieved data

Circuit Diagram

DHT sensor has three terminals or four terminals. The four terminals DHT11 mostly have 1 terminal NC or Not connected. The other 3 terminals are VCC, SIGNAL/DATA, and GND.

  1. The VCC will be connected to 3.3V of esp8266.
  2. The GND will be connected to esp8266 GND.
  3. The SIGNAL/DATA will be connected to the D1 pin of ESP8266.

The LED has two terminals, cathode, and Anode. 

  1. Connect Anode with D2 of ESP8266.
  2. NodeMCU GND connects with LED cathode.

And Esp8266 will connect to the MQTT cloud using the router as a gateway.

circuit for esp8266 mqtt cloud
Nodemcu DHT circuit diagram

Code

#include <Adafruit_Sensor.h> //Library for Adafruit sensors , we are using for DHT
#include <DHT_U.h> //DHT library which uses some func from Adafruit Sensor library
#include <ESP8266WiFi.h> //library for using ESP8266 WiFi 
#include <PubSubClient.h> //library for MQTT
#include <ArduinoJson.h> //library for Parsing JSON

//defining Pins
#define DHTPIN 5
#define LED D2

//DHT parameters
#define DHTTYPE    DHT11     // DHT 11
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

//MQTT Credentials
const char* ssid = "SSID";//setting your ap ssid
const char* password = "Password";//setting your ap psk
const char* mqttServer = "iot.reyax.com"; //MQTT URL
const char* mqttUserName = "MQTT username";  // MQTT username
const char* mqttPwd = "Password";  // MQTT password
const char* clientID = "username0001"; // client id username+0001
const char* topic = "api/request"; //publish topic

//parameters for using non-blocking delay
unsigned long previousMillis = 0;
const long interval = 5000;

String msgStr = "";      // MQTT message buffer

float temp, hum;


//setting up wifi and mqtt client
WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

}

void reconnect() {
  while (!client.connected()) {
    if (client.connect(clientID, mqttUserName, mqttPwd)) {
      Serial.println("MQTT connected");
      client.subscribe("api/command/37/#");
      Serial.println("Topic Subscribed");
    }
    else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);  // wait 5sec and retry
    }

  }

}

//subscribe call back
void callback(char*topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.print("Message size :");
  Serial.println(length);
  Serial.println();
  Serial.println("-----------------------");

  StaticJsonDocument<256> doc; //read JSON data
  deserializeJson(doc, payload, length); //deserialise it
  JsonObject command = doc["command"]; //get the values of command parameter

  int command_parameters_led = command["parameters"]["led"]; //get value of led, which will be 1 or 0

  if (command_parameters_led == 1) {
    Serial.println("LED");
    digitalWrite(LED, HIGH);
  }
  else {
    digitalWrite(LED, LOW);
  }
}


void setup() {
  Serial.begin(115200);
  // Initialize device.
  dht.begin();
  // get temperature sensor details.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  setup_wifi();

  client.setServer(mqttServer, 1883); //setting MQTT server
  client.setCallback(callback); //defining function which will be called when message is recieved.

}

void loop() {
  if (!client.connected()) { //if client is not connected
    reconnect(); //try to reconnect
  }
  client.loop();

  unsigned long currentMillis = millis(); //read current time

  if (currentMillis - previousMillis >= interval) { //if current time - last time > 5 sec
    previousMillis = currentMillis;

    //read temp and humidity
    sensors_event_t event;
    dht.temperature().getEvent(&event);


    if (isnan(event.temperature)) {
      Serial.println(F("Error reading temperature!"));
    }
    else {
      Serial.print(F("Temperature: "));
      temp = event.temperature;
      Serial.print(temp);
      Serial.println(F("°C"));
    }
    // Get humidity event and print its value.
    dht.humidity().getEvent(&event);
    if (isnan(event.relative_humidity)) {
      Serial.println(F("Error reading humidity!"));
    }
    else {
      Serial.print(F("Humidity: "));
      hum = event.relative_humidity;
      Serial.print(hum);
      Serial.println(F("%"));
    }

    msgStr = "{\"action\": \"notification/insert\",\"deviceId\": \"s3s9TFhT9WbDsA0CxlWeAKuZykjcmO6PoxK6\",\"notification\":{\"notification\": \"temperature\",\"parameters\":{\"temp\":" + String(temp) + ",\"humi\":" + String(hum) + "}}}";
    byte arrSize = msgStr.length() + 1;
    char msg[arrSize];

    Serial.print("PUBLISH DATA:");
    Serial.println(msgStr);
    msgStr.toCharArray(msg, arrSize);
    client.publish(topic, msg);
    msgStr = "";
    delay(50);

  }

}

github: https://github.com/HighVoltages/ESP8266-with-MQTT-Cloud/

Code and Project Description

In the following video, I have explained the each line of code and you can watch the build of this project in the video. Make sure to subscribe to me on youtube so you can follow the complete How to MQTT series.

esp8266 mqtt cloud

Conclusion

In this blog we learned to use MQTT protocol in ESP8266.

We used the Cloud MQTT broker RYC1001 to control the LED from a GUI made in Python and also published the DHT sensor data. 

Cheers!

Summary
ESP8266 PUBLISH/SUBSCRIBE TO MQTT CLOUD
Article Name
ESP8266 PUBLISH/SUBSCRIBE TO MQTT CLOUD
Description
In this blog, we will learn how to subscribe and publish MQTT messages using ESP8266 (NodeMcu) to the MQTT cloud RYC1001.
Author
Publisher Name
High Voltages
Publisher Logo
Support us by sharing

Comments (1)

  1. […] How to use ESP8266 with MQTT Cloud March 26, 2021 […]

Leave a Reply

%d bloggers like this: