#include <FirebaseESP32.h>
#include <SD.h>
#include <DHT.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <Audio.h>  // Include your audio library
#include <esp_task_wdt.h>

// Firebase setup
#define FIREBASE_HOST "your-project-id.firebaseio.com"   // Your Firebase project
#define FIREBASE_AUTH "your-firebase-auth-key"           // Your Firebase API key

// Pin Definitions
#define DHTPIN 13
#define DHTTYPE DHT11
#define GAS_PIN 34
#define SIM800_TX 17
#define SIM800_RX 16
#define SD_CS 5      // Chip select pin for SD card
#define AUDIO_PIN 23  // Pin connected to the audio output

DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial sim800(SIM800_RX, SIM800_TX);
Audio audio; // Create an Audio object

// Firebase and SIM800 Setup
FirebaseData fbData;
String basePath = "/sensorData";

// Message and Sound Setup
String incomingSMS;

// SD Card setup for sound
File soundFile;

// Maximum number of retries for sending data to Firebase
const int MAX_RETRIES = 2;

// Watchdog timer configuration
const int WDT_TIMEOUT = 10;  // Timeout set to 10 seconds

// Function prototypes
void sendCommandToSIM800(String command);
void checkSMSForCodes(String sms);
void playSound(String soundFileName);
void sendDataToFirebase(float temp, float hum, int gas, int AQI, String collectedTime, String sentTime);
String getISOTime();
int calculateAQI(int gasValue);
void playAlertAudio();
void playDisasterAudio(String code);
void rebootSystem();
void fullSystemScan();
void emergencyReboot();
void initSIM800();

bool isPlaying = false; // To track if audio is currently playing

void setup() {
    Serial.begin(115200);
    sim800.begin(9600);
    esp_task_wdt_init(WDT_TIMEOUT, true);
    esp_task_wdt_add(NULL);

    // Initialize DHT sensor
    dht.begin();

    // Initialize SD card
    if (!SD.begin(SD_CS)) {
        Serial.println("SD card initialization failed");
        return;
    }
    audio.setPin(AUDIO_PIN); // Set the pin for audio output
    Serial.println("SD card initialized successfully");

    // Firebase initialization
    Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
    Firebase.reconnectWiFi(true);

    // SIM800 initialization
    initSIM800(); // Initialize the SIM module
}

void loop() {
    static unsigned long lastSendTime = 0;
    static int retryCount = 0;

    esp_task_wdt_reset(); // Reset the watchdog timer

    // Check for incoming SMS
    if (sim800.available()) {
        incomingSMS = sim800.readString();
        checkSMSForCodes(incomingSMS);
    }

    // Read sensors
    float temp = dht.readTemperature();
    float hum = dht.readHumidity();
    int gasValue = analogRead(GAS_PIN);

    // Calculate Air Quality Index (dummy logic for now)
    int AQI = calculateAQI(gasValue);

    // Get timestamps
    String dataCollected = getISOTime();
    String dataSent = getISOTime();  // Assume data is sent right after collection

    // Send data to Firebase with retries
    bool dataSentSuccessfully = sendDataToFirebase(temp, hum, gasValue, AQI, dataCollected, dataSent);

    if (!dataSentSuccessfully) {
        retryCount++;
        if (retryCount <= MAX_RETRIES) {
            Serial.println("Retrying to send data...");
            delay(5000);  // Wait before retrying
            sendDataToFirebase(temp, hum, gasValue, AQI, dataCollected, dataSent); // Retry sending data
        } else {
            Serial.println("Data send failed after retries. Performing full system scan and reboot.");
            fullSystemScan(); // Perform full system scan
            rebootSystem(); // Reboot the system
        }
    } else {
        retryCount = 0; // Reset retry count on successful send
    }

    // Check if audio is playing
    if (!isPlaying) {
        playAlertAudio(); // Play the alert audio first
    }

    delay(10000);  // Delay 10 seconds between readings
}

void initSIM800() {
    sendCommandToSIM800("AT");
    delay(1000);
    sendCommandToSIM800("AT+CMGF=1");  // Set SMS text mode
    delay(1000);
    sendCommandToSIM800("AT+CNMI=1,2,0,0,0");  // Immediate SMS notification
    delay(1000);
}

void sendCommandToSIM800(String command) {
    sim800.println(command);
    delay(1000);
    while (sim800.available()) {
        Serial.println(sim800.readString());
    }
}

void checkSMSForCodes(String sms)...
Read more »