Hackster is hosting Hackster Holidays, Ep. 4: Livestream & Giveaway Drawing. Start streaming on Wednesday!Stream Hackster Holidays, Ep. 4 on Wednesday!
Fatima Zahra Souna
Published

Temperature control & monitoring system, NodeMCU, iot projec

Distant monitoring system, control via WhatsApp messages

BeginnerWork in progress474
Temperature control & monitoring system, NodeMCU, iot projec

Things used in this project

Hardware components

NodeMCU ESP8266 Breakout Board
NodeMCU ESP8266 Breakout Board
×1
Temperature Sensor
Temperature Sensor
×1

Software apps and online services

Arduino IDE
Arduino IDE
Twilio API for WhatsApp
Twilio API for WhatsApp
ThingSpeak API
ThingSpeak API

Story

Read more

Custom parts and enclosures

No files

Schematics

Project circuit

I'd rather like that some modifications can be made according to the users need and experience

Code

Temperature control & monitoring system

C/C++
Monitor temperature at a distance and control your equipments via WhatsApp messages
Choice between automatic mode or control mode
Automatic mode : sends system state to each of webpage, thingspeak and whatsapp, still doesn't allow you to control the state of equipments
Control mode: sends system data to webpage and thingspeak, allows you to control and monitor system via whatsapp command messages
Before accessing the webpage you need to enter the account authentication
Note that you still need to change the accounts authentication information.. and the pins according to yours
#include <ESP8266HTTPClient.h>
#include <Callmebot_ESP8266.h>
#include <ThingESP.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h> 
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <SoftwareSerial.h>
#include "ThingSpeak.h" // always include thingspeak header file after other header files and custom macros


//Max values to store for the plot
float temperatures[300];  
int temperatureIndex = 0;
//sett the SSID and Password of Nodemcu and WiFi router
const char* mywifi= "fatima zahra";
const char* ssid = "ESP8266 NodeMCU";
const char* password = "05/13/11";

// set the suthentification cridentials
const char* username = "Fatima Zahra";
const char* pswd = "05/13/11";

//creat esp8266 web server
ESP8266WebServer server (80);
//ThingSpeak confidentials
unsigned long Temp_CH_ID = channel_id;
const char* APIKey = "your_api_key";

//time delay for published readings 
unsigned long lastTime = 0;
unsigned long timeDelay = 25000;// every 25s
//WhatsApp confidentials
String phoneNumber = "+213542805527";
String apiKey = "1422167";
String message = "Welcome To ESP8266 \n Temperature controller 2023";

//setup ThingESP to recieve messages
ThingESP8266 thin("name", "project name", "id");

WiFiClient client;

// declaring the html page
String SendHTML();
// Controle mode :
bool isAutomatic = false;

//integrating pin numbers, high&low temperature
const int sensorPin = A0; 
uint8_t Safe = D5;
bool SafeStat = LOW;

//control pins 
const int HeatingPin = D7;
const int led_B = D7;
bool HT_Stat = 0;

const int CoolingPin = D6;
const int led_R = D6;// modifier location des leds
bool CL_Stat = 0 ;
//declare globale variables
float Temperature;
// Threshold values
float highTemp = 30.0;
float  lowTemp = 25.0;
String Mode;

String request;
void notFound() {
    server.send(404, "text/plain", "Not found");
}

