#include #include #include #include #include #include #include #include #include #include // Définition des broches #define RELAY_PIN 12 #define BUTTON_PIN 0 #define LED_PIN 13 // EEPROM #define EEPROM_SIZE 8 // Taille nécessaire pour stocker 4 octets pour la durée et 4 octets pour l'heure d'allumage // Configuration WiFi const char* ssid = "WifiHome2"; const char* password = "louca2212"; // Variables globales Bounce buttonDebouncer; ESP8266WebServer server(80); // Serveur Web sur le port 80 WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600); // Serveur NTP avec décalage UTC+1 bool relayState = false; unsigned long relayTimer = 0; unsigned long relayDuration = 60000; // 60 secondes par défaut bool saveSuccess = false; // Indique si l'EEPROM a été sauvegardée int relayStartHour = 0; // Heure d'allumage (par défaut 00) int relayStartMinute = 0; // Minute d'allumage (par défaut 00) unsigned long lastNTPUpdate = 0; // Temps de la dernière mise à jour NTP (en ms) // Fonction pour mettre à jour le client NTP toutes les 30 secondes void updateNTP() { unsigned long currentMillis = millis(); if (currentMillis - lastNTPUpdate >= 30000 || lastNTPUpdate == 0) { timeClient.update(); lastNTPUpdate = currentMillis; unsigned long rawTime = timeClient.getEpochTime(); Serial.println("Mise à jour NTP effectuée. Temps brut reçu : " + String(rawTime)); Serial.println("Temps formaté (UTC) : " + String(rawTime % 86400 / 3600) + ":" + String(rawTime % 3600 / 60)); } } // Fonction pour basculer l'état du relais void toggleRelay() { relayState = !relayState; digitalWrite(RELAY_PIN, relayState); if (relayState) { relayTimer = millis(); Serial.println("Relais activé"); } else { Serial.println("Relais désactivé"); } } // Fonction pour sauvegarder les paramètres dans l'EEPROM void saveSettings() { EEPROM.write(0, relayDuration / 60000); // Sauvegarde la durée en minutes EEPROM.write(1, relayStartHour); // Sauvegarde l'heure EEPROM.write(2, relayStartMinute); // Sauvegarde les minutes EEPROM.commit(); Serial.println("Paramètres sauvegardés dans l'EEPROM"); } // Fonction pour charger les paramètres depuis l'EEPROM void loadSettings() { relayDuration = EEPROM.read(0) * 60000; // Chargement de la durée en ms relayStartHour = EEPROM.read(1); // Chargement de l'heure relayStartMinute = EEPROM.read(2); // Chargement des minutes // Vérifier les valeurs invalides et appliquer des valeurs par défaut if (relayDuration == 0 || relayDuration > 10800000) relayDuration = 60000; // Valeur par défaut 60 secondes if (relayStartHour < 0 || relayStartHour >= 24) relayStartHour = 0; // Heure par défaut 00 if (relayStartMinute < 0 || relayStartMinute >= 60) relayStartMinute = 0; // Minute par défaut 00 Serial.println("Paramètres chargés :"); Serial.println("Durée du relais : " + String(relayDuration / 60000) + " minutes"); Serial.println("Heure d'allumage : " + String(relayStartHour) + ":" + String(relayStartMinute)); } // Fonction pour mettre à jour la LED en fonction de l'état void updateLED() { if (WiFi.status() != WL_CONNECTED) { digitalWrite(LED_PIN, LOW); // LED éteinte si déconnecté } else if (relayState) { digitalWrite(LED_PIN, LOW); // LED allumée si relais activé } else { digitalWrite(LED_PIN, HIGH); // LED éteinte si relais désactivé } } // Gestion des clics du bouton void handleButton() { if (buttonDebouncer.fell()) { Serial.println("Bouton pressé"); toggleRelay(); // Bascule le relais } } // Fonction pour obtenir l'heure au format HH:MM String getFormattedTime() { unsigned long rawTime = timeClient.getEpochTime(); unsigned long adjustedTime = rawTime ; int hours = (adjustedTime % 86400L) / 3600; // Heures int minutes = (adjustedTime % 3600) / 60; // Minutes char buffer[6]; snprintf(buffer, sizeof(buffer), "%02d:%02d", hours, minutes); return String(buffer); } // Calculer le délai en minutes avant le prochain allumage int calculateMinutesUntilNextStart() { unsigned long currentTime = timeClient.getEpochTime(); int currentHour = (currentTime % 86400L) / 3600; int currentMinute = (currentTime % 3600) / 60; // Convertir l'heure actuelle et l'heure de démarrage en minutes depuis minuit int currentTotalMinutes = currentHour * 60 + currentMinute; int startTotalMinutes = relayStartHour * 60 + relayStartMinute; // Calculer la différence int delay = startTotalMinutes - currentTotalMinutes; if (delay < 0) { delay += 1440; // Ajouter 24 heures si le délai est négatif (allumage le lendemain) } return delay; } int calculateMinutesUntilNextStop() { int delayUntilStart = calculateMinutesUntilNextStart(); if (relayState) { // Si le relais est déjà activé, calcule le temps restant jusqu'à son extinction unsigned long elapsedMillis = millis() - relayTimer; return max(0L, (long)((relayDuration - elapsedMillis) / 60000)); } else { // Si le relais est désactivé, ajoute la durée d'activation au délai jusqu'au prochain allumage return delayUntilStart + (relayDuration / 60000); } } // Page principale void handleMainPage() { updateNTP(); // Mettre à jour le client NTP si nécessaire String currentTime = getFormattedTime(); int nextStart = calculateMinutesUntilNextStart(); int nextStop = calculateMinutesUntilNextStop(); String relayStateColor = relayState ? "green" : "red"; // Détermine la couleur du texte String relayStateText = relayState ? "ACTIVÉ" : "DÉSACTIVÉ"; String html = R"rawliteral( Relais Sonoff

