• Pooja Velavan

Controlling Ceiling Light using NodeMCu, AWS, and Relay | IoT Project

IoT based Home Automation enables to control of home appliances by using the internet. This technology allows us to control or monitor any devices at any place with our fingertip. It assures energy conservation and optimized use of money and energy.


In this article, let us learn to design a simple home automation system for controlling ceiling lights by using NodeMCU, AWS, and Relay module. Let's first start with the requirements that we will need to design the IoT project.


Hardware Requirements:

1. Breadboard


Breadboard
Breadboard

A breadboard is an essential component that is in a rectangular shape with small holes in it that are used to insert the components to test the circuits. The connections are not fixed and can be varied. In a breadboard, the holes in one horizontal line are in series connection with each other. Breadboards are made from plastic or wood and come in all shapes, sizes, and even different colors, the most commonly used sizes for designing the circuits are "full-size," "half-size," and "mini" breadboards.


Buy the Breadboard from here.


2. Node MCU ESP 8266


Node MCU ESP 8266
NodeMCU ESP8266

NodeMCU is an inexpensive, open-source hardware #development board. It best suits for building the Internet of Things (IoT) projects. It has an operating voltage of 3.3Volt. It consists of 4-power pins, 4 -ground pins, I2C pins, 17-GPIO pins, UART pins, SPI pins, SDIO pins, PWM pins, and Control pins. NodeMCU uses an IDE environment to upload programs to the board by creating an Arduino add-on.


Buy NodeMCU ESP8266 from here.


3. Relay Module


Relay Module
Relay Module

In this project, a single-channel #relay module is used. The relay module is an electromagnetically operating switch. It consists of three voltage terminals in which the controlling device is connected. The pins are Normally closed (NC), Normally Open (NO), and Common terminal. And on another side, has 3 terminals it is connected to the controller board. The Three pins are the Ground pin (Gnd), Supply pin (Vcc), and the Input pin (IN).


Buy Relay Module from here.


4. Jumper Wires

Jumper Wires
Jumper Wires

These are the main components that are used to establish the connections between different devices of the circuit. There are three types male to female, female to female, and male to male.


Buy Jumper Wires from here.


5. USB Cable


USB Cable
USB Cable

This cable is used to connect the development boards to the power supply. It also helps in the transmission of data.


Buy USB Cable from here.


Software Requirements:


1. Arduino IDE


Arduino IDE LOGO
Arduino IDE LOGO

Arduino #IDE (Integrated Development Platform) which is used to interface the boards like NodeMCU to run the desired code designed to interface hardware devices.


2. Amazon Web Service (AWS)


Amazon Web Service (AWS) LOGO
Amazon Web Service (AWS) LOGO

Amazon Web Services is an inexpensive, reliable cloud service platform that allows the creation of #IoT projects. It is a flexible platform to store, compute, and secure the data.


3. OpenSSL:


OpenSSL LOGO
OpenSSL LOGO

OpenSSL tool is an open-source software used to provide a secure network connection. It is a command-line tool that generates certificates, private keys, or changes the file format.


Hardware Implementation:

Circuit Connection
Circuit Connection

The connection between the NodeMCU and the Relay Module by using jumper wires involves the following steps:

  • The Supply pin (Vcc) is connected to the 5V of the Relay module which is further connected to the Vin terminal of the NodeMCU using a Red jumper wire.

  • The Input pin (IN) is connected to the digital pin 5 of the NodeMCU using a Yellow jumper wire.

  • Finally, the ground pin (GND) is connected to the ground terminal of the NodeMCU board.

After connecting #NodeMCU with the relay, connect the ceiling light with AC load to the Normally open and the common pin of the relay module.


Software Implementation:


In the software part first, open the AWS website by clicking the AWS Management Console link to create your account. It will charge a minimum amount to create the AWS account. In #AWS it includes three to four processes to control the light. They are Generation of Certificates, Creation of policy, and Attachment of policy to the Certificates. Let us understand these processes in detail.


Generation of Certificates:

  • On creating the account set the service to 'IoT Core' and click the manage icon ---> Thing option to create a new thing.

  • Now add the device that we are going to use to the Thing registry and create the certificate.

  • Download the Certificate and also the private key and CA certificate.

