CC Blog Projects Research & Design Hub

Build Your Own IoT Platform – Part 2: Connecting to Devices

Dhairya continues his article series on how to build your own IoT platform. Here, in Part 2, he explains how to use the MQTT and Node-RED features of the platform backend you set up in Part 1 to build your first IoT project that controls relays through a Node-RED dashboard.

  • How to use the MQTT and Node-RED features of the platform backend you set up in Part 1

  • How to set up the hardware for your IoT project

  • How to do the coding for your IoT project

  • How each of the major program functions work

  • How to set up the IoT platform

  • NodeMCU development board

  • 4-channel Relay module

  • DHT11 sensor

  • Breadboard and connecting wires

  • Node-RED

  • MQTT Broker

Last month, in Part 1 (Circuit Cellar 371, June 2021) [1], we set up our very own IoT platform. Just to refresh your memory, these are the steps we went through in that article:

1) Digital Ocean Droplet setup
2) Installing Apache, PhpMyAdmin and MySQL.
3) Installation of Node.js, Node-RED and the Mosquitto MQTT library

Here, in Part 2, we will use the MQTT and Node-RED features of our platform to build our first project! The project demonstrates both the control and monitoring capabilities of our platform, enabling us to control relay modules (in other words, the appliances connected to these modules) through a Node-RED dashboard we create. It also monitors sensor values from the same dashboard.

According to Wikipedia, the definition of home automation is as follows:
“Home automation is building automation for a home, called a smart home or smart house. A home automation system will monitor and/or control home attributes such as lighting, climate, entertainment systems, and appliances. It may also include home security such as access control and alarm systems. When connected with the Internet, home devices are an important constituent of the Internet of Things (“IoT”).”

In simple terms, it is the ability to control and monitor home appliances wirelessly through a dashboard or a mobile application. Even smart speakers like Google Home or Amazon Echo (Alexa) can be used to control the appliances. But here we’ll stick with the simplest form of home automation: one controlled by the dashboard that we will create. In short, the aim of this article is to build a simple project that uses our IoT platform (from Part 1) for both monitoring and control purposes.

HARDWARE SETUP

First let’s prepare our hardware. For this article, we’re building a fairly simple project—one that anyone can easily learn from and comfortably implement. Figure 1 shows all the required components. Here’s a brief summary:

— ADVERTISMENT—

Advertise Here

Figure 1 Required components to build the hardware for our project. They include a NodeMCU board, a 4 channel relay module, a DHT11 sensor and connecting wires.
Figure 1
Required components to build the hardware for our project. They include a NodeMCU board, a 4 channel relay module, a DHT11 sensor and connecting wires.

NodeMCU development board: This is the “brain” of our project. It is based on the popular Espressif Systems ESP8266 chip and the principal feature of this chip is Wi-Fi support. The board connects to the hardware peripherals and to our IoT platform dashboard through MQTT.

4-channel Relay module: To demonstrate the control capabilities of our platform, we will be using a 4-channel relay module, which is used in practical applications too. You can use a simple relay or solid-state relay module. We will control these relays through toggle switches on our dashboard.

DHT11 sensor: This is a temperature and humidity sensor, available from Adafruit. The NodeMCU board periodically fetches the sensor values and sends it to our platform so that we can monitor them in real time.

Breadboard and connecting wires: To assemble all the components in a nice and presentable manner, we use a breadboard and jumper wires to connect all the component pins.

After all the required components have been collected, it’s time to connect them to make the hardware module for our project. The connections should be made according to Figure 2. Note that there is no separate power source for the relays or the sensor. All the components will be powered by the NodeMCU board, which is powered using a micro USB connection. Once all the hardware connections have been made, the final hardware looks as shown in Figure 3.

Figure 2 Diagram for the Hardware connections. This is how we connect all our hardware components. Relays are used to control appliances and DHT11 sensor for collecting temperature and humidity data.
Figure 2
Diagram for the Hardware connections. This is how we connect all our hardware components. Relays are used to control appliances and DHT11 sensor for collecting temperature and humidity data.
Figure 3 The assembled hardware module. This is a breadboard setup but the same can be done on a perf board with some normal soldering.
Figure 3
The assembled hardware module. This is a breadboard setup but the same can be done on a perf board with some normal soldering.
THE CODING

