Smart room monitoring and control system

Author: Claudiu-Catalin Pumnea - SRIC

Short Description of the project

The “Smart room monitoring and control system” is an innovative project that focuses on collecting environment parameters and leveraging them to control the lights and outlets of a kitchen. The system utilizes a range of sensors including a water level detection sensor, a temperature and humidity sensor, and a gas sensor. Additionally, a control module equipped with two relays is employed for managing the lights and outlets.

To provide users with real-time data and control functionality, a web application has been developed. The web app features intuitive graphs displaying the humidity and temperature readings, allowing users to visualize the environmental conditions in the kitchen. Furthermore, the app provides the capability to control the status of the relays, enabling users to remotely manage the lights and outlets for enhanced convenience and energy efficiency.


Hardware

To develop this project, the following components were utilized:

  • Water Level Detection Sensor: This sensor enables the system to detect and monitor the water level within the kitchen, providing valuable information in the event of flooding or water leakage.
  • Temperature and Humidity Sensor (DHT11): The DHT11 sensor measures the temperature and humidity levels in the kitchen, allowing for precise environmental monitoring and control.
  • Gas Sensor (MQ2): This sensor measures the level of gas in the kitchen, providing crucial information for safety and preventing potential hazards.
  • Module with Relays: A module equipped with two relays is employed to manage the kitchen's electrical devices. The relays enable control over the lights and outlets, enhancing convenience and energy management.
  • EspWROOM32: Microcontroller that integrates Wi-Fi (802.11 b/g) and Bluetooth (dual mode version 4.2) capabilities. It serves as the core of the project, enabling data collection from sensors and transmitting the it to a database through requests. Additionally, the ESP32 is responsible for controlling various components of the system, such as managing lights and outlets in the kitchen.

Hardware setup


Software

Technologies used in the project:

  • HTML5: It the latest version of the Hypertext Markup Language and is used for structuring and presenting the content of web pages.
  • CSS (Cascading Style Sheets): CSS is a style sheet language used to describe the visual presentation of HTML documents. It is used to enhance the appearance and layout of web pages.
  • TypeScript & TypeORM: TypeScript is a superset of JavaScript that adds static typing and additional features to the language. It enhances code maintainability and provides improved tooling support. TypeORM is an Object-Relational Mapping (ORM) library that simplifies database interactions in TypeScript/JavaScript projects.
  • Nest.js: Nest.js is a framework for building server-side applications using TypeScript. It leverages the capabilities of Node.js and provides a modular, scalable, and opinionated structure for building back-end applications.
  • PostgreSQL: PostgreSQL is an open-source relational database management system (RDBMS) known for its reliability and robustness. It is used for storing and managing structured data in the project.
  • React: A JavaScript library for building user interfaces. React is used for creating dynamic and interactive components on the client-side of the application.

These technologies form the foundation of the project, combining front-end (HTML, CSS, React), back-end ( Nest.js), and database (PostgreSQL) components to create a comprehensive web application with enhanced functionality and a reliable data storage system.

Code

Used Libraries

#include <DHT.h>
#include <string.h>
#include <HTTPClient.h>
#include <WiFi.h>
#include <ArduinoJson.h>

Constants and global variables

#define LIGHT_RELAY_PIN 18
#define CURRENT_OUTLET_RELAY_PIN 4

//Water level sensor
#define WATER_LEVEL_SENSOR_PIN 34

//Gas sensor
#define GAS_SENSOR_MQ2_PIN 35

//Temperature sensor
#define DHTPIN 19
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE); //Initialize dht

//Room and apartment constants
const char* roomType = "Kitchen";
const int apartmentNumber = 49;

//Initialize Docs
DynamicJsonDocument getInitializeDoc(2048);
DynamicJsonDocument getRelayStatusDoc(2048);

////Wifi credentials
const char* ssid = "yourWifiNameHere";
const char* password = "yourWifiPasswordHere";


//Initialize wifiClient and httpClient
WiFiClient client;
HTTPClient http;

//Flags if relays exists

bool currentOutletRelayExists = true;
bool lightRelayExists = true;

//Counter for sending the post message
int counter = 0;

//Declare gas_value and wate_level_value
float gas_value ;
float water_Level_value ;

Setup

