#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHTesp.h"

// Thông tin kết nối MQTT
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* mqtt_topic = "nhietdoam";  // Topic cho dữ liệu gốc
const char* mqtt_topic1 = "nhietdoam_trungbinh";  // Topic cho giá trị trung bình
const char* mqtt_topic2 = "nhietdoam_canhbao";  // Topic cho cảnh báo
const char* MQTT_ID = "1cf9d474-41f9-458d-970e-15ec958ed4ac";

WiFiClient espClient;
PubSubClient client(espClient);

// Thông tin kết nối Wi-Fi
const char* ssid = "Wokwi-GUEST";  
const char* password = "";  

// Cấu hình cảm biến DHT22
const int DHTPIN = 15;       
#define DHTTYPE DHT22 
DHTesp dhtSensor;  // Khởi tạo đối tượng DHT

// Cấu hình LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);  // Địa chỉ I2C là 0x27, màn hình 16x2

// Mảng lưu 3 giá trị nhiệt độ và độ ẩm gần nhất
float temperatureValues[3] = {0};  
float humidityValues[3] = {0};     
int currentIndex = 0;  // Chỉ số vị trí mảng

void WIFIConnect() {
  Serial.println("Connecting to SSID: Wokwi-GUEST");
  WiFi.begin("Wokwi-GUEST", "");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected");
  Serial.print(", IP address: ");
  Serial.println(WiFi.localIP());
}

