Réservé : explications code ESP32
Le code sur l'ESP32 nécessite bien sûr une connexion Wifi pour la discussion avec les prises mais aussi pour connaitre l'heure (via un serveur NTP). Les horaires d'allumage des prises sont définis par une structure qui indique, pour chaque plage horaire :
- L'identifiant de la prise
- Les jours de la semaine
- L'heure et les minutes d'allumage
- L'heure et les minutes d'extinction
- Une durée aléatoire autour de ces horaires pour rendre le système moins prévisible
Quelques exemples :
{Salon, 0b1111111, 7, 10, 8, 0, 0}, /* every days, from 7:10 to 8:00, no random */
{Salon, 0b1000001, 21, 45, 23, 15, 20}, /* saturday & sunday, from 21:45 to 23:15, 20' random */
{Salon, 0b1000001, 23, 45, 0, 15, 10}, /* saturday & sunday, from 23:45 to 00:15, 10' random */
{Salon, 0b0111110, 22, 30, 23, 55, 15}, /* week days, from 22:30 to 23:55, 15' random */
{Salon, 0b0111000, 0, 15, 1, 25, 10}, /* -MTW---, from 00:15 to 01:05, 10' random */
Ensuite, chaque minute pleine, l'ESP32 vérifie si l'on entre ou sort d'une de ces plages et met à jour la ou les prises concernées.
Un affichage sur un petit écran OLED permet de connaitre l'état des prises à chaque instant.
L'ESP32 est à l'adresse IP fixe : 192.168.0.51, ça peut être changé dans le code. Lorsqu'on va sur http://192.168.0.51 on obtient l'IHM montrée plus haut, qui indique l'état de chaque prise : ON (bouton vert), OFF (bouton rouge) ou non connectée (bouton bleu). Le bouton est cliquable : ON <--> OFF.
Si on clique sur le nom de la prise, on accède à une nouvelle page qui liste les plages horaires associées.
La connexion à l'ESP32 est protégée par mot de passe, il est écrit en dur dans le code :
// Credentials to connect to the ESP32
const char* www_username = "***";
const char* www_password = "****";
Pour l'instant le code est configuré pour un nombre maximum de 8 prises, c'est réglable avec le paramètre
#define deviceNumber 8
Les identifiants vont donc de 0 à 7, ils sont redéfinis avec un enum :
enum device_t : byte {Salon, Cuisine, Couloir, SalleDeBain, ChLea, ChIrena, WC, Entree};
Les noms des prises sont définis ici
char deviceName[deviceNumber][31] = {"Salon", "Cuisine", "Couloir", "SdB",
"Ch.L", "Ch.I", "WC", "Entree"
};
On peut les changer dans le code mais aussi de manière interactive directement grâce à l'IHM des prises.
Pour le serveur web, j'utilise la bibliothèque WebServer.h pour ESP32, qui permet de gérer des commandes très simplement. Je me suis inspiré de ce tuto. Le traitement des commandes se fait grâce à la méthode 'on', déclarée dans le setup :
server.on("/", handle_OnConnect);
server.on("/on", handle_on);
server.on("/off", handle_off);
server.on("/list", handle_list);
Elle lie les requêtes à des fonctions appelées selon leur contenu. Ainsi si la requête contient 'on',l'ESP exécute la fonction handle_on qui envoie une commande d'allumage au relais concerné (en argument) et met à jour le serveur.
void handle_on() {
if (server.arg("id") == "") {
server.send(400, "text/plain", "Bad request");
} else {
byte device = server.arg(0).toInt();
deviceState[device] = ON;
sendCommand (device, 4);
char * ptr = webStatus ();
server.send(200, "text/html", ptr);
free(ptr);
}
}
A noter que j'ai réécrit les affichages sur le serveur sans utiliser de String pour éviter les problèmes de mémoire (avec allocation dynamique et libération de la chaîne de caractères de grande taille utilisée à chaque affichage).
L'envoi des commandes aux prises se fait par la fonction
state sendCommand (byte device, byte command) {
/*
List of available commands:
0 get id
1 get name
2 get status
3 switch off (relay and led)
4 switch on (relay and led)
5 blink
*/
6 commandes sont possibles pour l'instant. Elles sont envoyées lors du clic sur les boutons de l'IHM, ce qui permet de construire le texte de la requête contenant la commande et ses arguments.