#define BLYNK_TEMPLATE_ID "TMPL6YU7qPUiH"
#define BLYNK_TEMPLATE_NAME "nongtraiCopyCopy"
#define BLYNK_AUTH_TOKEN "x0h8UgamQoRBkSMyoh0VTV4qXjccd4Jg"

#include <DHT.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <HTTPClient.h>
#include <WiFiClient.h>
#include <Adafruit_GFX.h>
#include <BlynkSimpleEsp32.h>
#include <Adafruit_SSD1306.h>

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "02"; //Tên WWifi
char pass[] = "12345678"; // Mật khẩu Wifi

String Web_App_URL = "https://script.google.com/macros/s/AKfycbzXY0_vzWmEkX9FqAkSTO9Q7PbRjDt1m3UqSg3ectT99uSyXlhC_X0n1xrD2iudgUiO/exec";

#define On_Board_LED_PIN  2
#define DHTPIN 4          
#define DHTTYPE DHT11     
#define DOAMDAT 36        
#define DOAMDAT A0

DHT dht(DHTPIN, DHTTYPE);

#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_RESET -1 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int button_oled = 19;
int button_chedo = 15; // chọn 15 hoặc 19
int button_bomtuoi = 18; 
int button_den = 5;
int button_ra = 17;
int button_vao = 16;

int relay_bomtuoi = 13;
int relay_den = 12; 
int relay_ra = 27;  
int relay_vao = 14;

#define NHIETDO         V0
#define DOAM            V1
#define CHEDO           V2
#define RELAY           V3
#define DOAM_BAT        V4
#define DOAM_TAT        V5
#define RELAY_RA        V6
#define RELAY_VAO       V7
#define DEN             V9
WidgetLED ledconnect   (V8);

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

int autoOnHour = 12; // giờ bật đèn
int autoOnMinute = 15; // Phút bật đèn
int autoOffHour = 12; // giờ tắt đèn
int autoOffMinute = 16; // Phút tắt đèn

float tempHigh = 36.0; // Nhiệt độ điều khiển mái che ra
float tempLow = 33.0; // Nhiệt độ điều khiển mái che vào

int doam_bat = 30; 
int doam_tat = 80; 

bool displayText = true;
boolean chedo_hoatdong = false;
int autoModeState = 0;
int relay_bomtuoi_State = LOW;
int relay_ra_State = LOW; 
int relay_vao_State = LOW; 
int relay_den_State = LOW;
String Status_Read_Sensor = "";
String Maiche_State = "";
String Den_State = "";
String Bom_State = "";
unsigned long lastTime = 0;  
unsigned long timerDelay = 10000; // thời gian gửi báo cáo lên Google Sheet
unsigned long times=millis();
BLYNK_WRITE(V9) {
  if (chedo_hoatdong) {
    relay_den_State = param.asInt();
    digitalWrite(relay_den, relay_den_State);
    Serial.println("Chế độ Thủ công: Đang " + String(relay_den_State ? "BẬT" : "TẮT") + " đèn");
  }
}

BLYNK_WRITE(V7) {
  if (chedo_hoatdong) {
    relay_vao_State = param.asInt();
    if (relay_vao_State == HIGH) { 
      relay_ra_State = LOW;
      digitalWrite(relay_ra, relay_ra_State);
      Blynk.virtualWrite(V6, relay_ra_State); 
    }
    digitalWrite(relay_vao, relay_vao_State);
    Serial.println("Chế độ Thủ công: Đang " + String(relay_vao_State ? "BẬT" : "TẮT") + " relay_vao");
  }
}

BLYNK_WRITE(V6) {
  if (chedo_hoatdong) {
    relay_ra_State = param.asInt();
    if (relay_ra_State == HIGH) { 
      relay_vao_State = LOW;
      digitalWrite(relay_vao, relay_vao_State);
      Blynk.virtualWrite(V7, relay_vao_State); 
    }
    digitalWrite(relay_ra, relay_ra_State);
    Serial.println("Chế độ Thủ công: Đang " + String(relay_ra_State ? "BẬT" : "TẮT") + " relay_ra");
  }
}

BLYNK_WRITE(V3) {
  if (chedo_hoatdong) {
    relay_bomtuoi_State = param.asInt();
    digitalWrite(relay_bomtuoi, relay_bomtuoi_State);
    Serial.println("Chế độ Thủ công: Đang " + String(relay_bomtuoi_State ? "BẬT" : "TẮT") + " bom tưới");
  } else {
    Blynk.virtualWrite(V3, relay_bomtuoi_State); 
  }
}

