#include <WiFi.h> // Thư viện để kết nối WiFi
#include "DHTesp.h" // Thư viện để sử dụng cảm biến DHT22
#include <Firebase_ESP_Client.h> // Thư viện để kết nối và sử dụng Firebase
#include <addons/TokenHelper.h> // Thư viện hỗ trợ tạo và quản lý token
#include <addons/RTDBHelper.h> // Thư viện hỗ trợ làm việc với Firebase Realtime Database
#include "Firebase.h" // Thư viện chính của Firebase
#include <ESP_Mail_Client.h>
// Cấu hình Firebase
#define API_KEY "AIzaSyBZM0gBLtJfUUKx0EO3bFk0Jhi5KQLRpyc" // API Key của Firebase
#define DATABASE_URL "https://fire-alarm-system-befab-default-rtdb.firebaseio.com" // URL của Firebase Realtime Database
#define USER_EMAIL "[email protected]" // Email của người dùng đã đăng ký trong Firebase
#define USER_PASSWORD "satthuvip965" // Mật khẩu của người dùng đã đăng ký trong Firebase
/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465
/* The sign in credentials */
#define AUTHOR_EMAIL "[email protected]"
#define AUTHOR_PASSWORD "qtee hfvh azpg xyoc"
/*Email người nhận*/
#define RECIPIENT_EMAIL "[email protected]"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
Session_Config S_config;
SMTP_Message message;
/* Callback function to get the Email sending status */
// Cấu hình WiFi
const char* WIFI_NAME = "Wokwi-GUEST"; // Tên mạng WiFi
const char* WIFI_PASSWORD = ""; // Mật khẩu WiFi
// Cấu hình chân GPIO
#define dhtPin 17 // Chân kết nối cảm biến DHT22
#define led_dht_detech 19 // Chân kết nối LED phát hiện nhiệt độ
#define led_gas_detech 18 // Chân kết nối LED phát hiện khí gas
#define led_flame_detech 5 // Chân kết nối LED phát hiện lửa
#define buzz 26 // Chân kết nối buzzer
#define flamePin 34 // Chân kết nối cảm biến lửa
#define MQ2Pin 35 // Chân kết nối cảm biến khí gas
// Định nghĩa âm thanh cho buzzer
#define NOTE_F4 349 // Tần số âm thanh F4 cho buzzer
// Khai báo và khởi tạo các biến
DHTesp dht; // Đối tượng cảm biến DHT22
WiFiClient client; // Đối tượng WiFiClient để kết nối với Firebase
// Cấu hình Firebase
FirebaseData fbdo; // Đối tượng FirebaseData để làm việc với Firebase
FirebaseAuth auth; // Đối tượng FirebaseAuth để xác thực người dùng
FirebaseConfig config; // Đối tượng FirebaseConfig để cấu hình Firebase
// Cấu trúc dữ liệu để lưu trạng thái cảm biến
typedef struct {
bool dht_sensor_detech = false; // Trạng thái cảm biến nhiệt độ
bool gas_sensor_detech = false; // Trạng thái cảm biến khí gas
bool flame_sensor_detech = false; // Trạng thái cảm biến lửa
bool burningState = false; // Trạng thái báo cháy
} fireDetech;
fireDetech Fire_handle; // Biến để lưu trạng thái cảm biến
void smtpCallback(SMTP_Status status);
// Hàm gửi dữ liệu lên Firebase
void sendDataToFirebase(float temperature, uint16_t gas, uint16_t flameLevel, bool burningState) {
if (Firebase.ready()) {
FirebaseJson json; // Tạo đối tượng FirebaseJson để chứa dữ liệu gửi lên Firebase
json.add("Temperature", temperature); // Thêm dữ liệu nhiệt độ vào JSON
json.add("Gas Value", gas); // Thêm dữ liệu khí gas vào JSON
json.add("Flame Value", flameLevel); // Thêm dữ liệu lửa vào JSON
json.add("burning state", burningState); // Thêm trạng thái cháy vào JSON
String path = "/ESP32"; // Đường dẫn trong Firebase Realtime Database
bool result = Firebase.RTDB.setJSON(&fbdo, path, &json); // Gửi dữ liệu JSON lên Firebase
if (result) {
Serial.println("Data sent to Firebase successfully"); // In thông báo thành công
} else {
Serial.println("Error sending data: " + fbdo.errorReason()); // In thông báo lỗi nếu có
}
}
}
// Hàm xử lý dữ liệu cảm biến
void sensorProcessing() {
// Đọc giá trị từ cảm biến DHT22
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
// Đọc giá trị từ cảm biến khí gas MQ2
uint16_t gas = analogRead(MQ2Pin);
// Đọc giá trị từ cảm biến lửa
uint16_t flameLevel = analogRead(flamePin);
// In dữ liệu ra màn hình serial
Serial.printf("Temp: %0.2f °C\n", temperature);
Serial.println("");
Serial.printf("Humidity: %0.2f%%\n", humidity);
Serial.println("");
Serial.printf("Gas level: %d ppm\n", gas);
Serial.println("");
Serial.printf("Flame level: %d\n", flameLevel);
Serial.println("");
Serial.println("-------------------------------------");
// Kiểm tra nhiệt độ và điều khiển LED
if (temperature >= 70) {
digitalWrite(led_dht_detech, HIGH); // Bật LED nếu nhiệt độ >= 70°C
Fire_handle.dht_sensor_detech = true;
} else {
digitalWrite(led_dht_detech, LOW); // Tắt LED nếu nhiệt độ < 70°C
Fire_handle.dht_sensor_detech = false;
}
// Kiểm tra giá trị khí gas và điều khiển LED
if (gas >= 400) {
digitalWrite(led_gas_detech, HIGH); // Bật LED nếu giá trị khí gas >= 300
Fire_handle.gas_sensor_detech = true;
} else {
digitalWrite(led_gas_detech, LOW); // Tắt LED nếu giá trị khí gas < 300
Fire_handle.gas_sensor_detech = false;
}
// Kiểm tra giá trị lửa và điều khiển LED
if (flameLevel >= 250) {
digitalWrite(led_flame_detech, HIGH); // Bật LED nếu giá trị lửa >= 250
Fire_handle.flame_sensor_detech = true;
} else {
digitalWrite(led_flame_detech, LOW); // Tắt LED nếu giá trị lửa < 250
Fire_handle.flame_sensor_detech = false;
}
// Gửi dữ liệu lên Firebase
sendDataToFirebase(temperature, gas, flameLevel, Fire_handle.burningState);
// Kiểm tra nếu tất cả cảm biến phát hiện cháy
if (Fire_handle.dht_sensor_detech || Fire_handle.flame_sensor_detech || Fire_handle.gas_sensor_detech) {
Fire_handle.burningState = true;
/* Declare the message class */
/* Set the message headers */
message.sender.name = F("Fire alarm system");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Detech fire");
message.addRecipient(F("Sara"), RECIPIENT_EMAIL);
//Send raw text message
String textMsg = "Temperaute: " + String(temperature) + "°C Gas: " + String(gas) + "ppm Flame: " + String(flameLevel) + "Lux";
message.text.content = textMsg.c_str();
message.text.charSet = "us-ascii";
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Connect to the server */
if (!smtp.connect(&S_config)){
ESP_MAIL_PRINTF("Connection error, Status Code: %d, Error Code: %d, Reason: %s\n", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn()){
Serial.println("\nNot yet logged in.");
}
else{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
if (!MailClient.sendMail(&smtp, &message))
ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
tone(buzz, NOTE_F4, 100); // Bật buzzer nếu phát hiện cháy
} else {
Fire_handle.burningState = false;
tone(buzz, 0, 100); // Tắt buzzer nếu không phát hiện cháy
}
}
// Hàm kết nối WiFi
void wifi_setup() {
WiFi.begin(WIFI_NAME, WIFI_PASSWORD); // Kết nối với mạng WiFi
while (WiFi.status() != WL_CONNECTED) { // Chờ kết nối WiFi
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("WiFi connected!"); // Thông báo kết nối thành công
Serial.println("Local IP: " + String(WiFi.localIP())); // In địa chỉ IP của thiết bị
WiFi.mode(WIFI_STA); // Đặt chế độ WiFi thành Station
}
void setup() {
Serial.begin(115200); // Khởi động Serial với tốc độ 115200 bps
// Cấu hình chân GPIO
pinMode(led_dht_detech, OUTPUT);
pinMode(led_flame_detech, OUTPUT);
pinMode(led_gas_detech, OUTPUT);
pinMode(buzz, OUTPUT);
pinMode(flamePin, INPUT);
pinMode(MQ2Pin, INPUT);
// Cấu hình Firebase
config.host = DATABASE_URL;
config.api_key = API_KEY;
auth.user.email = USER_EMAIL;
auth.user.password = USER_PASSWORD;
// Kết nối WiFi và Firebase
wifi_setup();
Firebase.begin(&config, &auth);
if (Firebase.ready()) {
Serial.println("Connected to Firebase"); // Thông báo kết nối Firebase thành công
} else {
Serial.println("Failed to connect to Firebase"); // Thông báo lỗi kết nối Firebase
}
Firebase.reconnectNetwork(true); // Kết nối lại mạng Firebase nếu cần
// Cấu hình cảm biến DHT22
dht.setup(dhtPin, DHTesp::DHT22);
/* Set the network reconnection option */
MailClient.networkReconnect(true);
/** Enable the debug via Serial port
* 0 for no debugging
* 1 for basic level debugging
*
* Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
/* Set the session config */
S_config.server.host_name = SMTP_HOST;
S_config.server.port = SMTP_PORT;
S_config.login.email = AUTHOR_EMAIL;
S_config.login.password = AUTHOR_PASSWORD;
S_config.login.user_domain = "";
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
S_config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
S_config.time.gmt_offset = 3;
S_config.time.day_light_offset = 0;
//if (!MailClient.sendMail(&smtp, &message))
//ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
void loop() {
sensorProcessing(); // Xử lý dữ liệu cảm biến
delay(1000); // Thời gian chờ giữa các vòng lặp
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status){
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success()){
// ESP_MAIL_PRINTF used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. AVR, SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
ESP_MAIL_PRINTF("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
ESP_MAIL_PRINTF("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients.c_str());
ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}