void MQTT_Reconnect() {
  while (!client.connected()) {
    if (client.connect(MQTT_ID)) {
      Serial.print("MQTT Topic: ");
      Serial.print(mqtt_topic);
      Serial.println(" connected");
      Serial.print("MQTT Topic: ");
      Serial.print(mqtt_topic1);
      Serial.println(" connected");
      Serial.print("MQTT Topic: ");
      Serial.print(mqtt_topic2);
      Serial.println(" connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.println(topic);
  Serial.print("Message: ");
  String stMessage;

  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    stMessage += (char)message[i];
  }
  lcd.setCursor(0,1);
  lcd.print("                 ");
  lcd.print(stMessage);
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  dhtSensor.setup(DHTPIN, DHTesp::DHT22);  // Sử dụng phương thức setup() để chỉ định chân DHT

  WIFIConnect();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  lcd.init();
  lcd.backlight();

  // Hiển thị chào mừng
  lcd.setCursor(3, 0);
  lcd.print("Welcome!");
  
  // Kết nối với MQTT và đăng ký topic
  client.subscribe(mqtt_topic2);
}

void loop() {
  delay(10);
  if (!client.connected()) {
    MQTT_Reconnect();
    client.subscribe(mqtt_topic2);
  }
  client.loop();

  // Đọc dữ liệu từ cảm biến DHT22
  float humidity = dhtSensor.getHumidity();
  float temperature = dhtSensor.getTemperature();

  // Kiểm tra dữ liệu có hợp lệ không
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Lưu giá trị vào mảng (3 giá trị gần nhất)
  temperatureValues[currentIndex] = temperature;
  humidityValues[currentIndex] = humidity;
  currentIndex = (currentIndex + 1) % 3; // Vị trí sẽ quay lại 0 sau khi đạt 3

  // Tính giá trị trung bình
  float avgTemperature = (temperatureValues[0] + temperatureValues[1] + temperatureValues[2]) / 3.0;
  float avgHumidity = (humidityValues[0] + humidityValues[1] + humidityValues[2]) / 3.0;

  // Gửi giá trị hiện tại lên MQTT
  String message = String(temperature) + "|" + String(humidity);
  client.publish(mqtt_topic, message.c_str()); // Gửi thông tin nhiệt độ và độ ẩm vào topic gốc
  // Gửi giá trị trung bình lên MQTT
  String avgMessage = String(avgTemperature) + "|" + String(avgHumidity);
  client.publish(mqtt_topic1, avgMessage.c_str());

  // Cảnh báo nếu nhiệt độ trung bình cao
  if (avgTemperature >= 60) {
    client.publish(mqtt_topic2, "Cảnh báo nhiệt độ cao!");
  } else {
    client.publish(mqtt_topic2, "Bình thường");
  }
  

  // Hiển thị dữ liệu trên LCD
  lcd.clear(); // Xóa nội dung cũ trên LCD
  lcd.setCursor(0, 0); // Đặt con trỏ tại vị trí đầu tiên của LCD
  lcd.print("Temp: ");
  lcd.print(avgTemperature);
  lcd.print(" C");

  lcd.setCursor(0, 1); // Chuyển con trỏ xuống dòng tiếp theo
  lcd.print("Humidity: ");
  lcd.print(avgHumidity);
  lcd.print(" %");

  // Thêm delay để giữ dữ liệu trên màn hình một thời gian
  delay(1000); // Cập nhật mỗi 1 giây
}










// <!DOCTYPE html>
// <html lang="en">
// <head>
//     <meta charset="UTF-8">
//     <meta name="viewport" content="width=device-width, initial-scale=1.0">
//     <title>Temperature and Humidity Dashboard</title>
//     <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
//     <style>
//         body {
//             font-family: Arial, sans-serif;
//             background-color: #f4f4f9;
//             padding: 20px;
//         }
//         .dashboard {
//             text-align: center;
//         }
//         .data {
//             font-size: 24px;
//             margin: 20px;
//         }
//         .alert {
//             color: red;
//             font-weight: bold;
//         }
//         .normal {
//             color: green;
//             font-weight: bold;
//         }
//     </style>
// </head>
// <body>
//     <div class="dashboard">
//         <h1>Nhiệt Độ Và Độ Ẩm</h1>
//         <div class="data">
//             <p><strong>Nhiệt độ : </strong><span id="temperature">Loading...</span> °C</p>
//             <p><strong>Độ ẩm : </strong><span id="humidity">Loading...</span> %</p>
//             <p><strong>Nhiệt độ trung bình : </strong><span id="avgTemperature">Loading...</span> °C</p>
//             <p><strong>Độ ẩm trung bình : </strong><span id="avgHumidity">Loading...</span> %</p>
//             <p><strong>Trạng thái : </strong><span id="status">Loading...</span></p>
//         </div>
//     </div>

//     <script>
//         // Khai báo MQTT thông tin kết nối
//         const mqttServer = 'wss://broker.emqx.io:8084/mqtt'; // Broker MQTT hỗ trợ WebSockets
//         const clientId = 'webClient-' + Math.random().toString(36).substr(2, 9);  // Tạo ID ngẫu nhiên cho client
//         const mqttTopic = 'nhietdoam';  // Topic nhiệt độ và độ ẩm
//         const mqttTopic1 = 'nhietdoam_trungbinh';  // Topic giá trị trung bình
//         const mqttTopic2 = 'nhietdoam_canhbao';  // Topic cảnh báo

//         const client = mqtt.connect(mqttServer, {
//             clientId: clientId,
//             clean: true
//         });

//         let temperature = 0;
//         let humidity = 0;
//         let avgTemperature = 0;
//         let avgHumidity = 0;

//         // Khi kết nối thành công với broker
//         client.on('connect', function () {
//             console.log('Connected to MQTT broker');
//             client.subscribe([mqttTopic, mqttTopic1, mqttTopic2], function (err) {
//                 if (!err) {
//                     console.log('Subscribed to topics');
//                 } else {
//                     console.log('Subscription error: ', err);
//                 }
//             });
//         });

//         // Khi nhận được tin nhắn từ broker
//         client.on('message', function (topic, message) {
//             let msg = message.toString();
//             if (topic === mqttTopic) {
//                 // Nhận thông điệp nhiệt độ và độ ẩm
//                 const [temp, hum] = msg.split('|').map(parseFloat);

//                 // Lưu giá trị và hiển thị
//                 temperature = temp;
//                 humidity = hum;

//                 document.getElementById('temperature').textContent = temperature.toFixed(2);
//                 document.getElementById('humidity').textContent = humidity.toFixed(2);
//             } else if (topic === mqttTopic1) {
//                 // Nhận giá trị trung bình từ topic nhietdoam_trungbinh
//                 const [avgTemp, avgHum] = msg.split('|').map(parseFloat);

//                 avgTemperature = avgTemp;
//                 avgHumidity = avgHum;

//                 document.getElementById('avgTemperature').textContent = avgTemperature.toFixed(2);
//                 document.getElementById('avgHumidity').textContent = avgHumidity.toFixed(2);
//             } else if (topic === mqttTopic2) {
//                 // Nhận cảnh báo từ topic cảnh báo
//                 document.getElementById('status').textContent = msg;
//                 if (msg === "Cảnh báo nhiệt độ cao!") {
//                     document.getElementById('status').classList.add('alert');
//                     document.getElementById('status').classList.remove('normal');
//                 } else {
//                     document.getElementById('status').classList.add('normal');
//                     document.getElementById('status').classList.remove('alert');
//                 }
//             }
//         });
//     </script>
// </body>
// </html>