There have been many incidents like explosions and fire due to certain gases leakage. Such incidents can cause dangerous effects if the leakage is not detected at an early stage. Therefore, Measurement and control of these types of toxic gases present in the environment are essential. IoT based Air Quality Monitoring and analyzing multiple environmental parameters in real-time serves as one of the best solutions for controlling the particular process. A portable system regarding the same in real-time, log data to a remote server, and keeping the data updated over the internet can offer an overview of the process. Gases measurements are in Parts per Million (PPM) metrics.
In this project, we are using nodemcu esp8266 as the microcontroller and an MQ2 sensor that detects different kinds of gases and particles. This board has a Wi-Fi module that acts as the internet connector and information accessing for the air quality. This is the reason why we are choosing this board as some of the tools for this project, besides the price of this board is very cheap as well.
Generally, for gas leakage detection (home and industry), we will use the MQ2 module. It is suitable for detectingH2, LPG, CH4, CO, Alcohol, Smoke, or Propane. Due to the high sensitivity and fast response time of it. But, in this design, we used the MQ2 sensor for the smoke situation. This sensor has four outputs, namely, Vcc, ground, D0, and A0.
Architecture
Firstly, to make an IoT based Air Quality Monitoring system will be collecting the data from the mq2 senor and send to NodeMCU. We will then be sending this data to aws IoT core using MQTT protocol and creating a database using the DynamoDB service of aws. Using this dataset we made a website with the help of aws Lambda and aws API gateway.
Setting up the aws
- Step1: Login to aws account
- Step2: Create a thing in aws iot core
- Step3: Download the certificates
- Step4: create a policy and add it to the certificates of the thing
- Step5: Convert all the certificates into .der format by following openssl commands
> openssl x509 -in xxxxxxxxxxxxx-certificate.pem.crt -out cert.der -outform DER
> openssl rsa -in xxxxxxxxxx-private.pem.key -out private.der -outform DER
> openssl x509 -in xxxxxxxxxx.pem -out ca.der -outform DER
Setting up the Hardware
- Connect the Analog pin of the MQ2 gas sensor to the A0 pin of ESP8266 and Vcc and GND to 3.3V and 0V respectively. Firstly, Download the esp8266 board and add it to IDE then upload the code in the Arduino IDE.
- Create a Folder, name it Data, and add all the certificates into this folder.
- Create another folder, add the data folder and code.ino file.
- Check whether the certificate names in the data folder and in the code are matching.
- Go to tools and select ESP8266 Sketch Data Upload then compile and upload the code.
#include "FS.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>// allows you to send and receive mqtt messages
#include <NTPClient.h> // include time information from the internet
#include <WiFiUdp.h>
int Gas_analog = A0; // used for ESP8266
int Gas_digital = D1; // used for ESP8266
// Update these with values suitable for your network.
const char* ssid = "xxxxx";
const char* password = "xxxxxxxx";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
const char* AWS_endpoint = "arufwoersqlu4-ats.iot.us-east-2.amazonaws.com"; //MQTT broker ip
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]);
}
Serial.println();
}
WiFiClientSecure espClient;
PubSubClient client(AWS_endpoint, 8883, callback, espClient); //set MQTT port number to 8883 as per //standard
#define BUFFER_LEN 256
char msg[BUFFER_LEN];
long lastMsg = 0;
int value = 0;
byte mac[6];
char mac_Id[18];
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
espClient.setBufferSizes(512, 512);
Serial.println();
Serial.print("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.println("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("outTopic", "hello");
// ... and resubscribe
client.subscribe("inTopic");
} 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(115200);
pinMode(Gas_digital, INPUT);
Serial.setDebugOutput(true);
setup_wifi();
delay(1000);
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
// Load certificate file
File cert = SPIFFS.open("/cert.der", "r");
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("cert loaded");
else
Serial.println("cert not loaded");
// Load private key file
File private_key = SPIFFS.open("/private.der", "r");
if (!private_key) {
Serial.println("Failed to open private cert file");
}
else
Serial.println("Success to open private cert file");
delay(1000);
if (espClient.loadPrivateKey(private_key))
Serial.println("private key loaded");
else
Serial.println("private key not loaded");
// Load CA file
File ca = SPIFFS.open("/ca.der", "r"); //replace ca eith your uploaded file name
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 failed");
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
//===========================================================================
WiFi.macAddress(mac);
snprintf(mac_Id, sizeof(mac_Id), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.print(mac_Id);
//============================================================================
}
//int AirQualityIndex = analogRead(Gas_analog);
//int gassensorDigital = digitalRead(Gas_digital);
int gassensorAnalog = analogRead(Gas_analog);
int gassensorDigital = digitalRead(Gas_digital);
void loop() {
String macIdStr = mac_Id;
//const char* airquality = String(gassensorAnalog).c_str();
char cstr[16];
itoa(gassensorAnalog, cstr, 10);
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, BUFFER_LEN, "{\"mac_Id\" : \"%s\", \"AirQualityIndex\" : \"%s\"}", macIdStr.c_str(), cstr);
Serial.print("Gas Sensor: ");
Serial.print(gassensorAnalog);
Serial.print("\t");
Serial.print("Gas Class: ");
Serial.print(gassensorDigital);
Serial.print("\t");
Serial.print("\t");
if (gassensorAnalog > 1000) {
Serial.println("Gas");
}
else {
Serial.println("No Gas");
}
delay(100);
}
client.publish("outTopic", msg);
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap()); //Low heap can cause problems
}
Storing ESP8266 data into Amazon DynamoDB using AWS IoT Core(MQTT)
- Setting up DynamoDB & Creating a rule to fetch data from the MQTT topic then pass to DynamoDB
Creating a Website for viewing the AQI
We are going to create a webpage from the data stored in DynamoDB .
Html code
<pre class="wp-block-syntaxhighlighter-code"><!DOCTYPE html>
<html>
<head>
<title>AirQualityIndex</title>
<style>
body {
height: 400px;
width: 655px;
background-image: url("FINAL.jpg");
}
h1 {
font-family: cursive;
}
#bg {
height: 675px;
width: 855px;
/* background-color:darksalmon; */
background-image: url(AQI.jpg);
background-position: center center;
background-repeat: no-repeat;
}
</style>
</head>
<body id="bg">
<h1 style="color: rgb(30, 83, 161);">
Welcome to TEAM-1 project <b>IOTEDU</b></h1>
<!-- <img src="AQI.jpg" alt="" srcset=""> -->
</body>
</html>
<meta charset="utf-8" />
<a href="http://jquery-3.1.1.min.js">http://jquery-3.1.1.min.js</a>
<a href="http://knockout-3.4.2.js">http://knockout-3.4.2.js</a>
<script type="text/javascript">
$(document).ready(function() {
var customerViewModel = function() {
var self = this;
self.AirQualityIndex = ko.observable("");
self.ts = ko.observable("");
self.time = ko.observable("");
self.searchKey = ko.observable("");
self.getCustomerDetails = function () {
$.ajax({
url: 'https://vzzsnq7olk.execute-api.us-east-2.amazonaws.com/Develop/aqi',
cache: false,
type: 'GET',
data: { "time": self.searchKey() },
success: function (data) {
self.AirQualityIndex(data.Item.AirQualityIndex)
self.ts(data.Item.ts),
self.time(data.Item.time)
}
});
}
}
var viewModel = new customerViewModel();
ko.applyBindings(viewModel);
});
</script>
</head>
<body>
<table>
<tr>
<td>Search Key(time):</td>
<td><input type="text" id="txtSearchKey" data-bind="value : searchKey"/></td>
</tr>
</table>
<br />
<table id="AirMonitor">
<thead>
<tr>
<td>AQI:</td>
<td><label id="AirQualityIndex" data-bind="text: AirQualityIndex"/></td>
</tr>
<tr>
<td>Time Stamp:</td>
<td><label id="ts" data-bind="text: ts"/></td>
</tr>
<tr>
<td>Time:</td>
<td><label id="time" data-bind="text: time"/></td>
</tr>
</thead>
</table>
<br />
<table>
<tr>
<td><input type="button" value="AQI" data-bind="click: $root.getCustomerDetails()"/></td>
</tr>
</table>
</body>
</html>
</pre>
Final output
Download full frontend and backend codes Here