commit bbf8f160a5b261219f7fdfc433cc226643455c58 Author: gilles Date: Sun Nov 24 16:42:52 2024 +0100 Ajouter main.cpp diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..72301e1 --- /dev/null +++ b/main.cpp @@ -0,0 +1,354 @@ +#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(); +} \ No newline at end of file