ESP8266 with mqtt 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.
Also, learn how to make android application for same esp8266 and mqtt project.
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.
- Single Level
- 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
- Never start with leading forward slash.
home/room1, is good practice but /home1/room1 is not. - Never use spaces in topics.
- Keep the topic short and concise.
- Use only ASCII characters, don’t use non printable characters.
- Don’t just subscribe to #. It sounds easy but don’t be lazy.
- 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.
Buying guide
Development board | Amazon (US) | Ali express |
---|---|---|
ESP32 | ||
Raspberry pi zero | ||
Raspberry pi 4 | ||
ESP8266 | ||
DHT11 |
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.
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.
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.
REYAX Technologies has been making IoT Products, you can check that by visiting their website.
Here are few reasons to use REYAX RYC1001 MQTT IoT Cloud,
- Built on stable AWS service.
- Database to store, search and modify data.
- 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,
- Set MQTT url and communication port.
- Set username , password, and client id.
- Connect and login.
- ESP8266 will subscribe to api/command/<network id>/# to receive command to turn on and off LED.
- ESP8266 will read DHT11 data and publish it on api/request.
- 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.
- 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.
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.
- The VCC will be connected to 3.3V of esp8266.
- The GND will be connected to esp8266 GND.
- The SIGNAL/DATA will be connected to the D1 pin of ESP8266.
The LED has two terminals, cathode, and Anode.
- Connect Anode with D2 of ESP8266.
- NodeMCU GND connects with LED cathode.
And Esp8266 will connect to the MQTT cloud using the router as a gateway.
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.
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!