void handleRoot() {
  server.send(200, "text/html", SendHTML());
}
void handle_onconnet(){
 SafeStat = LOW;
 CL_Stat = LOW;
 HT_Stat = LOW;
 digitalWrite(HeatingPin , LOW);
 digitalWrite(CoolingPin , LOW);
 digitalWrite(led_B, LOW);
 digitalWrite(led_R, LOW);
 Serial.println("GPI05 Status : OFF | GPI06 Status : OFF | GPI07 Status : OFF");
 server.send(200, "text/html", SendHTML());
 
}
void handle_Allgoodon(){
  SafeStat = HIGH;
  if (SafeStat)
  {
    digitalWrite(Safe, HIGH);
  }
  else
  {
    digitalWrite(Safe, LOW);
  }
  digitalWrite(HeatingPin , HIGH);
  digitalWrite(CoolingPin , HIGH);
  digitalWrite(led_B, HIGH);
  digitalWrite(led_R, HIGH);
  Serial.println("GPI05 Status : ON");
  server.send(200, "text/html", SendHTML());
}
void handle_Allgoodoff(){
  SafeStat = LOW;
  if (SafeStat)
  {
    digitalWrite(Safe, HIGH);
  }
  else
  {
    digitalWrite(Safe, LOW);
  }
  Serial.println("GPI05 Status : OFF");
  server.send(200, "text/html", SendHTML());
}
void handle_HeatingOn(){
  digitalWrite(HeatingPin , LOW);
  digitalWrite(led_B, LOW);
  SafeStat = LOW;
  HT_Stat = HIGH;
  CL_Stat = LOW;
  digitalWrite(CoolingPin , HIGH);
  Serial.println("GPI06 Status : ON");
  server.send(200, "text/html", SendHTML());
}
void handle_HeatingOff( ){
  digitalWrite(HeatingPin , HIGH);
  HT_Stat = LOW;
  digitalWrite(led_B, HIGH);
  Serial.println("GPI06 Status : OFF");
  server.send(200, "text/html", SendHTML());
}
void handle_CoolingOn(){
  digitalWrite(CoolingPin , LOW);
  digitalWrite(led_R, LOW);
  SafeStat = LOW;
  CL_Stat = HIGH;
  HT_Stat = LOW;
  digitalWrite(HeatingPin , HIGH);
  Serial.println("GPI07 Status : ON");
  server.send(200, "text/html", SendHTML());
}
void handle_CoolingOff(){
  digitalWrite(CoolingPin , HIGH);
  digitalWrite(led_R, HIGH);
  CL_Stat = LOW;
  Serial.println("GPI07 Status : OFF");
  server.send(200, "text/html", SendHTML());
}


void handle_Manual() {
  
   if (CL_Stat){
    digitalWrite(CoolingPin, LOW);
    digitalWrite(led_R, LOW);
  }
  else
  {
    digitalWrite(CoolingPin, HIGH);
    digitalWrite(led_R, HIGH);
  }

  if (HT_Stat)
  {
    digitalWrite(HeatingPin, LOW);
    digitalWrite(led_B, LOW);
  }
  else
  {
    digitalWrite(HeatingPin, HIGH);
    digitalWrite(led_B, HIGH);
  }
}
void WebSocketMsg(){
  unsigned long previousMillis = 0;
  const long interval = 1000; // Interval for sampling the analog input
  // Send the temperature and time data to the client over WebSocket
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    String message01 = "{\"Temperature\": " + String(Temperature) + ", \"time\": " + String(currentMillis) + "}";
    server.send(200, "application/json", message01.c_str(), message01.length());
  }
}

