This shows you the differences between two versions of the page.
iothings:proiecte:2025sric:smokedetector [2025/05/29 14:47] theodor.paraschiv |
iothings:proiecte:2025sric:smokedetector [2025/05/29 15:38] (current) theodor.paraschiv |
||
---|---|---|---|
Line 24: | Line 24: | ||
{{:iothings:proiecte:2025sric:smoke_detector_diagram.png?600 |}} | {{:iothings:proiecte:2025sric:smoke_detector_diagram.png?600 |}} | ||
+ | {{:iothings:proiecte:2025sric:smoke_detector_hardware.jpeg?600 |}} | ||
+ | |||
+ | |||
+ | ====== Software Implementation ====== | ||
+ | |||
+ | 🖥️ **Frontend** | ||
+ | |||
+ | * **TypeScript** – The frontend is a TypeScript-based single-page web application designed to visualize real-time gas and smoke concentration data retrieved from a Firebase Realtime Database | ||
+ | |||
+ | ☁️ **Backend** | ||
+ | |||
+ | * **Firebase** – serving as a cloud-hosted NoSQL data store for logging gas/smoke sensor values from the ESP32 microcontroller, data being structured by timestamp-based paths — e.g. /logs/1716760000/value — ensuring clean chronological ordering and ease of querying for frontend consumption | ||
+ | * **IFTTT** - acting as an automation service, receiving webhook triggers from the ESP32 whenever gas/smoke levels exceed a defined threshold, instantly dispatching email alerts to notify the user in real time | ||
+ | |||
+ | 📟 **Embedded Software (ESP32)** | ||
+ | |||
+ | Developed using the **Arduino Framework**, with the following libraries: | ||
+ | |||
+ | * **mobizt/Firebase Arduino Client Library for ESP8266 and ESP32@^4.4.17** – Interface for Firebase Realtime Database | ||
+ | |||
+ | |||
+ | 📝 **Code snippet** | ||
+ | |||
+ | <code> | ||
+ | |||
+ | #include <Arduino.h> | ||
+ | #include <WiFi.h> | ||
+ | #include <Firebase_ESP_Client.h> | ||
+ | #include "addons/TokenHelper.h" | ||
+ | #include "addons/RTDBHelper.h" | ||
+ | #include <HTTPClient.h> | ||
+ | |||
+ | #define IFTTT_URL "" | ||
+ | |||
+ | #define WIFI_SSID "" | ||
+ | #define WIFI_PASSWORD "" | ||
+ | |||
+ | #define API_KEY "" | ||
+ | #define DATABASE_URL "" | ||
+ | |||
+ | |||
+ | #define MQ2_PIN 23 | ||
+ | #define BUZZER_PIN 22 | ||
+ | |||
+ | // Firebase objects | ||
+ | FirebaseData fbdo; | ||
+ | FirebaseAuth auth; | ||
+ | FirebaseConfig config; | ||
+ | |||
+ | unsigned long sendDataPrevMillis = 0; | ||
+ | bool signupOK = false; | ||
+ | |||
+ | void triggerIFTTT() { | ||
+ | if (WiFi.status() == WL_CONNECTED) { | ||
+ | HTTPClient http; | ||
+ | http.begin(IFTTT_URL); | ||
+ | int httpResponseCode = http.GET(); | ||
+ | |||
+ | if (httpResponseCode > 0) { | ||
+ | Serial.print("IFTTT triggered, code: "); | ||
+ | Serial.println(httpResponseCode); | ||
+ | } else { | ||
+ | Serial.print("IFTTT trigger failed: "); | ||
+ | Serial.println(http.errorToString(httpResponseCode).c_str()); | ||
+ | } | ||
+ | http.end(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(115200); | ||
+ | pinMode(MQ2_PIN, INPUT); | ||
+ | pinMode(BUZZER_PIN, OUTPUT); | ||
+ | digitalWrite(BUZZER_PIN, LOW); | ||
+ | |||
+ | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | ||
+ | Serial.print("Connecting to Wi-Fi"); | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | Serial.print("."); | ||
+ | delay(300); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | Serial.print("Connected with IP: "); | ||
+ | Serial.println(WiFi.localIP()); | ||
+ | |||
+ | config.api_key = API_KEY; | ||
+ | config.database_url = DATABASE_URL; | ||
+ | |||
+ | if (Firebase.signUp(&config, &auth, "", "")) { | ||
+ | Serial.println("Firebase signup OK"); | ||
+ | signupOK = true; | ||
+ | } else { | ||
+ | Serial.printf("Signup failed: %s\n", config.signer.signupError.message.c_str()); | ||
+ | } | ||
+ | |||
+ | config.token_status_callback = tokenStatusCallback; | ||
+ | Firebase.begin(&config, &auth); | ||
+ | Firebase.reconnectWiFi(true); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 5000)) { | ||
+ | sendDataPrevMillis = millis(); | ||
+ | |||
+ | int smokeValue = analogRead(MQ2_PIN); | ||
+ | Serial.print("MQ-2 Sensor value: "); | ||
+ | Serial.println(smokeValue); | ||
+ | |||
+ | // Control buzzer | ||
+ | if (smokeValue > 300) { | ||
+ | digitalWrite(BUZZER_PIN, HIGH); | ||
+ | triggerIFTTT(); | ||
+ | } else { | ||
+ | digitalWrite(BUZZER_PIN, LOW); | ||
+ | } | ||
+ | |||
+ | unsigned long currentTimestamp = Firebase.getCurrentTime(); | ||
+ | String path = "/logs/" + String(currentTimestamp) + "/value"; | ||
+ | |||
+ | if (Firebase.RTDB.setInt(&fbdo, path.c_str(), smokeValue)) { | ||
+ | Serial.print("Data sent: "); | ||
+ | Serial.print(smokeValue); | ||
+ | Serial.print(" at "); | ||
+ | Serial.println(currentTimestamp); | ||
+ | } else { | ||
+ | Serial.print("Send failed: "); | ||
+ | Serial.println(fbdo.errorReason()); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | 📱 **Web** | ||
+ | |||
+ | {{:iothings:proiecte:2025sric:smoek_detector_web.png?600 |}} | ||
+ | |||
+ | |||
+ | |||
+ | ====== References ====== | ||
+ | |||
+ | * [[https://ocw.cs.pub.ro/courses/iothings/laboratoare/2022/lab4]] | ||
+ | * [[https://ocw.cs.pub.ro/courses/iothings/laboratoare/2022/lab5]] | ||
+ | * [[https://randomnerdtutorials.com/guide-for-mq-2-gas-smoke-sensor-with-arduino/]] | ||
+ | * [[https://www.circuitbasics.com/how-to-send-a-text-message-with-ifttt/]] | ||