The next step is the coding part of the project. But before going into those details, let’s look at how our project actually works. Take a look at Figure 4 which shows the overall project flow diagram. The final code for this project can be found in the GitHub repository [2] created for this article. The link is provided in RESOURCES at the end of this article. To make this all easier to understand, I’ve broken the code here into small snippets and we will go through each of them.

Figure 4 Flow diagram showcasing how the whole project operates—the roles of the hardware and software components in the project.
Figure 4
Flow diagram showcasing how the whole project operates—the roles of the hardware and software components in the project.

This article assumes that you have your Arduino IDE environment installed and set up to program the NodeMCU development board. A reference link to a very good blog on this topic is available at [3]. Let’s start with the code explanation.

// Importing all the required Libraries
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

// defining permanent value variable for DHT Type.
#define DHTTYPE DHT11

This snippet is to import all the required libraries for this project. The first two libraries come pre-installed with the ESP8266 development package. To install the DHT library, just follow these steps:

First, go to Sketch > Include Library > Manage Libraries. After the window opens, search “DHT Sensor” in the search bar and you will see “DHT Sensor Library by Adafruit” as the first option. Press the Install button.

— ADVERTISMENT—

Advertise Here

The DHT sensor library uses the Adafruit sensor support backend. So, search the library manager for “Adafruit Unified Sensor” and install that too (you may have to scroll a bit). Finally, define the type of DHT sensor you will be using. For this project, we will be using a DHT11 sensor.

// 1. WiFi Credentials
const char* ssid = "wifi_ssid";
const char* password = "wifi_pass";

// 2. MQTT Broker Credentials
const char* mqtt_server = "mqtt_broker_ip";

Next, we need to modify the above lines because they are the network credentials. The first two lines are the Wi-Fi credentials and the last line is the IP address of our IoT platform. The MQTT Broker also runs on the same address on port 1883, as discussed in the first article.

The next step is to create Wi-Fi and publish/subscribe clients for our board—WiFiClient and PubSubClient. This is shown in Listing 1. We will be using this client object to connect to the Wi-Fi and the MQTT Broker. Then we initialize the pins on which the relay modules and the DHT sensor is connected. We will also initialize some variables for the timer. Finally, we create an object for our DHT sensor class so that we can access the required functions—which simply means fetching the sensor data.

Listing 1

This code creates a Wi-Fi client and a publish/subscribe client for our board.

WiFiClient espClient;
PubSubClient client(espClient);

uint8_t switch1 = D0;
uint8_t switch2 = D1;
uint8_t switch3 = D2;
uint8_t switch4 = D3;
uint8_t DHTpin = D5;
long now = millis();
long lastMeasure = 0;

DHT dht(DHTpin, DHTTYPE);    // Initialize DHT sensor.
CALLBACK FUNCTION

The callback() function for our MQTT network is shown in the top part of Listing 2. This is the function that handles the data which the client receives on the subscribed channels. After the message has been received, we check on which topic the message has. According to the topic (in our case switch_1, switch_2 and so on), we send a HIGH or LOW signal to the particular pin. The state depends on the received value. As shown in the bottom part of Listing 2, if we send 1, the switch turns on (NodeMCU pins are low activated) and the switch turns off when it receives 0 on the same topic. Note that you will have to repeat this for all four relays. The only requirement is to change the topic name and the pin that is to be controlled by that topic.

The reconnect() function is very useful when dealing with MQTT. If, for some reason, our node disconnects from the MQTT Broker, this function helps it reconnect to the Broker which prevents connectivity issues and prevent data loss. The reconnect() function is shown in Listing 3. The function does the following: First it checks if the client is connected. If not, it attempts to establish a connection to the Broker again using a random client id. If the connection is successful, it subscribes to all the topics we are interested in. If it cannot connect, it will show the error code and try to reconnect again after 5 seconds.

The setup_wifi() function (Listing 4) is written to connect to a specific Wi-Fi network whose credentials have been defined as constant variables. The Wi-Fi setup function is a very simple function, which uses the built-in functions of the ESP8266 Wi-Fi library to connect to a specified SSID and password pair. Once a connection has been established, it will also print the IP address of our device on the Serial Monitor.

The code snippet in Listing 5 deals with setting up the relay pin mode to output, initiating the DHT sensor, turning off all the Relay pins initially and finally starting a serial communication interface with a baud rate of 115200.

The setup function (shown in Listings 6 and 8) is similar to a main() function. All the final setups, essential function calls, initializations, etc is done in this function.

