Présentation
Composants
Branchements
Code ESP32
Alimentation programmée de la Livebox
en 12V par panneau Photovoltaïque
La
box ADSL consomme 10W X 24h X 31 jours = 7.44 KWh/mois.
Si je la coupe quand je dors, elle consomme 10W X 16h X 31 jours = 4.96 KWh/mois,
économie 2.48 KWh/mois
La
box fibre consomme 4.8W sans Wifi, 10.9W avec Wifi.
Si je la coupe quand je dors, elle consomme 4.8W X 16h X 31 jours = 2.38 KWh/mois,
économie 1.19 KWh/mois
Donc pour économiser l'électricité, et produire moins de chaleur en été,
un ESP32 avec un bouton poussoir avec une LED permet d'allumer/éteindre la box avant de dormir.
Mais à 23h20 si elle est éteinte, l'ESP32 l'allume 20 minutes pour permettre à l'
ESP32 Températures de se connecter au Wifi et envoyer ses données au serveur web, parce que le Wifi de la Box est activé automatiquement chaque jour seulement entre 23 heures et minuit.
Ainsi si je l'éteins avant de dormir, il la rallume à 23h20 pendant 20 minutes.
Ainsi si je pars longtemps en voyage ou travailler, la box n'est allumée que 20mn/jour, et pas de souci d'envoi des températures.
Et comme le tout est alimenté par panneaux photovoltaïques je peux couper le disjoncteur général 220V avant de partir, et ils peuvent couper EDF dans l'immeuble/le quartier.
Composants
/* Livebox alimentée en 12V solaire. Version: 12 septembre 2025
Au boot, l'ESP se connecte en Wifi à un Access Point du smartphone pour demander à un script PHP
le timestamp actuel pour faire settimeofday() et ensuite faire du gettimeofday().
OU
Je me réveille par Timer, il est 23h20. Si box éteinte je l'allume, me rendors 20mn,
et quand me réveille l'éteins, recale le Timer RTC via wifi livebox, et regarde combien de secondes dormir jusqu'à 23h20 (environ 24h - 20 minutes).
Si elle est déjà allumée, je ne fais rien car elle a été allumée par le bouton. Dormir 24h.
OU
Je me réveille parce que le bouton a été pressé:
Si box éteinte je l'allume.
Si box allumée: je l'éteins et m'endors jusqu'à 23h20.
Ainsi je peux éteindre la box et dormir, ou partir 1 mois, ils peuvent couper EDF dans appart/immeuble/quartier,
l'ESP l'allumera de 23h20 à 23h40 pour permettre à l'ESP Températures d'envoyer ses données.
C'est mieux que de laisser la Box tourner 24/7: économie entre 3 et 7KWh/mois.
Le code pour ESP32-C3 est différent:
- ESP_SLEEP_WAKEUP_GPIO est la bonne raison du réveil par bouton (au lieu de ESP_SLEEP_WAKEUP_EXT0)
- Pour le réveil par bouton, à la place de
esp_sleep_enable_ext0_wakeup((gpio_num_t)2,0); //Réveil par bouton 1 = High, 0 = Low
il faut
esp_deep_sleep_enable_gpio_wakeup(1 << WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_LOW);
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <sys/time.h>
#include <esp_sleep.h>
/*=============================================================*/
//#define DBUG
#define BOUTON (gpio_num_t)2
#define LED (gpio_num_t)3
#define RELAI (gpio_num_t)4
#define VIA_WIFI_ANDROID true
#define VIA_WIFI_LIVEBOX false
/*=============================================================*/
RTC_DATA_ATTR bool allumé = false;
RTC_DATA_ATTR bool boxAlluméeParESP = false;
/*=============================================================*/
void set_timestamp(bool android)
{
#ifdef DBUG
Serial.print("Connecting to WIFI");
#endif
if(android) WiFi.begin("AndroidAP31CF", "mdp");
else WiFi.begin("box_ssid","mdp");
while (WiFi.status() != WL_CONNECTED){
#ifdef DBUG
Serial.print(".");
#endif
digitalWrite(LED,HIGH);delay(200);
digitalWrite(LED,LOW); delay(200);
}
#ifdef DBUG
Serial.println("WiFi connected.");
#endif
HTTPClient http;
http.begin("https://apps.masta.fr/timestamp.php");
int httpCode = http.GET();
if (httpCode==200){
setenv("TZ","CET-1CEST,M3.5.0,M10.5.0/3",1); tzset();
struct timeval tv;
tv.tv_sec = uint64_t(atoi(http.getString().c_str()));
tv.tv_usec = 0;
settimeofday(&tv, NULL);
}
http.end();
WiFi.disconnect(true); //plus besoin de Wifi
WiFi.mode(WIFI_OFF);
}
/*=============================================================*/
void allumer(){
#ifdef DBUG
Serial.println("Allumer");
#endif
digitalWrite(LED, HIGH);
gpio_hold_en(LED);// maintenir LED allumée pendant sommeil
digitalWrite(RELAI, HIGH); // allumer la BOX
gpio_hold_en(RELAI);// maintenir RELAI allumé pendant sommeil
allumé = true;
gpio_deep_sleep_hold_en();
}
/*=============================================================*/
void eteindre(){
#ifdef DBUG
Serial.println("Éteindre");
#endif
digitalWrite (LED, LOW);
gpio_hold_dis(LED);
digitalWrite (RELAI, LOW); // éteindre la box
gpio_hold_dis(RELAI);
allumé = false;
}
/*=============================================================*/
int combienDormir(){
struct timeval tv;
struct timezone tz;
setenv("TZ","CET-1CEST,M3.5.0,M10.5.0/3",1); tzset();
gettimeofday(&tv,&tz);
struct tm* now = localtime(&tv.tv_sec);
#ifdef DBUG
Serial.print("il est ");
Serial.print(now->tm_hour); Serial.print("h");
Serial.print(now->tm_min); Serial.print("mn");
Serial.print(now->tm_sec); Serial.print("s");
#endif
// Combien de secondes jusqu'à 23h20?
int tstamp = now->tm_hour*3600 + now->tm_min*60 + now->tm_sec; // heure actuelle en secondes
int heureh = 23*3600 + 20*60; // 23h20 heure h en secondes
int dormirs = heureh - tstamp;
#ifdef DBUG
//Serial.print(" dormirs="); Serial.print(dormirs);
int dormirh = (int)(dormirs/3600);
int dormirmn = dormirs/60 - dormirh*60;
int sec = dormirs - dormirh*3600 - dormirmn*60;
Serial.print(" Jusqu'à 23h20 dormir ");
Serial.print(dormirh); Serial.print("h");
Serial.print(dormirmn); Serial.print("mn");
Serial.print(sec); Serial.println("s"); Serial.println("");
#endif
return dormirs;
}
/*=============================================================*/
void setup() {
#ifdef DBUG
Serial.begin(115200);
delay(1000);
//Serial.println("Reveil");
#endif
pinMode(BOUTON, INPUT_PULLUP);
pinMode(LED, OUTPUT);
pinMode(RELAI, OUTPUT);
uint64_t dormirs = 0;
esp_sleep_wakeup_cause_t wakeup_reason= esp_sleep_get_wakeup_cause();
// Réveil par bouton -------------------------------------------------
if(wakeup_reason == ESP_SLEEP_WAKEUP_GPIO){
#ifdef DBUG
Serial.println("Reveil par bouton");
#endif
if(!allumé) allumer(); else eteindre();
delay(200); // le temps de relacher le bouton
dormirs = combienDormir(); // combien dormir jusqu'à 23h20?
}
// Réveil par Timer --------------------------------------------------
else if(wakeup_reason == ESP_SLEEP_WAKEUP_TIMER){
#ifdef DBUG
Serial.println("Reveil par timer");
#endif
if(!allumé){
allumer();
boxAlluméeParESP = true;
dormirs = 20*60;
}
// si c'est l'ESP qui l'a allumée 20mn avant, alors l'éteindre
else if(boxAlluméeParESP){
eteindre();
boxAlluméeParESP = false;
set_timestamp(VIA_WIFI_LIVEBOX); // Recale le timer RTC
dormirs = combienDormir(); // Combien dormir jusqu'à 23h20? environ 24h - 20 minutes
}
// sinon c'est l'utilisateur qui l'a allumée avec le bouton: dormir 1 jour jusqu'à 23h20
else {delay(1000); dormirs = combienDormir();}//24*60*60;
}
// Réveil par BOOT ou RESET -----------------------------------------
// demande le timestamp à un script PHP pour faire settimeofday() et ensuite faire du gettimeofday()
else{
#ifdef DBUG
Serial.println("Reveil par Reboot/reset");
#endif
set_timestamp(VIA_WIFI_ANDROID);
dormirs = combienDormir(); // Combien de minutes dormir jusqu'à 23h20?
}
esp_deep_sleep_enable_gpio_wakeup(1 << BOUTON, ESP_GPIO_WAKEUP_GPIO_LOW); // réveil par bouton
esp_sleep_enable_timer_wakeup(dormirs* 1000000ULL); // réveil par timer
esp_deep_sleep_start();
}
void loop() {}
timestamp.php
<?php
echo time();
?>