Creation of policy:

  • To create a policy, Click on the Secure icon ---> Policy option.

  • Enter New Name and add the action and Resource ARN has '*' to all the IoT resources.

  • Allow the Effect Option.

  • Click the Create icon to create the policy.

Attachment of policy to the Certificates:

  • Go to the Certificate page that we created and click on the three-dotted icon ---> Attach Policy.

  • Select the policy that we created and the policy gets attached.

The downloaded Certificates are in PEM format. Hence the NodeMCU understands only the DER format, now convert it into DER format. For this conversion, the OpenSSL tool is used.


To open OpenSSL click the Command prompt in the Desktop or use this link to download the OpenSSL tool.


After Downloading, Open the tool and copy-paste the following Commands:

openssl x509 -in xxxxxxx-certificate.crt -out cert.der -outform DER 
openssl rsa -in xxxxxxx-private.pem.key -out private.der -outform DER
openssl x509 -in AmazonRootCA1.pem -out ca.der -outform DER

Download the following file for the Complete Command.

commands
.txt
TXT • 575B

Before copy-pasting, the commands remove the xxxxxxx and replace it with the certificate names that we downloaded from the AWS. Now run the commands individually the format of the certificates is changed from PEM to DER and stored in the directory.


The Next step is to upload these files in the file system of NodeMCU. For this store the certificates and the code for the esp8266 in a single folder. Then Open the Arduino IDE now go to Tool and search for "ESP8266 Sketch Data Upload" if the tool is not available download the tool from the given ESP8266 Sketch Data Upload link. Download the tool and extract it and store it in the same folder in which the certificates and esp8266 coding are stored.


Now open the #ESP8266 Sketch Data Upload and upload the certificates to the file system of the NodeMCU. Then copy-paste the esp8266 coding in the #Arduino IDE. Before compiling the program select the required specifications for the NodeMCU board and enter the endpoint value in the code. To get the endpoint value go to the AWS account setting option and copy-paste the endpoint in the code.


Coding Explanation:

The following code needs to be entered into the Arduino IDE and uploaded to the NodeMCU board.

# include <FS.h>

Include this header file to upload the certificates to the file system of the NodeMCU.

# include <ESP8266WiFi.h>

Include this header file from the Arduino library for establishing the board WIFI connection.

# include <PubSubClient.h>

It is included for maintaining the MQTT protocol connection.

# include <NTPClient.h>

The above header file is included for real-time data management to the server.

# include <WiFiUdp.h>

This enables the UDP protocol to establish connections in real-time.

# define Relay D5

It defines the pin to which the relay is connected to the NodeMCU and to which the output is given.

// My network your network.

const char* ssid =   "xxxxxxxxx";
const char* password = "xxxxxxxxxx";

The above statement is to establish an internet connection. Enter the WIFI id and password in the required space before uploading the program.

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

To get the NTP UDP client protocol to store the real-time data within the time server.

const char* AWS_endpoint = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

Initialize the endpoint to authorize with the AWS platform. Copy-paste the endpoint from the AWS account.

void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]); //printing payload content
  }

  char relay = (char)payload[63]; // Extracting the controlling command from the Payload to Controlling LED from AWS
  Serial.print("Relay Status= ");
  Serial.println(relay);
  
  if (relay == 49) // 49 is the ASCII value of 1
  {
    digitalWrite(Relay, HIGH);
    Serial.println("LED_State changed to HIGH");
  }

  else if (relay == 48) // 48 is tge ASCII value of 0
  {
    digitalWrite(Relay, LOW);
    Serial.println("LED_State changed to LOW");
  }
  Serial.println();
}

The callback function runs repeatedly to get the data. The received data is stored in the payload and print the payload value in the serial monitor. Then the command is extracted from it to control the LED by using AWS. By that, the relay state is changed from 0 to 1 in which it changes the LED from OFF state to ON state.