void setup() {
    //configuring pins mode
  pinMode(sensorPin, INPUT);
  pinMode(HeatingPin, OUTPUT);
  pinMode(CoolingPin, OUTPUT);
  pinMode(Safe, OUTPUT);
  
  delay(1000);
  Serial.begin(9600);
  WiFi.mode(WIFI_AP);// nodemcu as wifi station
  WiFi.begin( mywifi, "05/13/11");
  Serial.print("Connecting to WiFi ");
  while(WiFi.status()!= WL_CONNECTED)
  {
    Serial.print(".");
    delay(200);
  }
  Serial.print("IP Address :");
  Serial.println(WiFi.localIP());
  Serial.print("MacAddress :");
  Serial.println(WiFi.macAddress());
  
  Serial.println();
  Serial.print("Configuring access point...");
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  //serve the HTML page
  server.on("/", []() {
    if (!server.authenticate(username, pswd))
    {
      return server.requestAuthentication(DIGEST_AUTH, "Login Required", "Authentification Failed, try again");
    }
    server.send(200, "text/html", SendHTML());
  });
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Connect Failed! Rebooting...");
    delay(1000);
    ESP.restart();
  }
  server.begin();
  Serial.println("HTTP server started");
  //initialize system state
  digitalWrite(Safe , false);
  Serial.println("Green Led OFF");
  digitalWrite(HeatingPin, HIGH);
  digitalWrite(led_B, HIGH);
  Serial.println("Heater OFF");
  digitalWrite(CoolingPin, HIGH);
  digitalWrite(led_R, HIGH);
  Serial.println("Cooler OFF");

  
  //start whatsapp messages
  whatsappMessage(phoneNumber, apiKey, message + "\nWait while choosing monitor and control mode\n");
  //Specify the control mode
  // Read user input from the serial monitor
  Serial.println("\n Choose your controle mode ");
  unsigned long i = 0;
  unsigned long timeup = 25000;
  if ( millis()+i <= timeup){// give the user a delay of 25 sec to choose mode
   do {
    // Wait for user input
    i = millis();
    }while (Serial.available() == 0);
    Mode = Serial.readStringUntil('\n'); 
  }
   else {
      Mode = "true";
      Serial.println("You've been redirected to automatic mode");
  }
   // Convert input (controle mode) to boolean value
  if (Mode == "true") {
    isAutomatic = true;
    whatsappMessage(phoneNumber, apiKey, "Automatic mode is enabled, welcome again to WhatsApp bot\n");
  } else if (Mode == "false") {
    isAutomatic = false;
    whatsappMessage(phoneNumber, apiKey, "Commande mode is enabled, see you on Twilio\n");
  } else {
    // Invalid input
    Serial.println("Invalid input. Please enter 'true' or 'false'.");
    return;
  }
  
   //start ThingSpeak client
   ThingSpeak.begin(client);

     //setup ThingESP 
     thing.SetWiFi( mywifi, password);
     thing.initDevice();

}

String HandleResponse(String received){
  if (received ==""){
    return "welcome to commande mode ";
  }
   // Controle heater
  if (received == "heater on") {
    digitalWrite(HeatingPin, LOW); // Turn on the heater
    digitalWrite(CoolingPin, HIGH); // turn off fan for security
    digitalWrite(Safe, LOW); //turn off green led for security 
    return "DONE : Heater turned on"; // Send confirmation message
  }
  else if (received == "heater off") {
    digitalWrite(HeatingPin, HIGH); // Turn off the heater
    return "DONE : Heater turned off"; // Send confirmation message
  }
  // Controle cooling fan
  else if (received == "fan on") {
    digitalWrite(CoolingPin, LOW); // Turn on the fan
    digitalWrite(HeatingPin, HIGH); //turn off heater 
    digitalWrite(Safe, LOW); //turn off green led for security 
    return "DONE : Fan turned on"; // Send confirmation message
  }
  else if (received == "fan off") {
    digitalWrite(CoolingPin, HIGH); // Turn off the fan
    return "DONE : Fan turned off"; // Send confirmation message
  }
  // Controle both
  else if (received == "all on") {
    digitalWrite(CoolingPin, LOW); // Turn on the fan
    digitalWrite(HeatingPin, LOW); // Turn on the heater
    digitalWrite(Safe, HIGH); // Turn on geen Led
    return "DONE : Fan and Heater turned on"; // Send confirmation message
  }
  else if (received == "all off") {
    digitalWrite(CoolingPin, HIGH); // Turn off the fan
    digitalWrite(HeatingPin, HIGH); // Turn off the heater
    digitalWrite(Safe, LOW);// Turn off green led
    return "DONE : Fan and Heater turned off"; // Send confirmation message
  }
  //check system status while without command
  else if (received == "state") {
      
      if(lowTemp < Temperature < highTemp){
        handle_Allgoodon();
        handle_HeatingOff();
        handle_CoolingOff();
      }
      else if (Temperature < lowTemp){
        handle_Allgoodoff();
        handle_HeatingOn();
        handle_CoolingOff();
      }
       if(highTemp < Temperature ){
        handle_Allgoodoff();
        handle_HeatingOff();
        handle_CoolingOn();
      }
      String HT = digitalRead(HeatingPin) ? "Heater is OFF\n" : "Heater is ON\n";
      String CL = digitalRead(CoolingPin) ? "Fan is OFF\n" : "Fan is ON\n";
      String givenState = "Current Temperature is : " + String(Temperature)+ "C\n"+HT+"\n"+ CL+"\n";
    return  givenState ;
  }
  else {
      String invalide ="Your request was invalid...\n Current Temperature is : "+ String(Temperature) +"C\n";
    return  invalide;
  }
}

