#include <DHT.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// --- Config WiFi ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// --- Config OneSignal ---
const char* ONE_SIGNAL_APP_ID = "3d1d69c8-857a-4b46-a25b-c971b48801dd";
const char* ONE_SIGNAL_API_KEY = "os_v2_app_huowtsefpjfunis3zfy3jcab3xlach4ooifuqkvabepfijnrtm3jib26sarwjgijq7fvubnhnagelsliq5hh5brlby5jvaezzo6q5kq";
// --- Pins ---
#define DHTPIN 4
#define DHTTYPE DHT22
#define LED_GREEN 16
#define LED_RED 18
#define LED_YELLOW 23
#define BUZZER 13
// --- Limites ---
#define TEMP_MAX 65.0
#define HUM_MAX 80.0
// --- Objets ---
DHT dht(DHTPIN, DHTTYPE);
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
bool alerteSent = false;
// ============================================================
void setup() {
Serial.begin(115200);
// Attendre que le Serial Monitor soit prêt
while (!Serial) {
delay(10);
}
delay(2000);
Serial.println("========================================");
Serial.println("[BOOT] Démarrage du système...");
Serial.println("========================================");
// --- Pins ---
Serial.println("[INIT] Configuration des pins...");
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_YELLOW, OUTPUT);
pinMode(BUZZER, OUTPUT);
Serial.println("[INIT] ✔ Pins configurés : LED_GREEN(16), LED_RED(18), LED_YELLOW(23), BUZZER(13)");
// --- DHT ---
Serial.println("[INIT] Initialisation capteur DHT22 sur pin D4...");
dht.begin();
Serial.println("[INIT] ✔ DHT22 prêt");
// --- I2C / RTC ---
Serial.println("[INIT] Initialisation I2C (SDA=21, SCL=22)...");
Wire.begin(21, 22);
Serial.println("[INIT] ✔ I2C démarré");
Serial.println("[INIT] Initialisation RTC DS1307...");
if (!rtc.begin()) {
Serial.println("[INIT] ✘ ERREUR : RTC DS1307 non détecté !");
} else {
Serial.println("[INIT] ✔ RTC DS1307 détecté");
if (!rtc.isrunning()) {
Serial.println("[RTC] ⚠ RTC non synchronisé — synchronisation avec heure de compilation...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
Serial.println("[RTC] ✔ RTC synchronisé");
} else {
Serial.println("[RTC] ✔ RTC déjà en marche, heure conservée");
}
}
// --- LCD ---
Serial.println("[INIT] Initialisation LCD I2C 16x2 (adresse 0x27)...");
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(" Station Meteo ");
lcd.setCursor(0, 1);
lcd.print(" Initialisation");
Serial.println("[LCD] ✔ LCD allumé — affichage écran de bienvenue");
delay(2000);
lcd.clear();
// --- WiFi ---
Serial.printf("[WIFI] Connexion au réseau : %s\n", ssid);
WiFi.begin(ssid, password);
lcd.setCursor(0, 0);
lcd.print("Connexion WiFi..");
int tries = 0;
while (WiFi.status() != WL_CONNECTED && tries < 20) {
delay(500);
Serial.printf("[WIFI] Tentative %d/20...\n", tries + 1);
tries++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("[WIFI] ✔ Connecté au WiFi !");
Serial.printf("[WIFI] Adresse IP : %s\n", WiFi.localIP().toString().c_str());
lcd.setCursor(0, 1);
lcd.print("WiFi connecte! ");
} else {
Serial.println("[WIFI] ✘ Échec connexion WiFi — notifications désactivées");
lcd.setCursor(0, 1);
lcd.print("WiFi echec... ");
}
delay(1500);
lcd.clear();
Serial.println("========================================");
Serial.println("[BOOT] ✔ Initialisation terminée — boucle principale démarrée");
Serial.println("========================================\n");
}
// ============================================================
void sendOneSignalNotif(String title, String message) {
Serial.println("[NOTIF] Préparation envoi OneSignal...");
if (WiFi.status() != WL_CONNECTED) {
Serial.println("[NOTIF] ✘ WiFi non connecté — notification annulée");
return;
}
Serial.printf("[NOTIF] Titre : %s\n", title.c_str());
Serial.printf("[NOTIF] Message : %s\n", message.c_str());
HTTPClient http;
http.begin("https://onesignal.com/api/v1/notifications");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", String("Basic ") + ONE_SIGNAL_API_KEY);
Serial.println("[NOTIF] En-têtes HTTP configurés");
StaticJsonDocument<512> doc;
doc["app_id"] = ONE_SIGNAL_APP_ID;
doc["included_segments"][0] = "All";
doc["contents"]["en"] = message;
doc["headings"]["en"] = title;
String body;
serializeJson(doc, body);
Serial.printf("[NOTIF] Payload JSON : %s\n", body.c_str());
Serial.println("[NOTIF] Envoi de la requête POST...");
int code = http.POST(body);
if (code > 0) {
Serial.printf("[NOTIF] ✔ Réponse HTTP : %d\n", code);
Serial.printf("[NOTIF] Réponse serveur : %s\n", http.getString().c_str());
} else {
Serial.printf("[NOTIF] ✘ Erreur HTTP : %d\n", code);
}
http.end();
Serial.println("[NOTIF] Connexion HTTP fermée");
}
// ============================================================
void buzzerAlerte() {
Serial.println("[BUZZER] ▶ Déclenchement buzzer alerte (3 bips)");
for (int i = 0; i < 3; i++) {
Serial.printf("[BUZZER] Bip %d/3\n", i + 1);
tone(BUZZER, 1000, 200);
delay(300);
}
Serial.println("[BUZZER] ■ Buzzer terminé");
}
// ============================================================
void loop() {
Serial.println("----------------------------------------");
Serial.println("[LOOP] Nouvelle lecture...");
// --- Lecture DHT22 ---
Serial.println("[DHT] Lecture température et humidité...");
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (isnan(temp) || isnan(hum)) {
Serial.println("[DHT] ✘ ERREUR : Lecture invalide (NaN) !");
Serial.println("[LCD] Affichage erreur capteur");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Erreur capteur!");
Serial.println("[LED] LED_YELLOW ON (erreur capteur)");
digitalWrite(LED_YELLOW, HIGH);
delay(2000);
digitalWrite(LED_YELLOW, LOW);
Serial.println("[LED] LED_YELLOW OFF");
return;
}
Serial.printf("[DHT] ✔ Température : %.1f°C (limite : %.1f°C)\n", temp, TEMP_MAX);
Serial.printf("[DHT] ✔ Humidité : %.1f%% (limite : %.1f%%)\n", hum, HUM_MAX);
// --- Lecture RTC ---
Serial.println("[RTC] Lecture heure...");
DateTime now = rtc.now();
char timeStr[20];
sprintf(timeStr, "%02d/%02d/%04d %02d:%02d",
now.day(), now.month(), now.year(),
now.hour(), now.minute());
Serial.printf("[RTC] ✔ Heure actuelle : %s\n", timeStr);
// --- Évaluation alerte ---
bool alerte = (temp > TEMP_MAX || hum > HUM_MAX);
Serial.printf("[CHECK] Dépassement seuil ? %s\n", alerte ? "OUI ⚠" : "NON ✔");
if (temp > TEMP_MAX) Serial.printf("[CHECK] → Température %.1f°C > seuil %.1f°C\n", temp, TEMP_MAX);
if (hum > HUM_MAX) Serial.printf("[CHECK] → Humidité %.1f%% > seuil %.1f%%\n", hum, HUM_MAX);
if (alerte) {
// ---- MODE ALERTE ----
Serial.println("[MODE] ⚠ MODE ALERTE activé");
Serial.println("[LED] LED_GREEN OFF");
digitalWrite(LED_GREEN, LOW);
Serial.println("[LED] LED_RED ON");
digitalWrite(LED_RED, HIGH);
buzzerAlerte();
Serial.println("[LCD] Affichage message d'alerte");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("!!! ALERTE !!!");
lcd.setCursor(0, 1);
if (temp > TEMP_MAX) {
lcd.print("Temp: ");
lcd.print(temp, 1);
lcd.print((char)223);
lcd.print("C HIGH");
Serial.println("[LCD] → Ligne 2 : Température critique");
} else {
lcd.print("Hum: ");
lcd.print(hum, 1);
lcd.print("% HIGH");
Serial.println("[LCD] → Ligne 2 : Humidité critique");
}
// Notification OneSignal (une seule fois par alerte)
if (!alerteSent) {
Serial.println("[NOTIF] Première alerte — envoi notification OneSignal...");
String ctx = "";
if (temp > TEMP_MAX) ctx += "Temp: " + String(temp, 1) + "C ";
if (hum > HUM_MAX) ctx += "Hum: " + String(hum, 1) + "% ";
ctx += "| " + String(timeStr);
sendOneSignalNotif("Alerte Station Meteo", ctx);
alerteSent = true;
Serial.println("[NOTIF] ✔ Flag alerteSent = true (pas de doublon)");
} else {
Serial.println("[NOTIF] Alerte déjà envoyée — notification ignorée");
}
} else {
// ---- MODE NORMAL ----
Serial.println("[MODE] ✔ MODE NORMAL");
if (alerteSent) {
Serial.println("[MODE] Retour au normal — reset flag alerteSent");
alerteSent = false;
}
Serial.println("[LED] LED_RED OFF");
digitalWrite(LED_RED, LOW);
Serial.println("[LED] LED_GREEN ON");
digitalWrite(LED_GREEN, HIGH);
noTone(BUZZER);
Serial.println("[BUZZER] Buzzer silencieux");
Serial.printf("[LCD] Affichage : Temp=%.1f°C Hum=%.1f%%\n", temp, hum);
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temp, 1);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0, 1);
lcd.print("Hum: ");
lcd.print(hum, 1);
lcd.print("% ");
}
Serial.println("[LOOP] Attente 3 secondes...\n");
delay(3000);
}