BLYNK_WRITE(V2) {
  autoModeState = param.asInt();
  Blynk.virtualWrite(CHEDO, autoModeState); 
  Serial.println("Nút V2 được nhấn! Chế độ Tự động: " + String(autoModeState));
  if (autoModeState == 0) {
    chedo_hoatdong = false;
    Serial.println("Chế độ hoạt động: Tự động");
  } else {
    chedo_hoatdong = true;
    Serial.println("Chế độ hoạt động: Thủ công");
    Serial.println("Trạng thái đèn: " + String(relay_den_State ? "BẬT" : "TẮT")); 
  }
}

BLYNK_WRITE(DOAM_BAT){
  doam_bat = param.asInt();
  Serial.println("Độ ẩm MIN: " + String(doam_bat) + "%");
}

BLYNK_WRITE(DOAM_TAT){
  doam_tat = param.asInt();
  Serial.println("Độ ẩm MAX: " + String(doam_tat) + "%");
}

BLYNK_CONNECTED() {
  Blynk.virtualWrite(V2, autoModeState);
  Blynk.virtualWrite(V3, relay_bomtuoi_State); 
  Blynk.virtualWrite(V6, relay_ra_State);
  Blynk.virtualWrite(V7, relay_vao_State);
  Blynk.virtualWrite(V9, relay_den_State);
  
}

TaskHandle_t Task1;
TaskHandle_t Task2;