WiFiClientSecure espClient;
PubSubClient client(AWS_endpoint, 8883, callback, espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

This ensures a secure connection to the WIFI and real-time data management from the AWS platform and board connection with the correct execution of the callback functions.

void setup_wifi()
{
  delay(10);
  espClient.setBufferSizes(512, 512);

  // We start by connecting to a network
  Serial.println();
  Serial.println("Connecting to..");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

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

These lines ensure a secure connection to the WIFI and the board. With a delay initialize the buffer size. And on establishing a proper connection to the network, it displays in the serial monitor or else wait for some time to establish the proper connection.

 timeClient.begin();
  while (!timeClient.update())
  {
    timeClient.forceUpdate();
  }

  espClient.setX509Time(timeClient.getEpochTime());
  
}

The above statement obtains the real-time service from the NTP server and it also tries to matches the AWS certificates timing to the server time format.

void reconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection...");
    
    // Attempt to connect
    if (client.connect("ESPthing")) 
    {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("Status", "Relay status");
      // ... and resubscribe
      client.subscribe("Relay State");
    } 

    
    else 
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      char buf[256];
      espClient.getLastSSLError(buf,256);
      Serial.print("WiFiClientSecure SSL error: ");
      Serial.println(buf);

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


The above statements are used to reconnect the connection to AWS using the NTP protocol. It makes sure the connection of the client and indicate if any error in uploading the certificates.

void setup()
{
  Serial.begin(9600);
  Serial.setDebugOutput(true);

  // initialize digital pin as an output.
  pinMode(Relay, OUTPUT);
  setup_wifi();
  delay(1000);

In the setup function, the output pin of the relay is initialized. And the WIFI connection is checked with a delay.

 if (!SPIFFS.begin())
  {
    Serial.println("Failed to mount file system");
    return;
  }

  Serial.print("Heap: ");
  Serial.println(ESP.getFreeHeap());

  // Load Certifacates file

  File cert = SPIFFS.open("/cert.der", "r"); //replace cert.crt eith your uploaded file name
  if (!cert)
  {
    Serial.println("Failed to open cert file");
  }
  else
  {
    Serial.println("Success to open cert file");
  }


   delay(1000);

  if (espClient.loadCertificate(cert))
  {
    Serial.println("Certificate Loaded");
  }
  else
  {
    Serial.println("Certificate not Loaded");
  }

  // Load Private Key
  File private_key = SPIFFS.open("/private.der", "r");
  if (!private_key)
  {
    Serial.println("Failed to open Private key");
  }
  else
  {
    Serial.println("Success to open Private key");
  }
  

  delay(1000);

  if (espClient.loadPrivateKey(private_key))
  {
    Serial.println("Private Key Loaded");
  }
  else
  {
    Serial.println("Private Key not Loaded");
  }

  // Load CA Files
  File ca = SPIFFS.open("/ca.der", "r");
  if (!ca)
  {
    Serial.println("Failed to open ca");
  }
  else
  {
    Serial.println("Success to open ca");
  }

  delay(1000);

  if (espClient.loadCACert(ca))
  {
    Serial.println("ca Loaded");
  }
  else
  {
    Serial.println("ca not Loaded");
  }

  Serial.println("Heap");
  Serial.println(ESP.getFreeHeap());
}

The above statements are compiled when there is an error in uploading the AWS certificates to the file system. If the certificates are not loaded, run the above code to upload all the files individually to the file system of the NodeMCU.


Complete Code:


# include <FS.h>
# include <ESP8266WiFi.h>
# include <PubSubClient.h>
# include <NTPClient.h>
# include <WiFiUdp.h>

# define Relay D5

// My network your network.

const char* ssid =   "xxxxxxxxx";
const char* password = "xxxxxxxxxx";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

const char* AWS_endpoint = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";



void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]); //printing payload content
  }

  char relay = (char)payload[63]; // Extracting the controlling command from the Payload to Controlling LED from AWS
  Serial.print("Relay Status= ");
  Serial.println(relay);
  
  if (relay == 49) // 49 is the ASCII value of 1
  {
    digitalWrite(Relay, HIGH);
    Serial.println("LED_State changed to HIGH");
  }

  else if (relay == 48) // 48 is tge ASCII value of 0
  {
    digitalWrite(Relay, LOW);
    Serial.println("LED_State changed to LOW");
  }
  Serial.println();
}