Relais Sonoff

Heure : TIME

État du relais : RELAY_STATE

Délai avant prochain allumage du relais : NEXT_START minutes

Délai avant prochaine extinction du relais : NEXT_STOP minutes

)rawliteral"; html.replace("TIME", currentTime); html.replace("RELAY_STATE", relayStateText); html.replace("RELAY_COLOR", relayStateColor); html.replace("NEXT_START", String(nextStart)); html.replace("NEXT_STOP", String(nextStop)); server.send(200, "text/html", html); } // Page des paramètres void handleSettingsPage() { // Charger les paramètres depuis l'EEPROM loadSettings(); // Générer la page HTML String html = R"rawliteral( Paramètres Relais

Paramètres Relais

Durée (minutes) :

Heure d'allumage : :

)rawliteral"; html.replace("DURATION", String(relayDuration / 60000)); html.replace("HOUR", String(relayStartHour)); html.replace("MINUTE", String(relayStartMinute)); server.send(200, "text/html", html); } // Sauvegarde des paramètres void handleSaveSettings() { JsonDocument doc; DeserializationError error = deserializeJson(doc, server.arg("plain")); if (error) { server.send(400, "text/plain", "Erreur JSON"); return; } relayDuration = doc["relayDuration"].as() * 60000; relayStartHour = doc["relayStartHour"].as(); relayStartMinute = doc["relayStartMinute"].as(); saveSettings(); server.send(200, "text/plain", "Paramètres sauvegardés."); } // Initialisation void setup() { Serial.begin(115200); Serial.println("Démarrage du programme..."); // Initialisation des broches pinMode(RELAY_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); digitalWrite(RELAY_PIN, LOW); digitalWrite(LED_PIN, LOW); Serial.println("Broches configurées"); // Configuration du bouton avec Bounce2 buttonDebouncer.attach(BUTTON_PIN); buttonDebouncer.interval(25); Serial.println("Bouton configuré"); // Connexion WiFi avec WiFiManager Serial.println("Connexion au WiFi..."); WiFiManager wifiManager; wifiManager.autoConnect("SonoffRelay", "password"); Serial.println("Connecté au WiFi : " + String(WiFi.SSID()) + " - IP : " + WiFi.localIP().toString()); EEPROM.begin(EEPROM_SIZE); loadSettings(); // Initialisation du client NTP timeClient.begin(); updateNTP(); server.on("/", handleMainPage); server.on("/settings", handleSettingsPage); server.on("/save", HTTP_POST, handleSaveSettings); server.begin(); Serial.println("Serveur web démarré"); } // Boucle principale void loop() { buttonDebouncer.update(); handleButton(); // Mise à jour de l'heure NTP timeClient.update(); // Gère les requêtes HTTP des clients server.handleClient(); // Obtenir l'heure actuelle unsigned long rawTime = timeClient.getEpochTime(); int currentHour = (rawTime % 86400L) / 3600; // Heures actuelles int currentMinute = (rawTime % 3600) / 60; // Minutes actuelles // Vérifier si l'heure actuelle correspond à l'heure d'allumage if (!relayState && currentHour == relayStartHour && currentMinute == relayStartMinute) { Serial.println("Allumage automatique du relais à l'heure programmée"); toggleRelay(); // Allume le relais } // Gestion du relais (arrêt automatique après la durée spécifiée) if (relayState && millis() - relayTimer >= relayDuration) { Serial.println("Extinction automatique du relais après la durée configurée"); toggleRelay(); // Éteint le relais } // Mise à jour de la LED updateLED(); }