void Task1code(void* pvParameters) {
  
  for (;;) {
       if (WiFi.status() != WL_CONNECTED) {
    Blynk.connectWiFi(ssid, pass);
  }
  if (!Blynk.connected()) {
    Blynk.connect();
  }
if(ledconnect.getValue()){
      ledconnect.off();
    }else{
      ledconnect.on();
    }
  Blynk.run();
  timeClient.update();

int hours = timeClient.getHours();
int minutes = timeClient.getMinutes();
int seconds = timeClient.getSeconds();

int t = dht.readTemperature(); 
Blynk.virtualWrite(V0, t); 

int doamdat = analogRead(DOAMDAT); 
doamdat = constrain(doamdat, 0, 4095);
int percent = map(doamdat, 0, 4095, 100, 0); 
Blynk.virtualWrite(V1, percent); 

if (digitalRead(button_oled) == LOW) {
  displayText = !displayText;
  delay(500); 
}

display.setTextSize(1);

if (displayText) {
  display.clearDisplay();
  display.setCursor(42, 0);
  char buffer[9];
  sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
  display.println(buffer);
  // Hiển thị thông tin cá nhân
  display.setCursor(10, 9); // Đặt con trỏ tại vị trí ngay dưới thời gian
  display.println("PHAM NGOC TUAN K18");
  // Hiển thị trạng thái các relay
  display.setCursor(16, 21); // Đặt con trỏ tại vị trí dòng đầu tiên
  display.println("Che do: " + String(chedo_hoatdong ? "THU CONG" : "TU DONG"));
  display.setCursor(6, 32);
  relay_bomtuoi_State = digitalRead(relay_bomtuoi);
  display.println("Bom: " + String(relay_bomtuoi_State ? "BAT" : "TAT"));
  display.setCursor(61, 32);
  relay_den_State = digitalRead(relay_den);
  display.println("- Den: " + String(relay_den_State ? "BAT" : "TAT"));
  if (relay_ra_State == HIGH && relay_vao_State == LOW) {
    display.setCursor(17, 42);
    display.println(" Mai che [ RA ]");
  } else if (relay_ra_State == LOW && relay_vao_State == HIGH) {
    display.setCursor(17, 42);
    display.println(" Mai che [ VAO ]");
  } else if (relay_ra_State == LOW && relay_vao_State == LOW) {
    display.setCursor(15, 42);
    display.println("Mai che [ DUNG ]");
  }
  display.setCursor(0,54);
  display.println("T: " + String(t) + " *C");
  display.setCursor(68,54);
  display.println("- H: " + String(percent) + " %");
  display.display();
} else {

  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(42, 0);
  char buffer[9];
  sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
  display.println(buffer);
  display.setCursor(10, 9); 
  display.println("PHAM NGOC TUAN K18");
  display.setTextSize(2);
  display.setCursor(10,22);
  display.println("T: " + String(t) + " *C");
  display.setCursor(20,44);
  display.println("H: " + String(percent) + " %");
  display.display(); 
}

  if (digitalRead(button_chedo) == LOW) {
  chedo_hoatdong = !chedo_hoatdong;
  delay(500);
  Blynk.virtualWrite(CHEDO, chedo_hoatdong ? 1 : 0);
  Blynk.virtualWrite(V2, chedo_hoatdong ? 1 : 0);
  Serial.println("Chế độ hoạt động: " + String(chedo_hoatdong ? "Thủ công" : "Tự động"));
  }
  if (chedo_hoatdong && digitalRead(button_den) == LOW) {
    relay_den_State = !relay_den_State; 
    delay(500);
    digitalWrite(relay_den, relay_den_State);  
    Blynk.virtualWrite(V9, relay_den_State);  
 }
  if (chedo_hoatdong && digitalRead(button_bomtuoi) == LOW) {
  relay_bomtuoi_State = !relay_bomtuoi_State;
  delay(500); 
  digitalWrite(relay_bomtuoi, relay_bomtuoi_State); 
  Blynk.virtualWrite(V3, relay_bomtuoi_State); 
  }
  if (!chedo_hoatdong) {
    int currentHour = timeClient.getHours();
    int currentMinute = timeClient.getMinutes();
    if ((currentHour > autoOnHour || (currentHour == autoOnHour && currentMinute >= autoOnMinute)) &&
        (currentHour < autoOffHour || (currentHour == autoOffHour && currentMinute < autoOffMinute))) { // cùng giờ khác phút
      /*if ((currentHour >= autoOnHour && currentMinute >= autoOnMinute) || 
    (currentHour < autoOffHour || (currentHour == autoOffHour && currentMinute < autoOffMinute))) {// khác giờ khác phút*/
      digitalWrite(relay_den, HIGH);
      Blynk.virtualWrite(V9, 1);
   } else {
      digitalWrite(relay_den, LOW);
      Blynk.virtualWrite(V9, 0);
   }
  }
  if (chedo_hoatdong) {
    if (digitalRead(button_ra) == LOW) {
      relay_ra_State = !relay_ra_State;
      delay(500);
      relay_vao_State = LOW;
      digitalWrite(relay_ra, relay_ra_State);
      digitalWrite(relay_vao, relay_vao_State);
      Blynk.virtualWrite(V6, relay_ra_State);
      Blynk.virtualWrite(V7, relay_vao_State);
   }
    if (digitalRead(button_vao) == LOW) {
      relay_vao_State = !relay_vao_State;
      delay(500);
      relay_ra_State = LOW;
      digitalWrite(relay_vao, relay_vao_State);
      digitalWrite(relay_ra, relay_ra_State);
      Blynk.virtualWrite(V7, relay_vao_State);
      Blynk.virtualWrite(V6, relay_ra_State);
  }
  }
  if (!chedo_hoatdong) { 
    if (t > tempHigh) {
      relay_ra_State = HIGH; 
      relay_vao_State = LOW; 
      digitalWrite(relay_ra, relay_ra_State); 
      digitalWrite(relay_vao, relay_vao_State); 
      Blynk.virtualWrite(V6, relay_ra_State); 
      Blynk.virtualWrite(V7, relay_vao_State); 
   } else if (t <= tempLow) {
      relay_ra_State = LOW; 
      relay_vao_State = HIGH; 
      digitalWrite(relay_ra, relay_ra_State); 
      digitalWrite(relay_vao, relay_vao_State); 
      Blynk.virtualWrite(V6, relay_ra_State); 
      Blynk.virtualWrite(V7, relay_vao_State); 
      }
  }
   if (!chedo_hoatdong) { 
    if (percent <= doam_bat/* && ((hours >= 17 && minutes >= 0 && seconds >= 0) || (hours <= 8 && minutes <= 0 && seconds <= 0))*/) {
      relay_bomtuoi_State = HIGH; 
      digitalWrite(relay_bomtuoi, relay_bomtuoi_State); 
      Blynk.virtualWrite(V3, relay_bomtuoi_State); 

    } else if (percent >= doam_tat) {
      relay_bomtuoi_State = LOW; // 
      digitalWrite(relay_bomtuoi, relay_bomtuoi_State); 
      Blynk.virtualWrite(V3, relay_bomtuoi_State); 
    }
  }
  }
}