WiFiClientSecure espClient;
PubSubClient client(AWS_endpoint, 8883, callback, espClient);
long lastMsg = 0;
char msg[50];
int value = 0;


void setup_wifi()
{
  delay(10);
  espClient.setBufferSizes(512, 512);

  // We start by connecting to a network
  Serial.println();
  Serial.println("Connecting to..");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

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

  timeClient.begin();
  while (!timeClient.update())
  {
    timeClient.forceUpdate();
  }

  espClient.setX509Time(timeClient.getEpochTime());
  
}

void reconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection...");
    
    // Attempt to connect
    if (client.connect("ESPthing")) 
    {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("Status", "Relay status");
      // ... and resubscribe
      client.subscribe("Relay State");
    } 

    
    else 
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      char buf[256];
      espClient.getLastSSLError(buf,256);
      Serial.print("WiFiClientSecure SSL error: ");
      Serial.println(buf);

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


 

void setup()
{
  Serial.begin(9600);
  Serial.setDebugOutput(true);

  // initialize digital pin as an output.
  pinMode(Relay, OUTPUT);
  setup_wifi();
  delay(1000);

  if (!SPIFFS.begin())
  {
    Serial.println("Failed to mount file system");
    return;
  }

  Serial.print("Heap: ");
  Serial.println(ESP.getFreeHeap());

  // Load Certifacates file

  File cert = SPIFFS.open("/cert.der", "r"); //replace cert.crt eith your uploaded file name
  if (!cert)
  {
    Serial.println("Failed to open cert file");
  }
  else
  {
    Serial.println("Success to open cert file");
  }


   delay(1000);

  if (espClient.loadCertificate(cert))
  {
    Serial.println("Certificate Loaded");
  }
  else
  {
    Serial.println("Certificate not Loaded");
  }

  // Load Private Key
  File private_key = SPIFFS.open("/private.der", "r");
  if (!private_key)
  {
    Serial.println("Failed to open Private key");
  }
  else
  {
    Serial.println("Success to open Private key");
  }
  

  delay(1000);

  if (espClient.loadPrivateKey(private_key))
  {
    Serial.println("Private Key Loaded");
  }
  else
  {
    Serial.println("Private Key not Loaded");
  }

  // Load CA Files
  File ca = SPIFFS.open("/ca.der", "r");
  if (!ca)
  {
    Serial.println("Failed to open ca");
  }
  else
  {
    Serial.println("Success to open ca");
  }

  delay(1000);

  if (espClient.loadCACert(ca))
  {
    Serial.println("ca Loaded");
  }
  else
  {
    Serial.println("ca not Loaded");
  }

  Serial.println("Heap");
  Serial.println(ESP.getFreeHeap());
}

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

For the Complete Code, download the following file.

Esp8266_AWS_MQTT
.txt
TXT • 5KB

Note: Please change the file extension to .ino(Arduino IDE) file format before you upload the code to the Arduino board.


Working:


On uploading the program to the NodeMCU, go to the AWS account and click the test option to test the working of the hardware. In the Publish section specify the topic and type the message "Device_1_LED" = "1 or 0". The 1 command will enable the #LED to glow and 0-command will switch off the LED.


The below image shows the picture of the circuit when the code is not applied.

Connection, Before Uploading the program
Connection, Before Uploading the program

After Uploading the code and passing the required command the light starts glowing.


Connection, After Uploading the program
Connection, After Uploading the program

A detailed explanation of the hardware and software implementation, coding part, and the working are explained clearly in the given video.


Video By - Harshit Gupta

Further, this #automation technology can also be demonstrated to control other appliances like fans, door, AC, etc by using mobile phones or computers for any large places like hospitals, industries, institutions, etc.


SEE ALSO:

Check the other IoT based automation projects listed below:

  1. IoT - Distance measurement using Ultrasonic Sensor & Raspberry Pi

  2. Fire Alert to Gmail using Raspberry Pi - IoT

  3. Smart Lighting System using ThingSpeak IoT Cloud and Raspberry Pi