The next step is to connect to the Internet using the setup_wifi () function and then tell the PubSubclient the MQTT Broker IP address and what function to use to handle the subscribed topic data (for example, callback() function). This is shown in the top part of Listing 6. The middle snippet in Listing 6 is used to connect our Device to the MQTT Broker of our IoT Platform. And the bottom part of Listing 6 is where we subscribe to the topics in which we are interested.

The loop() function (Listing 7) is the function that keeps running on the development board. We will do the following tasks in this function (for this particular project only):

1) Send the DHT Sensor readings every 2 seconds.
2) Make sure our device is connected to MQTT Server. If not, call the reconnect() function.

Finally, in Listing 8, we compute the temperature and humidity values using the functions of the DHT library. Then we convert these values to strings using the dtostrf function and then publish these values on the topics (we also print the values on the serial monitor):

monitor/temperature
monitor/humidity

This concludes the code explanation part of this article. Next, we will setup our IoT platform.

Listing 2
Shown here is the callback() function for our MQTT network (top snippet) and the-code for checking and the topics and switching states of the pins (bottom snippet).

void callback(String topic, byte* message, unsigned int length) 
{
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) 
  {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println(); 

The first lines in the above snippet print the topic from which the message is received and also prints the message body on the Serial Monitor. But we want to control the relays according the received messages. This is done using this next snippet:

if(topic == "control/relay_1")
  {
      Serial.print("Changing Switch 1 to ");
      if(messageTemp == "1"){
        digitalWrite(switch1, LOW);
        Serial.print("On");
      }
      else if(messageTemp == "0"){
        digitalWrite(switch1, HIGH);
        Serial.print("Off");
      }
  }
Listing 3
The reconnect() function first checks if the client is connected. If not, it attempts to establish a connection to the Broker again using a random client ID. If the connection is successful, it subscribes to all the topics in which we are interested.

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect

    if(client.connect("test_client_1")) 
    {
      Serial.println("connected");
      client.publish("outTopic", "Reconnected!");

      client.subscribe("control/relay_1");
      client.subscribe("control/relay_2");
      client.subscribe("control/relay_3");
      client.subscribe("control/relay_4");
    } 
    else 
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
Listing 4

The Wi-Fi setup function is written to connect to a specific Wi-Fi network whose credentials have been defined above as constant variables.

void setup_wifi()
{
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    Serial.println(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}
Listing 5
This code snippet deals with the relay pins and the serial communications interface.

// GPIO mode set and initilization---------------------
  
  pinMode(switch1, OUTPUT);
  pinMode(switch2, OUTPUT);
  pinMode(switch3, OUTPUT);
  pinMode(switch4, OUTPUT);
  dht.begin();

  //Turn all of them off initially : LOW ACTIVE
  digitalWrite(switch1, HIGH);
  digitalWrite(switch2, HIGH);
  digitalWrite(switch3, HIGH);
  digitalWrite(switch4, HIGH);
  
  // --------------------------------------------------
  
  Serial.begin(115200);    // Begin the Serial Monitor
Listing 6
These code snippets deal with (top) connecting to the Internet using the setup_wifi() function, (middle) connecting our device to the MQTT Broker of our IoT platform and (bottom) subscribing to the topics in which we’re interested.

// Connect to WiFi and setup MQTT Server Credentials
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

This next snippet is used to connect our Device to the MQTT Broker of our IoT Platform. Please note that this is the simplest connection method with literally no authentication but it is perfect for testing our platform. 
If the connection is successful, a “Connected” message will be published on the outTopic topic. In case of failure, the code will try to connect to the Broker again every 2 seconds.

// Connect to our Broker
  
  while (!client.connected()) 
  {
    Serial.println("Connecting to MQTT...");
     
    if (client.connect("test_client_123")) 
    {
      client.publish("outTopic", "Connected!");
      Serial.println("connected");  
    } 
    else 
    {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }

Finally, after a connection to our IoT platform MQTT Broker has been established, we just subscribe to the topics we are interested in. These topics will be used to control each relay in the relay module.

// Subscribe to all the relay related topics. 
  client.subscribe("control/relay_1");
  client.subscribe("control/relay_2");
  client.subscribe("control/relay_3");
  client.subscribe("control/relay_4");
Listing 7

The loop() function sends DHT sensor readings every two seconds and makes sure our device is connected to the MQTT server.

We will first check if the device is connected to our MQTT Broker. If not, we will call the reconnect() function till a connection has been applied.

void loop() 
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

This next snippet is used to fetch the humidity and temperature value from the DHT11 sensor every 2 seconds. There is an "if" condition that helps identify if there is a problem with our DHT sensor.

now = millis();
  // Publishes new temperature and humidity every 2 seconds
  if (now - lastMeasure > 2000) 
  {
    lastMeasure = now;
    
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    
 
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) 
    {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
Listing 8

In this code snippet we compute and publish temperature and humidity values.

// Computes temperature values in Celsius
    float hic = dht.computeHeatIndex(t, h, false);
    static char temperatureTemp[7];
    dtostrf(hic, 6, 2, temperatureTemp);
    
    static char humidityTemp[7];
    dtostrf(h, 6, 2, humidityTemp);
 
    // Publishes Temperature and Humidity values
    client.publish("monitor/temperature", temperatureTemp);
    client.publish("monitor/humidity", humidityTemp);
    
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
}
IoT PLATFORM SETUP

This article assumes that you have setup your own IoT platform according to Part 1 of this article series. With that in mind, your IoT platform should have the following:

• Node-RED installed and running
• MQTT Broker (mosquitto) installed and running

— ADVERTISMENT—

Advertise Here

Our next step is to create a dashboard for our project using Node-RED. This will also include using our MQTT Broker to establish a connection between our device and the IoT platform. First, start an instance of your server in PuTTY using SSH so you have access to the command line, if required. If you have set Node-RED to launch on start-up, you can proceed without doing anything to your browse. Type the provided IP address followed by a “:” and port number 1880.

< Your IP Address >:1880

After that, you will see the Node-RED home screen as shown in Figure 5. Our main aim is to set up a dashboard for our project. For that, we need the Node-RED dashboard extension, which does not come pre-installed. To install that, first open the menu by pressing the 3-bar icon on the top right side of the screen, then select the Manage Palette option. This will open a new window with two main sections: Nodes and Install. Select the Install section and it will change the main window. In the search bar, type “dashboard” and you will see the option node-red-dashboard on the screen (Figure 6). Install that extension and this completes installation of all the prerequisites for this project.

Figure 5 Node-RED home page when opening the following web address: <Your Droplet IP>:1880.
Figure 5
Node-RED home page when opening the following web address: :1880.
Figure 6 Shown here is the Node-RED palette search results for “dashboard”. Install the second option node-red-dashboard for this project.
Figure 6
Shown here is the Node-RED palette search results for “dashboard”. Install the second option node-red-dashboard for this project.

Now, we need to set up MQTT. First, we set up MQTT topics for our relay module and the DHT sensors. For that, we have the MQTT In and MQTT Out blocks. We will use the MQTT Out block for relays (because we want to publish the state on the topic) and the MQTT In block for the DHT sensors (because we want to fetch the sensor values from the client).

First, drag four MQTT Out blocks and two MQTT In blocks onto the main Flow screen. Once that’s done, the next step is to set up the MQTT Broker credentials for each MQTT block. This is very easy because you just need to setup the Broker for one block and these credentials are automatically applied to all the other blocks. To setup the credentials, open any MQTT block, then, in the Server option, press on the drop-down menu and select the Add New MQTT Broker option and press the pencil icon on its right. This will open a new window. On top, you will see the Name option. I call mine “MQTT Broker” but you can give it any name you choose. The only other option you need to fill in is the Server. In this box, you need to type in the IP address of the virtual server on which your IoT platform is running. This completes the MQTT Broker setup.

Now you need to enter the following topic names to your MQTT blocks and give them names that are easy to identify.

MQTT In
 Block 1: monitor/temperature (Temperature as block name)
 Block 2: monitor/humidity (Humidity as block name)

MQTT Out
 Block 1: control/relay_1 (Switch 1 as block name)
 Block 2: control/relay_2 (Switch 2 as block name)
 Block 3: control/relay_3 (Switch 3 as block name)
 Block 4: control/relay_4 (Switch 4 as block name)

To set up all the nodes, follow the instructions given in Figure 7 that shows how to set up each node. This completes the MQTT nodes setup for our project. At this point, we have all the MQTT publish and subscribe blocks ready, but now we need an interface to interact with them. This is where the dashboard comes into play. We will be using two components of the Node-RED-dashboard: The Gauge and Switch.

We use the Gauge to display the temperature and humidity values and the toggle switches to provide the control functionality. Setting up a dashboard in very easy in Node-RED. It just requires dropping some dashboard blocks onto the flow. For this dashboard, we will be dropping in two Gauge blocks and four Switch blocks. For setting up the Gauge and Switch blocks, refer to Figure 8. It has all the instructions required to set up each block.

Once that is done, its time to complete our flow by connecting the dashboard and MQTT components together. The final flow is shown in Figure 9. Note that you can download the JSON file for this from the GitHub repository [2] for this article. Then, just import the JSON file using the Import feature of Node-RED which can be found in the settings. Open it by pressing the 3-bar icon situated the top right side of the screen. This completes the whole setup process. Only thing left to do is see the project in action!

Figure 8 Dashboard nodes set up instructions. We use the Gauge and Switch nodes for this project. Follow the "Note" instructions to prevent any issues during testing.
Figure 7
MQTT Node set up instructions. This includes set up instructions for both the MQTT In and MQTT Out nodes. Follow the “Note” instructions to prevent any issues during testing.
Figure 8 Dashboard nodes set up instructions. We use the Gauge and Switch nodes for this project. Follow the "Note" instructions to prevent any issues during testing.
Figure 8
Dashboard nodes set up instructions. We use the Gauge and Switch nodes for this project. Follow the “Note” instructions to prevent any issues during testing.
Figure 9 Final Node-RED flow of our very first project. After deployment, you'll be able to access the dashboard on the following IP address: <Your Droplet IP>:1880/ui.
Figure 9
Final Node-RED flow of our very first project. After deployment, you’ll be able to access the dashboard on the following IP address: :1880/ui.
FINAL DEMONSTRATION

For a final demonstration, after the flow is complete, just press the Deploy button on the top right corner of the Node-RED home page (this is running on your server). Node-RED can be accessed using <Your Server’s IP Address Here>:1880. Once the flow has been deployed successfully, all you have to do is open the Node-RED dashboard by typing the following address on a new tab:

<Your Server’s IP Address Here>:1880/ui

This will open your project dashboard, which is shown in Figure 10. You will have two gauges and four control switches. Now, all you have to do is turn on the hardware (Figure 3) with the program uploaded. Once that is done, you can successfully control every relay of your device from the dashboard and also see the temperature and humidity values (monitoring) on the same dashboard.

Figure 10 Final dashboard of our project. You can see the real-time changes in temperature and humidity and control the relays of the hardware through this simple and elegant interface.
Figure 10
Final dashboard of our project. You can see the real-time changes in temperature and humidity and control the relays of the hardware through this simple and elegant interface.

This was the first project we built for our IoT platform! It helped us understand how to use MQTT as a communication bridge between our device and the platform, which is what most of the commercial platforms use. In the final part of this article series, Part 3, we will add several new features to our IoT platform, which include:

REST API development: We will create HTTP Rest API and see a small demo in which we will communicate with our NodeMCU via the REST API.

Capability to send emails: We will empower platform to send emails when a particular event takes place. For example, if the temperature value goes above 35°C degrees, the platform will send an alert email notifying the user.

Capability to send texts: We will explore how to send text messages using the Node-RED platform and Twilio. We will use a free Twilio account to send text messages to verified numbers. 

Read Part 3 Here

RESOURCES

References:
[1] Build Your Own IoT Platform, Part 1 (Circuit Cellar 371, June 2021)
[2] Project GitHub: https://github.com/Dhairya1007/IoT-Platform-Article-2-Project
[3]  https://randomnerdtutorials.com/how-to-install-esp8266-board-arduino-ide

Adafruit | www.adafruit.com
Apache Software Foundation | www.apache.org
DigitalOcean | www.digitalocean.com
Eclipse Mosquitto | www.mosquitto.org
Espressif Systems | www.espressif.com
Node-RED | www.nodered.org
PuTTY | www.putty.org

PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JULY 2021 #372 – Get a PDF of the issue

Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.


Note: We’ve made the May 2020 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

+ posts

Dhairya Parikh is an Electronics Engineer and an avid project developer. Dhairya makes projects that can bring a positive impact in a person’s life by making it easier. He is currently working as an IoT engineer. His projects are mainly related to IoT and machine learning. Dhairya can be contacted on dhairyaparikh1998@gmail.com

Sponsor this Article

Supporting Companies

Upcoming Events


Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2021 KCK Media Corp.

Build Your Own IoT Platform – Part 2: Connecting to Devices…

by Dhairya A. Parikh time to read: 16 min