void Task2code(void* pvParameters) {
  for (;;) {
   // Kiểm tra xem đã đủ thời gian chờ chưa
    if ((millis() - lastTime) > timerDelay) {
      // Nếu đủ, cập nhật lại thời điểm cuối cùng
      lastTime = millis();
  int t = dht.readTemperature(); 
  Blynk.virtualWrite(V0, t); 
  int doamdat = analogRead(DOAMDAT); 
  doamdat = constrain(doamdat, 0, 4095);
  int percent = map(doamdat, 0, 4095, 100, 0); 
  Blynk.virtualWrite(V1, percent);
  if (isnan(percent) || isnan(t)) {
    Serial.println();
    Serial.println(F("Failed to read from DHT sensor!"));
    Serial.println();
    Status_Read_Sensor = "That_bai";
    t = 0.00;
    percent = 0;
  } else {
    Status_Read_Sensor = "Thanh_cong";
  }
  Serial.println();
  Serial.println("-------------");
  Serial.print(F("Status_Read_Sensor : "));
  Serial.print(Status_Read_Sensor);
  if (digitalRead(relay_bomtuoi) == HIGH)  Bom_State = "Bat";
  if (digitalRead(relay_bomtuoi) == LOW) Bom_State = "Tat";
  if (digitalRead(relay_den) == HIGH)  Den_State = "Bat";
  if (digitalRead(relay_den) == LOW) Den_State = "Tat";
  if (relay_ra_State == HIGH && relay_vao_State == LOW) {
    Maiche_State = "Ra";
  } else if (relay_ra_State == LOW && relay_vao_State == HIGH) {
    Maiche_State = "Vao"; 
  } else if (relay_ra_State == LOW && relay_vao_State == LOW) {
    Maiche_State = "Dung";
  }

  if (WiFi.status() == WL_CONNECTED) {
    digitalWrite(On_Board_LED_PIN, HIGH);
  
    String Send_Data_URL = Web_App_URL + "?sts=write";
    Send_Data_URL += "&srs=" + Status_Read_Sensor;
    Send_Data_URL += "&temp=" + String(t); 
    Send_Data_URL += "&humd=" + String(percent); 
    Send_Data_URL += "&bom=" + Bom_State; 
    Send_Data_URL += "&den=" + Den_State; 
    Send_Data_URL += "&maiche=" + Maiche_State;

    Serial.println();
    Serial.println("-------------");
    Serial.println("Send data to Google Spreadsheet...");
    Serial.print("URL : ");
    Serial.println(Send_Data_URL);

      HTTPClient http;
  
      http.begin(Send_Data_URL.c_str());
      http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
  
      int httpCode = http.GET(); 
      Serial.print("HTTP Status Code : ");
      Serial.println(httpCode);
  
      String payload;
      if (httpCode > 0) {
        payload = http.getString();
        Serial.println("Payload : " + payload);    
      }
      
      http.end();
    
    digitalWrite(On_Board_LED_PIN, LOW);
    Serial.println("-------------");
   }
  }
 }
}
void setup() {
  Serial.begin(115200);
  Serial.println();
  delay(1000);
  Blynk.begin(auth, ssid, pass);;
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);

  int connecting_process_timed_out = 20; 
  connecting_process_timed_out = connecting_process_timed_out * 2;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    digitalWrite(On_Board_LED_PIN, HIGH);
    delay(250);
    digitalWrite(On_Board_LED_PIN, LOW);
    delay(250);
    if (connecting_process_timed_out > 0) connecting_process_timed_out--;
    if (connecting_process_timed_out == 0) {
      delay(1000);
      ESP.restart();
    }
  }

  digitalWrite(On_Board_LED_PIN, LOW);
  
  pinMode(DOAMDAT, INPUT); 
  pinMode(relay_bomtuoi, OUTPUT); 
  pinMode(relay_ra, OUTPUT);  
  pinMode(relay_vao, OUTPUT); 
  pinMode(relay_den, OUTPUT);
  pinMode(On_Board_LED_PIN, OUTPUT);

  pinMode(button_oled, INPUT_PULLUP);
  pinMode(button_chedo, INPUT_PULLUP);
  pinMode(button_bomtuoi, INPUT_PULLUP); 
  pinMode(button_ra, INPUT_PULLUP); 
  pinMode(button_vao, INPUT_PULLUP); 
  pinMode(button_den, INPUT_PULLUP); 
  
  chedo_hoatdong = false;
  Blynk.virtualWrite(CHEDO, autoModeState); 
  Blynk.virtualWrite(V2, autoModeState);    
  Blynk.virtualWrite(V3, relay_bomtuoi_State); 
  timeClient.begin();

  dht.begin();

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);
  xTaskCreatePinnedToCore(
    Task1code, /* Tác vụ */
    "Task1",   /* Tên tác vụ */
    10000,     /* Kích thước ngăn xếp */
    NULL,      /* Tham số */
    1,         /* Độ ưu tiên */
    &Task1,    /* Đối tượng tác vụ */
    1);        /* Nhân CPU */

  xTaskCreatePinnedToCore(
    Task2code,
    "Task2",
    10000,
    NULL,
    1,
    &Task2,
    1);
}
void loop() {

}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module