/* import des librairies */
#include <ESP8266WiFi.h> // pour la gestion du wifi
#include <ESPAsyncTCP.h> // pour la gestion des connections TCP asynchrones
#include <ESPAsyncWebServer.h> // pour un serveur web asynchrone
#include "fauxmoESP.h" // pour se connecter a Alexa
#include <ArduinoOTA.h> // pour mettre a jour la carte à distance
/* déclaration des constantes */
#define MON_SSID "XXXXXXX" // votre réseau wifi
#define MA_CLE_WIFI "XXXXXXXXXXXXXXXXXX" // votre clé wifi
#define PORT_SERVEUR 8080 // le port du serveur web
#define PORT_FAUXMO 80 // le port pour communiquer avec Alexa
#define HOST "TEST_fauxmo" // le nom pour le port réseau (OTA)
#define ID_LED "ma led" // le nom pour Alexa
#define BOUTON_PIN D3
/* déclaration des variables */
bool flag_led, flag_bouton = false; // 2 flags, un pour le bouton et un pour l'état de la led
/* déclaration des objets */
AsyncWebServer serveur(PORT_SERVEUR); // on définie un serveur web nommé serveur
fauxmoESP fauxmo; // on définie l'objet fauxmo
/* déclaration des fonctions */
// fonction qui créer la page web
String SendHTML() {
String couleur, etat; // on déclare 2 variables vide
if (flag_led) { // si flag_led est activé
couleur = "green"; // couleur vaut vert
etat = "ON"; // etat vaut ON
}
else { // si flag_led est désactivé
couleur = "red"; // couleur vaut rouge
etat = "OFF"; // etat vaut OFF
}
// on créer la page HTML avec nos variable qui se mettra à jour en temps réel
String page = "<!DOCTYPE html>\n";
page += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
page += "<title>TEST fauxmo, serveur web et OTA</title>\n";
page += "<script>\n";
page += "setInterval(loadDoc,200);\n";
page += "function loadDoc() {\n";
page += "var xhttp = new XMLHttpRequest();\n";
page += "xhttp.onreadystatechange = function() {\n";
page += "if (this.readyState == 4 && this.status == 200) {\n";
page += "document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
page += "};\n";
page += "xhttp.open(\"GET\", \"/\", true);\n";
page += "xhttp.send();\n";
page += "}\n";
page += "</script>\n";
page += "</head>\n";
page += "<body style='background:#C7C4C4; margin-top: 50px; text-align: center;'>\n";
page += "<div id=\"webpage\">\n";
page += "<h1>TEST fauxmo,serveur web et OTA</h1>\n";
page += "<p><a href=\"on\"><button style='background:#90EE90;border:2px solid black;font-weight: bold;font-size: 20px;padding: 20px 20px;border-radius: 25px;'>LED ON</button></a>\n";
page += " \n";
page += "<a href=\"off\"><button style='background:#F78A8A;border:2px solid black;font-weight: bold;font-size: 20px;padding: 20px 20px;border-radius: 25px;'>LED OFF</button></a></p>\n";
page += "<p style='font-size:2em; font-weight:bold;'>Etat de la LED : ";
page += "<span style='color:";
page += couleur;
page += ";'> ";
page += etat;
page += "</span></p>\n";
page += "</div>\n";
page += "</body>\n";
page += "</html>\n";
return page;
}
// on crée la fonction qui donne l'état de la led
String envoyer_etat_led() {
String etat;
flag_led ? etat = "ON" : etat = "OFF";
return etat;
}
// on crée la fonction si la page n'existe pas
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Essaye IP:8080/on ou off");
}
// on crée la fonction d'interruption
ICACHE_RAM_ATTR void handleInterrupt() {
// on active le flag
flag_bouton = true;
// un délai pour la sensibilité du bouton
delay(100);
}
/* le setup */
void setup() {
// on démarre la com série
Serial.begin(115200);
delay(250);
Serial.println();
// on déclare broche de la led interne en sortie
pinMode(LED_BUILTIN, OUTPUT);
// on déclare broche du bouton en entée avec un pullup
pinMode(BOUTON_PIN, INPUT_PULLUP);
// on paramètre le wifi en mode station (connecté sur la box)
WiFi.mode(WIFI_STA);
// on démarre le wifi
WiFi.begin(MON_SSID, MA_CLE_WIFI);
// tant qu'on est pas connecté la led clignote
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
digitalWrite(LED_BUILTIN, LOW);
delay(250);
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
}
Serial.println();
// on informe l'IP
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// on éteint la led interne (etat inverse pour la led interne)
digitalWrite(LED_BUILTIN, HIGH);
// on envoie la fonction SendHTML() si on se connecte à la racine de l'URL (IP:8080)
serveur.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send(200, "text/html", SendHTML());
});
// on envoie la fonction envoyer_etat_led() si on se connecte à l'onglet /etat de l'URL (IP:8080/etat)
serveur.on("/etat", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send(200, "text/html", envoyer_etat_led());
});
// on allume la led et envoi la fonction SendHTML() à l'onglet /on de l'URL (IP:8080/on)
serveur.on("/on", HTTP_GET, [] (AsyncWebServerRequest * request) {
flag_led = true;
fauxmo.setState(ID_LED, flag_led, 254);
digitalWrite(LED_BUILTIN, !flag_led);
Serial.printf("[WEB] Device (%s) state: %s \n", ID_LED, "ON");
request->send(200, "text/html", SendHTML());
});
// on éteint la led et envoi la fonction SendHTML() à l'onglet /off de l'URL (IP:8080/on)
serveur.on("/off", HTTP_GET, [] (AsyncWebServerRequest * request) {
flag_led = false;
fauxmo.setState(ID_LED, flag_led, 254);
digitalWrite(LED_BUILTIN, !flag_led);
Serial.printf("[WEB] Device (%s) state: %s \n", ID_LED, "OFF");
request->send(200, "text/html", SendHTML());
});
// on envoie la fonction notFound si l'onglet n'existe pas
serveur.onNotFound(notFound);
// on démarre le serveur web
serveur.begin();
// on crée un serveur fauxmo
fauxmo.createServer(true);
// on paramètre le port
fauxmo.setPort(PORT_FAUXMO);
// on active le serveur
fauxmo.enable(true);
// on ajoute notre led comme appareil
fauxmo.addDevice(ID_LED);
// la fonction de callbak quand Alexa communique
fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) {
// on affiche la commande reçu
Serial.printf("[ALEXA] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value);
// si le nom de l'appareil correspond à mon appareil (ma led)
if (strcmp(device_name, ID_LED) == 0) {
// flag_led prend la valeur de l'état demandé
flag_led = state;
// on allume la led en fonction de la valeur de flag_led (état inverse pour la led interne: LOW allume, HIGH éteint)
digitalWrite(LED_BUILTIN, flag_led ? LOW : HIGH);
}
});
// on envoie l'info à Alexa que la led est éteinte ( valeur de 0 à 254, ici on laisse à 100% )
fauxmo.setState(ID_LED, flag_led, 254);
// on configure le port réseau pour l' OTA
ArduinoOTA.setPort(8266);
// on configure le nom du host pour l' OTA
ArduinoOTA.setHostname(HOST);
// on démarre le serveur OTA
ArduinoOTA.begin();
// on met une interruption sur le bouton de type descendante associé à la fonction handleInterrupt
attachInterrupt(digitalPinToInterrupt(BOUTON_PIN), handleInterrupt, FALLING);
}
/* le loop */
void loop() {
// on écoute le serveur fauxmo
fauxmo.handle();
// on écoute le serveur OTA
ArduinoOTA.handle();
// si le bouton a été activé
if (flag_bouton) {
// on change l'état de la led
flag_led = !flag_led;
// on applique ce changement
digitalWrite(LED_BUILTIN, !flag_led);
// on informe que le bouton a été activé et l'état de la led
Serial.printf("[BOUTON] interruption détécté --> %s\n", flag_led ? "LED ON" : "LED OFF");
// on envoie à Alexa le nouvel état de la led
fauxmo.setState(ID_LED, flag_led, 254);
// on désactive le flag
flag_bouton = false;
}
}