void setup() {

Serial.begin(9600);
setupWiFi();
initializePins();
initializeBoard();

}

setupWiFi function

void setupWiFi() {
  WiFi.begin(ssid, password);
  Serial.print("\n Connecting to Wifi");
  
  pinMode(2, OUTPUT);
  while ( WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    digitalWrite(2, HIGH);
    delay(250);
    digitalWrite(2, LOW);
    delay(250);
  }

  digitalWrite(2, HIGH);
  Serial.println("\n Connected to the WiFi network");
  Serial.print("\n IP address: ");
  Serial.print(WiFi.localIP());
  
}

initializePins function

void initializePins() {

  pinMode(LIGHT_RELAY_PIN, OUTPUT);
  pinMode(CURRENT_OUTLET_RELAY_PIN, OUTPUT);
  pinMode(GAS_SENSOR_MQ2_PIN, INPUT);

  //Setting the initial state of the relays
  digitalWrite(LIGHT_RELAY_PIN, HIGH);
  digitalWrite(CURRENT_OUTLET_RELAY_PIN, HIGH);
  dht.begin();

}

initializeBoard function

void initializeBoard() {

  http.begin(client, "http://myIp:3050/apartments/initializeApartmentAndRoom?apartmentNumber=" + String(apartmentNumber) + "&roomType=" + roomType + "&currentOutletRelayExists=" + (currentOutletRelayExists ? "true" : "false") + "&lightRelayExists=" + (lightRelayExists ? "true" : "false"));

  int httpResponseCode = http.GET();


  String httpResponse = http.getString();

  deserializeJson(getInitializeDoc, httpResponse);
  delay(50);

  // Free resources
  http.end();

}

The code is designed to be robust and flexible. Upon loading the code onto the board, it requires the apartment number and room type for database identification. When the board connects to the internet, it sends a GET request to initialize variables. If the apartment number is not found, a new apartment is registered in the database. The same validation and creation mechanism is used for room initialization. During connection, relay presence and types are marked in the database using boolean indicators sent by the ESP32. For existing apartments and rooms, their relevant information is sent and the microcontroller automatically associates received data and IDs from the server.

Void loop

void loop() {

//Saving the needed ids from backend
const char* lightRelayId = getInitializeDoc["electricalRelays"]["lightRelayId"];
const char* currentOutletRelayId = getInitializeDoc["electricalRelays"]["currentOutletRelayId"];
const char* apartmentId = getInitializeDoc["apartmentId"];
const char* roomId = getInitializeDoc["roomId"];

//Initialize Relays status
bool lightRelayIsOn;
bool currentOutletRelayIsOn;

gas_value = readAndCheckGas();
water_Level_value = readWaterLevel();

//Getting relays status
  if(water_Level_value < 30 ){
    getRelayStatus(lightRelayId, currentOutletRelayId);

    //Changing the relay status booleans
    lightRelayIsOn = getRelayStatusDoc["lightRelayIsOn"] == 1 ?  true : false;
    currentOutletRelayIsOn = getRelayStatusDoc["currentOutletRelayIsOn"] == 1 ? true : false;

    setRelayStatus(lightRelayIsOn, currentOutletRelayIsOn);
  } else {
    setRelayStatus(false,false);
  }

  //Read humidity
  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(F("\n Failed to read from DHT sensor!"));
    return;

  }
Serial.println(counter);
  if (counter == 0) {
    postRequestTemperatureHumidity( h,  t, String("roomInputs"), roomId);
    counter = 240;
  }
  else {
    counter -= 1; 
  }
}

In the loop function of the microcontroller code, there is a continuous reading of the gas level and water level. If the water level exceeds 30%, the relay status is automatically set to LOW. This precautionary measure is taken to prevent potential short circuit problems in case of rising water levels. On the other hand, if the water level is below 30%, a request is made to the database through the backend. This request aims to retrieve the current status of the relays. After the request is completed, the setRelayStatus function is utilized to update the relay status accordingly. Since the loop function runs continuously, making a request to the database for the relay status provides real-time updates and makes the application feel responsive. As the request is made within a short time interval, the system stays synchronized with the actual relay status.

readGasLevel and readWaterLevel functions

