#include <WiFi.h>
#include "PubSubClient.h"
#include "DHTesp.h"
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <DHT.h>
// --- Cấu hình ---
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define LCD_SDA 21
#define LCD_SCL 22
#define LDR_PIN 34
#define PIR_PIN 25
#define LED_LOSUOI 26
#define LED_DIEUHOA 27
#define LED_REM 32
#define LED_DEN 33
#define LED_DENNgoai 14
#define LED_CUA 12
// WiFi và MQTT
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* MQTT_ID = "c5afa5ae-d3a0-48b7-b850-92015a281909";
WiFiClient espClient;
PubSubClient client(espClient);
// Chủ đề MQTT
const char* topicTempHumidity = "Iot/Nhietdoam";
const char* topicLightStatus = "Iot/Rem";
const char* topicMotionStatus = "Iot/Den";
const char* topicOutdoorLight = "Iot/DenNgoai";
const char* topicDoorStatus = "Iot/Cua";
const char* topicControl = "Iot/Control"; // Chủ đề nhận lệnh từ MQTT
// Cảm biến DHT
DHTesp dhtSensor;
DHT dht(DHT_PIN, DHT_TYPE);
// LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Biến ngưỡng và trạng thái
float tempThresholdLow = 18.0;
float tempThresholdHigh = 30.0;
int lightThreshold = 800;
int timeoutLight = 10000; // Thời gian chờ cho đèn
unsigned long lastMotionTime = 0;
unsigned long tempLowStartTime = 0;
unsigned long tempHighStartTime = 0;
unsigned long tempWaitTime = 5000; // Thời gian chờ mặc định (5 giây)
// Kết nối WiFi
void WIFIConnect() {
Serial.println("Đang kết nối tới WiFi: Wokwi-GUEST");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi đã kết nối, IP: ");
Serial.println(WiFi.localIP());
}
// Kết nối MQTT
void MQTT_Reconnect() {
while (!client.connected()) {
Serial.println("Đang kết nối lại MQTT...");
if (client.connect(MQTT_ID)) {
Serial.println("Đã kết nối MQTT thành công");
client.subscribe(topicControl); // Đăng ký nhận lệnh từ MQTT
} else {
Serial.print("Kết nối MQTT thất bại, lỗi: ");
Serial.println(client.state());
delay(5000);
}
}
}
// Gửi thông báo qua MQTT
void sendMQTT(const char* topic, String payload) {
if (!client.connected()) {
Serial.println("MQTT không kết nối, đang thử lại...");
MQTT_Reconnect();
}
if (client.publish(topic, payload.c_str())) {
Serial.print("Gửi thành công: ");
Serial.println(payload);
} else {
Serial.println("Gửi thất bại!");
}
}
// Xử lý dữ liệu từ MQTT
void handleControl(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("Lệnh nhận được từ MQTT: ");
Serial.println(message);
// Xử lý lệnh bật/tắt thiết bị
if (message.startsWith("set_wait_time:")) {
String waitTimeStr = message.substring(14);
tempWaitTime = waitTimeStr.toInt() * 1000;
sendMQTT("Iot/Response", "Thời gian chờ đã cập nhật");
} else if (message == "bat_lo_suoi") {
digitalWrite(LED_LOSUOI, HIGH);
sendMQTT("Iot/Response", "Lò sưởi đã bật");
} else if (message == "tat_lo_suoi") {
digitalWrite(LED_LOSUOI, LOW);
sendMQTT("Iot/Response", "Lò sưởi đã tắt");
} else if (message == "bat_dieu_hoa") {
digitalWrite(LED_DIEUHOA, HIGH);
sendMQTT("Iot/Response", "Điều hòa đã bật");
} else if (message == "tat_dieu_hoa") {
digitalWrite(LED_DIEUHOA, LOW);
sendMQTT("Iot/Response", "Điều hòa đã tắt");
} else if (message == "mo_cua") {
digitalWrite(LED_CUA, HIGH);
sendMQTT("Iot/Response", "Cửa đã mở");
} else if (message == "dong_cua") {
digitalWrite(LED_CUA, LOW);
sendMQTT("Iot/Response", "Cửa đã đóng");
} else if (message == "bat_den") {
digitalWrite(LED_DENNgoai, HIGH);
sendMQTT("Iot/Response", "Cửa đã mở");
} else if (message == "tat_den") {
digitalWrite(LED_DENNgoai, LOW);
sendMQTT("Iot/Response", "Cửa đã đóng");
}
}
// Xử lý nhiệt độ và độ ẩm
void handleTemperatureHumidity() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Lỗi đọc cảm biến DHT!");
return;
}
// Hiển thị lên LCD
lcd.setCursor(0, 0);
lcd.printf("Nhiet do: %.1f C", temperature);
lcd.setCursor(0, 1);
lcd.printf("Do am: %.1f %%", humidity);
// Kiểm tra nhiệt độ thấp
if (temperature < tempThresholdLow) {
if (tempLowStartTime == 0) {
tempLowStartTime = millis();
}
if (millis() - tempLowStartTime > tempWaitTime) {
digitalWrite(LED_LOSUOI, HIGH);
lcd.setCursor(0, 2);
lcd.print("Nhiet do Thap");
lcd.setCursor(0, 3);
lcd.print("Bat lo suoi...");
delay(3000);
digitalWrite(LED_LOSUOI, LOW);
tempLowStartTime = 0;
}
} else if (temperature > tempThresholdHigh) {
if (tempHighStartTime == 0) {
tempHighStartTime = millis();
}
if (millis() - tempHighStartTime > tempWaitTime) {
digitalWrite(LED_DIEUHOA, HIGH);
lcd.setCursor(0, 2);
lcd.print("Nhiet do Cao");
lcd.setCursor(0, 3);
lcd.print("Bat dieu hoa...");
delay(3000);
digitalWrite(LED_DIEUHOA, LOW);
tempHighStartTime = 0;
}
} else {
lcd.setCursor(0, 2);
lcd.print("Nhiet do Binh");
lcd.setCursor(0, 3);
lcd.print("Thuong...");
}
// Gửi qua MQTT
String tempHumPayload = String("{\"temperature\":") + temperature + ", \"humidity\":" + humidity + "}";
sendMQTT(topicTempHumidity, tempHumPayload);
}
// Xử lý ánh sáng và rèm
void handleLight() {
int lightValue = analogRead(LDR_PIN);
if (lightValue > lightThreshold) {
digitalWrite(LED_REM, HIGH);
digitalWrite(LED_DENNgoai, LOW);
sendMQTT(topicLightStatus, "Ánh sáng cao, rèm đã đóng");
sendMQTT(topicOutdoorLight, "Đèn ngoài đã tắt");
} else {
digitalWrite(LED_REM, LOW);
digitalWrite(LED_DENNgoai, HIGH);
sendMQTT(topicLightStatus, "Ánh sáng thấp, rèm đã mở");
sendMQTT(topicOutdoorLight, "Đèn ngoài đã bật");
}
}
// Xử lý chuyển động
void handleMotion() {
bool motionDetected = digitalRead(PIR_PIN);
if (motionDetected) {
digitalWrite(LED_DEN, HIGH);
lastMotionTime = millis();
sendMQTT(topicMotionStatus, "Phát hiện chuyển động, bật đèn");
}
if (millis() - lastMotionTime > timeoutLight) {
digitalWrite(LED_DEN, LOW);
sendMQTT(topicMotionStatus, "Không có chuyển động, tắt đèn");
}
}
void setup() {
Serial.begin(115200);
WIFIConnect();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(handleControl); // Đặt hàm callback cho MQTT
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
dht.begin();
lcd.init();
lcd.backlight();
pinMode(LDR_PIN, INPUT);
pinMode(PIR_PIN, INPUT);
pinMode(LED_LOSUOI, OUTPUT);
pinMode(LED_DIEUHOA, OUTPUT);
pinMode(LED_REM, OUTPUT);
pinMode(LED_DEN, OUTPUT);
pinMode(LED_DENNgoai, OUTPUT);
pinMode(LED_CUA, OUTPUT);
digitalWrite(LED_LOSUOI, LOW);
digitalWrite(LED_DIEUHOA, LOW);
digitalWrite(LED_REM, LOW);
digitalWrite(LED_DEN, LOW);
digitalWrite(LED_DENNgoai, LOW);
digitalWrite(LED_CUA, LOW);
}
void loop() {
if (!client.connected()) {
MQTT_Reconnect();
}
client.loop();
Serial.println("Xử lý nhiệt độ và độ ẩm...");
handleTemperatureHumidity();
Serial.println("Xử lý ánh sáng...");
handleLight();
Serial.println("Xử lý chuyển động...");
handleMotion();
delay(1000);
}