void setfields(){
  int  Temp_notf;
  int  HT_notf;
  int  CL_notf;
  Temp_notf = ThingSpeak.writeField(Temp_CH_ID, 1, Temperature, APIKey);
   if(Temp_notf == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Temp_notf));
    }
   HT_notf = ThingSpeak.writeField(Temp_CH_ID, 2, HT_Stat, APIKey);
   if(Temp_notf == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Temp_notf));
    }
    CL_notf = ThingSpeak.writeField(Temp_CH_ID, 3, CL_Stat, APIKey);
   if(Temp_notf == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Temp_notf));
    }
}
void loop(){
  // Handle incoming client requests
  server.handleClient();
  //get the current temperature
  int Temperature1 = analogRead(A0);  //Read Analog Voltage of ADC Pin
  float voltage = Temperature1 * (3300.0 / 1023.0);
  Temperature = voltage/10;       //10mV is 1 degree C  
  Serial.println(" The current temperature is : "+ String(Temperature)+"C\n =====================\n");
  
  // Check the value of isAutomatic and perform operaions
  if (isAutomatic) {
    Serial.println("Automatic mode is enabled.");
    // Perform some automatic operation
    // Turn on/off LEDs based on temperature 
    if(Temperature > highTemp) {
      HT_Stat = LOW;
      CL_Stat = HIGH;
      handle_HeatingOff();
      handle_CoolingOn();
      handle_Allgoodoff();
      handle_Manual();
      Serial.println("Temperature is too high!");
      String message1 = "Temperature is " + String(Temperature) + "C.\n"+"System is Overheated, turning on the cooling fan.\n"+" The heater is Off ";
      whatsappMessage(phoneNumber, apiKey, message1);
      // set the fields with the value
      setfields();
      delay(3000); 
    } else if(Temperature < lowTemp) {
      HT_Stat = HIGH;
      CL_Stat = LOW;
      handle_HeatingOn();
      handle_CoolingOff();
      handle_Allgoodoff();
      handle_Manual();
      Serial.println("Temperature is too low!");
      String message2 = "Temperature is " + String(Temperature) + "C.\n"+"System is under the min temperature, turning on the heating.\n"+" The cooling fan is Off. ";
      whatsappMessage(phoneNumber, apiKey, message2);
      // set the fields with the value
      setfields();
      delay(3000);
    } else {
      SafeStat = HIGH;
      HT_Stat = LOW;
      CL_Stat = LOW;
      handle_Allgoodon();
      handle_HeatingOff();
      handle_CoolingOff();
      handle_Manual();
      String message3 = "Temperature is " + String(Temperature) + " C.\n"+"All good.\n"+" Cooling Fan is Off.\n"+" Heater is Off.";
      whatsappMessage(phoneNumber, apiKey, message3);
      Serial.println("Temperature is in range ^-^");
      // set the fields with the value
      setfields();
      delay(3000);
      Serial.println("The current temperature is : " +String(Temperature) +"C");
    }
  
  }else {
    Serial.println("Command mode is enabled.");
    Serial.println("The current temperature is : " +String(Temperature) +"C");
    // perform some manual operation
    thing.Handle();
    setfields();
    delay(3000);
  }
    // Add data point to the chart
  Serial.println("Temperature vs Time");
  Serial.println("Time,Temperature");
  temperatures[temperatureIndex] = Temperature;
  temperatureIndex++;
  if (temperatureIndex >= 300) temperatureIndex = 0;  // Wrap index
  // Print values to serial plotter in CSV (comma separated) format 
  //for (int j=0; j<300; j++) {
  //Serial.println(temperatures[j]);  // Temperature value 
  //}
  
    WebSocketMsg();
    server.send(200, "text/html", SendHTML());
    notFound();
    
  }


   String SendHTML() {
  String page = "<!DOCTYPE html> <html> <head>\n";
  page += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  page += "<title>Temperature Monitoring Web Server</title>\n";
  page += "<script src=\"https://cdn.jsdelivr.net/npm/@moostep/realtimechart@1.0.0/dist/realtimechart.min.js\"></script>\n";
  page += "<style> \n";
  page += "div.card {  width: 450px; box-shadow: 1 4px 8px 1 rgba(0, 0, 0, 0.5), 0 7px 30px 0 rgba(0, 0, 0, 0.25);  text-align: center; border-radius: 6px; }\n";
 
  if(Temperature > highTemp) {
     page += "div.header {  color: black;  padding: 11px;  font-size: 16px;  border-radius: 6px; background-color : red;}\n";
    } else if(Temperature < lowTemp) {
      page += "div.header {  color: black;  padding: 11px;  font-size: 16px;  border-radius: 6px; background-color : #87CEEB;}\n";
    } else {
      page += "div.header {  color: black;  padding: 11px;  font-size: 16px;  border-radius: 6px; background-color :  #4BA705;}\n";
    }
  page += "div.container {  padding: 7px; border-radius: 6px; background-color: #777B7E}\n";
  page += "p {font-size: 15px;color: #888;margin-bottom: 12px;}\n";
  page += "</style>\n";
  page += "</head>\n";
  page += "<body>\n";
  page += "<center><h2>Temperature Monitoring Web Server</h2>\n";
  page += "<div class=";
  page += "card";
  page += ">\n";
  page += "<div class=";
  page += "header";
  page += ">\n";
  page += "<p>\n";
    page += "<h1>The current temperature is : " +String(Temperature) + " &deg;C</h1>\n";
    page += "<h2>The high set temperature is : "+String(highTemp) + " &deg;C</h2>\n";
    page += "<h2>The low set temperature is : "+String(lowTemp) + "&deg;C</h2>\n";
  page += "</div>\n";
  
  page += "<div class=";
  page += "container";
  page += ">\n";
    page += "<h2>Temperature</h2>\n";
  page += "</div>\n";
  page += "</div>\n";
  page += "</center>\n";
  page += "<center>\n";
    page += "<p>Cooling stat : " + String(CL_Stat) +"</p>\n";
    page += "<p>Heating stat : " + String(HT_Stat) +"</p>\n"; 
  page += "</center>\n";
  page += "<canvas id=\"chart\"></canvas>\n";
//  page += "<script>var data = [{x: [], y: [], type: 'scatter'}];\n";
  page += "<script>\n";
  page += "var chart = new RealtimeChart({\n";
  page += "canvas: document.getElementById('chart'), dataLength: 20, maxValue: 100, label: 'Temperature (C)'});\n";
  page += "var ws = new WebSocket('ws://' + window.location.hostname + ':81/');\n";
  page += "ws.onmessage = function(event) {var data = JSON.parse(event.data);chart.append(data.Temperature);};\n";
  page += "</script>";
//  page += "var layout = {title: 'Temperature Progres',\n";
//  page += "xaxis: {title: 'Time (s)'},\n";
//  page += "yaxis: {title: 'Temperature (C)'}};\n";
//  page += "var plot = Plotly.newPlot('plot', data, layout);\n";
//  page += "setInterval(function() {Plotly.extendTraces('plot', {x: [[Date.now() / 1000]],\n";
//  page += "y: [[parseFloat('" + String(Temperature) + "')]]}, [0])}, 1000);\n";
//  page += "</script>\n";
  page += "</body>\n";
  page += "</html>\n";

  return page;
}

Credits

Fatima Zahra Souna

Fatima Zahra Souna

1 project • 1 follower

Comments