float readGasLevel() {

  float gas_value = analogRead(GAS_SENSOR_MQ2_PIN);
  gas_value = gas_value * 100 / 4095;
  delay(50);

  return gas_value;
}

float readWaterLevel() {

  float water_Level_value = analogRead(WATER_LEVEL_SENSOR_PIN);
  water_Level_value = water_Level_value * 100 / 4095;
  delay(50);
  return water_Level_value;

}

getRelayStatus function

void getRelayStatus(const char * lightRelayId, const char * currentOutletRelayId) {
  http.begin(client, "http://192.168.137.241:3050/electricalRelay/statusRelays?lightRelayId=" + String(lightRelayId) +  "&currentOutletRelayId=" + String(currentOutletRelayId));

  int httpResponseCode = http.GET();

  String httpResponse = http.getString();
  
  deserializeJson(getRelayStatusDoc, httpResponse);
}

setRelayStatus function

void setRelayStatus(bool lightRelayIsOn, bool currentOutletRelayIsOn){

  digitalWrite(LIGHT_RELAY_PIN, lightRelayIsOn);
  digitalWrite(CURRENT_OUTLET_RELAY_PIN, currentOutletRelayIsOn);

}

postRequestTemperatureHumidity

void postRequestTemperatureHumidity(int h, int t, String route, const char * roomId) {

  http.begin(client, "http://192.168.137.241:3050/" + route);
  http.addHeader("Content-Type", "application/json");

  DynamicJsonDocument doc(2048);
  doc["humidity"] = String(h);
  doc["temperature"] = String(t);
  doc["roomId"] = String(roomId);

  String requestBody;
  serializeJson(doc, requestBody);
  Serial.print(requestBody);
  int httpResponseCode = http.POST(requestBody);
  String httpResponse = http.getString();
  Serial.print("\n HTTP Response: ");
  Serial.println(httpResponse);
  Serial.print("\n HTTP Response code: ");
  Serial.println(httpResponseCode);

  // Free resources
  http.end();
}

This function is executed every minute, thanks to the counter variable that has been created. This enables the system to store data at regular intervals of one minute. By capturing and storing data periodically, the system can maintain a time-stamped record of various parameters or measurements.


Web app short description

Database

- User Table:

  • The “user” table contains relevant data about the users of the web application.
  • It helps identify the users connected to the web app and determines the data to retrieve from the database.
  1. Apartment Table:
  • It holds relevant information about the apartments associated with each user.
  • This table helps organize and manage apartment-related data.
  1. Room Table:
  • It allows users to check individual graphs for each variable in different rooms of the apartment.
  • This table stores relevant data about the rooms in the apartment.
  1. Electric Relay Table:
  • The “electrical_relay” table is used to control the outputs and lights in the system.
  • It has properties like “isOn” to indicate if the relay should be closed or not, and “isUsedFor” to specify whether it is used for outlets or lights.
  • This table helps manage and control the electrical components of the system.
  1. Room Inputs Table:
  • The “room_inputs” table is used to store variables related to monitoring the room.
  • It holds the data collected from sensors or other inputs for monitoring purposes.

Application walkthrough

First time when you will open the app you will be redirected to the login page:

After a successful login, users are directed to the monitoring and control page. The page features two dropdown menus, one for selecting the apartments and another for choosing the rooms. This allows users to manage multiple apartments and select specific rooms within those apartments. For the purpose of the demo and screenshots, a single room (the kitchen) is being used.

On the page, users can find two graphs, one displaying the temperature and the other showing the humidity data. These graphs provide visual representation of the collected data. Users can customize the plotted data by selecting a start and end date using the date and time pickers. This allows them to view data recorded within a specific time period.

In addition to monitoring the data, the page also provides switches for controlling the relays individually. This functionality enables users to control the electrical components such as lights or outlets associated with each room.

Demo

In the demo, the main page of the web app will be showcased, featuring the date pickers that allow users to select a specific time range for data visualization. To illustrate the control system, a light bulb will be connected to the relay by connecting the positive terminal of the outlet to the positive terminal of the bulb. We will be able to switch the relay on or off, thereby controlling the power supply to the light bulb in real-time.

Links:

Bibliography

iothings/proiecte/2022sric/smart-room-monitoring-and-control-system.txt · Last modified: 2023/06/02 09:11 by claudiu.pumnea
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0