#define BLYNK_TEMPLATE_ID "TMPL6CJgt-PVz"
#define BLYNK_TEMPLATE_NAME "Home Automation IoT "
#define BLYNK_AUTH_TOKEN "-OpGmUb80EJmJyaocxMFBE4xrDE2cB3-"
#include <WiFi.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
#include <BlynkSimpleEsp32.h>

#define DHTPIN 14
#define DHTTYPE DHT22
#define button1 16
#define button2 2
#define button3 4
#define button4 15
#define fan 19
#define buzzer 17
#define mist 18
#define air_con 5
#define fire_sensor 27
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2

WidgetLED warning(V6);
Servo myservo;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);

char ssid[] = "Wokwi-GUEST";
char pass[] = "";
char auth[] = "-OpGmUb80EJmJyaocxMFBE4xrDE2cB3-";
float humidity, temparature, pre_hum=0, pre_temp=0;

bool control_fan, control_mist, control_air, control_door;
bool button_status1 = false, button_status2 = false, button_status3 = false, button_status4 = false;
bool mode, buzzer_status;
bool bt1, bt2, bt3, bt4, bt5, bt6;

unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 5000;  // Cập nhật mỗi 5 giây

BLYNK_WRITE(V2){
  bt1 = param.asInt();
  if (mode){
    if (bt1){
      button_status1 = 1;
      digitalWrite(fan, 1);
    }
    else {
      button_status1 = 0;
      digitalWrite(fan, 0);}
  }
}
BLYNK_WRITE(V3){
  bt2 = param.asInt();
  if (mode){
    if (bt2){
      button_status2 = 1;
      digitalWrite(mist, 1);
    }
    else {
      button_status2 = 0;
      digitalWrite(mist, 0);}
  }
}
BLYNK_WRITE(V4){
  bt3 = param.asInt();
  if (mode){
    if (bt3){
      button_status3 = 1;
      digitalWrite(air_con, 1);
    }
    else {
      button_status3 = 0;
      digitalWrite(air_con, 0);}
  }
}
BLYNK_WRITE(V5){
  bt4 = param.asInt();
  if (mode){
    if (bt4){
      button_status4 = 1;
      myservo.write(180);
    }
    else {
      button_status4 = 0;
      myservo.write(0);}
  }
}
BLYNK_WRITE(V7){
  bt5 = param.asInt();
  if (bt5 == 1){
    buzzer_status = 0;
  }
  else buzzer_status = 1;
}
BLYNK_WRITE(V8){
  bt6 = param.asInt();
  if (bt6 == 1){
    mode = 1;
  }
  else mode = 0;
}
void get_hum_and_temp() {
  humidity = dht.readHumidity();
  temparature = dht.readTemperature(); 
  if (pre_hum != humidity){
     Blynk.virtualWrite(V0, humidity);
      lcd.setCursor(0, 0);
      lcd.print("Hum: ");
      lcd.print(humidity);
    pre_hum = humidity;
  } 
  if (pre_temp != temparature){
    Blynk.virtualWrite(V1, temparature);
    lcd.setCursor(0, 1);
    lcd.print("Temp: ");
    lcd.print(temparature);
    pre_temp = temparature;

  }
}
void au() {
  if (temparature < 25) {
      digitalWrite(fan, 0);
      Blynk.virtualWrite(V2, 0);
      digitalWrite(air_con, 0);
      Blynk.virtualWrite(V4, 0);
      myservo.write(0);
      Blynk.virtualWrite(V5, 0);
  } else if (temparature >= 25 && temparature < 35) {
      digitalWrite(fan, 1);
      Blynk.virtualWrite(V2, 1);
      digitalWrite(air_con, 0);
      Blynk.virtualWrite(V4, 0);
      myservo.write(0);
      Blynk.virtualWrite(V5, 0);
  } else if (temparature >= 35) {
      digitalWrite(air_con, 0);
      digitalWrite(fan, 1);
      Blynk.virtualWrite(V2, 1);
      digitalWrite(air_con, 1);
      Blynk.virtualWrite(V4, 1);
      myservo.write(180);
      Blynk.virtualWrite(V5, 1);
  }
  if (humidity < 30) {
      digitalWrite(mist, 1);
      Blynk.virtualWrite(V3, 1);
  } else {
      digitalWrite(mist, 0);
      Blynk.virtualWrite(V3, 0);
  }
}
void manual() {
  if (control_fan == LOW) {
      button_status1 = !button_status1;
      Serial.println("bt1:");
      Serial.print(button_status1);
      digitalWrite(fan, button_status1);
      Blynk.virtualWrite(V2, button_status1);
      while (!digitalRead(button1)) ;
  }

  if (control_mist == LOW) {
      button_status2 = !button_status2;
      Serial.println("bt2:");
      Serial.print(button_status2);
      digitalWrite(mist, button_status2);
      Blynk.virtualWrite(V3, button_status2);
      while (!digitalRead(button2)) ;
  }

  if (control_air == LOW) {
      button_status3 = !button_status3;
      Serial.println("bt3:");
      Serial.print(button_status3);
      digitalWrite(air_con, button_status3);
      Blynk.virtualWrite(V4, button_status3);
      while (!digitalRead(button3));
  }

  if (control_door == LOW) {
      button_status4 = !button_status4;
      Serial.println("bt4:");
      Serial.print(button_status4);
      myservo.write(button_status4 ? 180 : 0);
      Blynk.virtualWrite(V5, button_status4);
      while(!digitalRead(button4));
  }
}

void fire_detect() {
  if (!digitalRead(fire_sensor)) {
    if (buzzer_status == 1)
      digitalWrite(buzzer, HIGH);
    else digitalWrite(buzzer, LOW);
    Blynk.logEvent("firewarning", "Fire Detected");
    warning.on();
    /*lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Fire Detected");*/
  } else {
    digitalWrite(buzzer, LOW);
  }
}



void setup() {
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  pinMode(buzzer, OUTPUT);
  pinMode(fan, OUTPUT);
  pinMode(mist, OUTPUT);
  pinMode(air_con, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);
  myservo.attach(13); 
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Hum: ");
  lcd.setCursor(0, 1);
  lcd.print("Temp: ");
  dht.begin();
}

void loop() {
  control_fan = digitalRead(button1);
  control_mist = digitalRead(button2);
  control_air = digitalRead(button3);
  control_door = digitalRead(button4);
  Blynk.run();
  //unsigned long currentMillis = millis();
  //if (currentMillis - lastUpdateTime >= updateInterval) {
    //lastUpdateTime = currentMillis;
  //}
  get_hum_and_temp();
  if (mode) manual();
  else au();
  fire_detect();
}