Pour faire suite à mon précédent article ,je vous propose de rendre l’interface Web du module , plus agréable, de la rendre « responsive » grâce à l’utilisation du framework Bootstrap. En prenant comme exemple la fabrication d’un thermomètre / hydromètre .
Dans cet article nous allons voir comment :
- Manipuler la bibliothèque DHT
- Utiliser les fonctions jquery , pour afficher les infos de mon module sur ma page web
- Mettre en place un serveur web JSON
- intégrez un framework comme Bootstrap , afin de dynamiser le tout et avoir une belle interface « responsive »
Pour cela il nous faut :
- un module WEMOS ou compatible ESP8266
- une sonde DHT 11 ou DHT 22 ( dans mon exemple j’utilise la sonde DHT 11 )
Branchement de la sonde DHT , au module WEMOS .
Plus d’info sur le branchement de ce composante et l’utilisation.
Pour info , on trouve souvent des modules dht , montés sur des circuits prêts à l’emploi avec résistance inclus ( ce qui facilite le montage ). C’est ce que j’utilise . Sur ce type de circuit , le brochage n’est pas dans le même ordre .
Voir photos ci dessous.
Sur le photo ci contre , j’ai indiqué l’ordre des 3 PIN restantes .
Face coté soudure , on du haut vers le bas :
- GND : A brancher sur une broche GND du module
- VCC : A brancher sur le 3,3 V du module
- Data : A brancher sur une entrée logique , sur mon Wemos D1 , je l’ai branché à la prise D2 , qui correspond en notation GPIO à la broche 16
Plus d’information sur les brochages du Wemos voir mon article suivant .
La Bibliothéque DHTesp :
Pour utiliser la bibliothèque DHTesp , il suffit d’ajouter les lignes suivantes :
// bibliotheque DHT pour module ESP
#include <DHTesp.h>
Puis on crée une instance DHT et on indique le numéro de PIN ou est relié la data
// init dht
DHTesp dht;
// PIN ou est connecté l’info data du dht
int dhtPin = 16; // GPIO16 egale a D2 sur WEMOS D1R1 ou D0 pour les autres ( averifier selon esp )
et enfin dans la boucle setup , on demarre la lecture du DHT.
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT11); // si vous avez un DHT22 , remplacé DHT11 par DHT22
Puis dans la fonction loop , je récupère les valeurs de température et d’humidité .
Dans un premier temps , je vais me contenter de lire les valeurs du DHT , et les afficher dans la console.
les differents valeurs récupérés sont les suivantes :
humidity = dht.getHumidity(); Récupére le pourcentage de l’humidité ( % )
temperature = dht.getTemperature(); la température en degrés celcius
heatIndex = dht.computeHeatIndex(temperature,humidity); L’index de chaleur , un peu comme la température ressentis , celui ci est basé sur l’humidité et la température ( en Europe , le vent est pris en charge aussi )
dewPoint = dht.computeDewPoint(temperature,humidity); Le point de rosée
cr = dht.getComfortRatio(cf,temperature,humidity); un indice de confort
per = dht.computePerception(temperature, humidity); un indice de perception humaine ( voir la doc pour plus de détails )
J’ai mis un délai de 10 secondes , pour récupérer les infos , il n’est pas utile de descendre plus bas , le module DHT auras du mal à suivre.
Ci dessous le script complet .
/*
* tuto thermometre partie 1
* Affichage des infos DHT dans console
*/
// bibliotheque temperature
#include <DHTesp.h>
unsigned long previousMillis=0 ;
unsigned long interval = 10000;
#define led 2
// init dht
DHTesp dht;
ComfortState cf;
// PIN ou est connecté l'info data du dht
int dhtPin = 16; // GPIO16 egale a D2 sur WEMOS D1R1 ou D0 pour les autres ( averifier selon esp )
float humidity ;
float temperature;
void setup() {
Serial.begin(115200);
Serial.println();
pinMode(led, OUTPUT);
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT11);
delay(1000);
humidity = dht.getHumidity();
temperature = dht.getTemperature();
}
void loop() {
// recup temp if( millis() - previousMillis >= interval) {
previousMillis = millis();
humidity = dht.getHumidity();
temperature = dht.getTemperature();
float heatIndex = dht.computeHeatIndex(temperature,humidity);
float dewPoint = dht.computeDewPoint(temperature,humidity);
float cr = dht.getComfortRatio(cf,temperature,humidity);
byte per = dht.computePerception(temperature, humidity);
String comfortStatus;
switch(cf) {
case Comfort_OK:
comfortStatus = "Comfort_OK";
break;
case Comfort_TooHot:
comfortStatus = "Comfort_TooHot";
break;
case Comfort_TooCold:
comfortStatus = "Comfort_TooCold";
break;
case Comfort_TooDry:
comfortStatus = "Comfort_TooDry";
break;
case Comfort_TooHumid:
comfortStatus = "Comfort_TooHumid";
break;
case Comfort_HotAndHumid:
comfortStatus = "Comfort_HotAndHumid";
break;
case Comfort_HotAndDry:
comfortStatus = "Comfort_HotAndDry";
break;
case Comfort_ColdAndHumid:
comfortStatus = "Comfort_ColdAndHumid";
break;
case Comfort_ColdAndDry:
comfortStatus = "Comfort_ColdAndDry";
break;
default:
comfortStatus = "Unknown:";
break;
}
Serial.println(" T:" + String(temperature) + "°C H:" + String(humidity) + "% I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus+" et per :"+ String(per));
}
}
Vous obtenez ceci :
La console , c’est pratique , pour « debugger » , mais un affichage déporté dans une interface WEB serait mieux
[adsense]Afficher l’info sur l’interface WEB :
afin que mon serveur Web , récupère l’info de la température , je crée un service web getInfo .
server.on(« /getInfo »,handleInfo); //Rpour récupérer info module
Qui envoie les requêtes sur la fonction handleInfo() . dans cette exemple , cette fonction est très simple , elle ne fait que renvoyer la valeur température .
void handleInfo() {
String Info=String(temperature);
server.send(200, « text/plane »,Info);
}
Il ne me reste plus qu’a modifier ma page web , afin de récupérer cette valeur .
Dans mon dossier data , je modifie mon fichier html ( de mon service WEB ) , je reprend le même fichier que dans l’article précédent , et j’ajoute les lignes suivantes :
Une balise HTML :
<div>Temperature : <span id= »Temp »></span> </div>
et un bout de code javascript ( jquery) ,afin d’aller renseigner l’info récupéré par l’appel à getInfo.
Ci dessous le code javascript :
function loadInfo(){
$( "#Temp" ).load( "/getInfo");
}
loadInfo(); // premiere execution
setInterval(function(){
loadInfo() // rappel toutes les 10 secondes
}, 10000);$( « #Temp » ).load( « /getInfo »); : permet de récupérer les données envoyés par la page /getInfo du module
La fonction setInterval , me permet de relancer cette fonction toutes les 10 secondes , afin d’actualiser la valeur de la température.
Ci dessous le script complet de la page HTML.
<!DOCTYPE html>
<html>
<head>
<script src="jquery.min.js"></script>
</head>
<body>
<center>
<h1>Tuto SPIFFS + jquery - Byfeel</h1>
<p>Demo jquery , pour on/off led interne</p>
<div>Temperature : <span id="Temp"></span> </div>
<form action='/setLED' method='POST' id='FormLED'>
<fieldset>
<legend>LED interne 2 :</legend>
<INPUT type='radio' name='LED' value='on' id='on' checked><label for='on'>ON</label>
<INPUT type='radio' name='LED' value='off' id='off'><label for='off'>OFF</label>
</fieldset>
<INPUT type='submit' value='Envoyer' id='bouton_LED'/>
</form>
<a href="https://byfeel.info">byfeel.info</a><br>
<div id="info"></div>
<script>
$("#FormLED").submit(function(){
$.ajax({
url: '/setLED',
type: 'post',
data: $("#FormLED").serialize(),
success: function(data) {
$("#info").html("<p> Commende LED : "+data+"</p>");
}
});
return false;
});
function loadInfo(){
$( "#Temp" ).load( "/getInfo");
}
loadInfo(); // premiere execution
setInterval(function(){
loadInfo() // rappel toutes les 10 secondes
}, 10000);
</script>
</body>
</html>fichier à coller dans le dossier data de votre script arduino . Ainsi que le fichier jquery.min.js
Voila a quoi ressemble votre structure :
Il faut copier l’intégralité du dossier data , dans votre wemos , par le biais de la fonction « ESP8266 sketch data upload » de votre interface Arduino ( voir article SPIFFS ). Puis uploader par la suite votre sketch , par la méthode traditionnel.
Dans le script , j’ai conservé la mise en place du serveur FTP , afin de faciliter les test avec le fichier html , et ainsi recharger uniquement le fichier index.html ( plus rapide ) , que de passer par la fonction inclus dans l’interface arduino.
Script complet : ( pensez à renseigner vos identifiants WIFI )
/*
* webserver dynamique - temperature
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h> //Include SPIFFS
// bibliotheque temperature
#include <DHTesp.h>
// FTPserver
#include "ESP8266FtpServer.h"
unsigned long previousMillis=0 ;
unsigned long interval = 10000;
//WiFi Connection configuration
const char *ssid = "nomduwifi";
const char *password = "mdp wifi";
#define led 2
// init dht
DHTesp dht;
ComfortState cf;
// PIN ou est connecté l'info data du dht
int dhtPin = 16; // GPIO16 egale a D2 sur WEMOS D1R1 ou D0 pour les autres ( averifier selon esp )
float humidity ;
float temperature;
// on crée l'instance
FtpServer ftpSrv;
//***********************************
//************* Gestion du serveur WEB
//***********************************
ESP8266WebServer server(80);
void handleRoot(){
server.sendHeader("Location", "/index.html",true); //Redirige vers page index.html sur SPIFFS
server.send(302, "text/plane","");
}
// fonction de traitement SETLED
void handleLED(){
String SetLED = server.arg("LED");
Serial.println(SetLED);
if (SetLED=="on") digitalWrite(led, LOW);
else digitalWrite(led, HIGH);
server.send(200, "text/plane",SetLED);
}
// fonction de traitement SETLED
void handleInfo() {
String Info=String(temperature);
server.send(200, "text/plane",Info);
}
void handleWebRequests(){
if(loadFromSpiffs(server.uri())) return;
String message = "File Not Detected\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
Serial.println(message);
}
//********** fin serveur web
void setup() {
Serial.begin(115200);
Serial.println();
// Conexion WIFI
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
//demarrage file system
if (SPIFFS.begin()) {
Serial.println("Demarrage file System");
ftpSrv.begin("esp8266","pass"); // demarrage serveur ftp avec user = esp8266 et mdp = password
}
else Serial.println("Erreur file System");
//Si connexion affichage info dans console
Serial.println("");
Serial.print("Connection ok sur le reseau : ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//Initialize Webserver
server.on("/",handleRoot);
server.on("/setLED",handleLED); //Rpour gerer led
server.on("/getInfo",handleInfo); //Rpour récupérer info module
server.onNotFound(handleWebRequests); //Set setver all paths
server.begin();
pinMode(led, OUTPUT);
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT11);
delay(1000);
humidity = dht.getHumidity();
temperature = dht.getTemperature();
}
void loop() {
//service web
server.handleClient();
ftpSrv.handleFTP();
// recup temp
if( millis() - previousMillis >= interval) {
previousMillis = millis();
humidity = dht.getHumidity();
temperature = dht.getTemperature();
float heatIndex = dht.computeHeatIndex(temperature,humidity);
float dewPoint = dht.computeDewPoint(temperature,humidity);
float cr = dht.getComfortRatio(cf,temperature,humidity);
byte per = dht.computePerception(temperature, humidity);
String comfortStatus;
switch(cf) {
case Comfort_OK:
comfortStatus = "Comfort_OK";
break;
case Comfort_TooHot:
comfortStatus = "Comfort_TooHot";
break;
case Comfort_TooCold:
comfortStatus = "Comfort_TooCold";
break;
case Comfort_TooDry:
comfortStatus = "Comfort_TooDry";
break;
case Comfort_TooHumid:
comfortStatus = "Comfort_TooHumid";
break;
case Comfort_HotAndHumid:
comfortStatus = "Comfort_HotAndHumid";
break;
case Comfort_HotAndDry:
comfortStatus = "Comfort_HotAndDry";
break;
case Comfort_ColdAndHumid:
comfortStatus = "Comfort_ColdAndHumid";
break;
case Comfort_ColdAndDry:
comfortStatus = "Comfort_ColdAndDry";
break;
default:
comfortStatus = "Unknown:";
break;
}
Serial.println(" T:" + String(temperature) + "°C H:" + String(humidity) + "% I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus+" et per :"+ String(per));
}
}
// gestion du not found.
bool loadFromSpiffs(String path){
String dataType = "text/plain";
if(path.endsWith("/")) path += "index.htm";
if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
else if(path.endsWith(".html")) dataType = "text/html";
else if(path.endsWith(".htm")) dataType = "text/html";
else if(path.endsWith(".css")) dataType = "text/css";
else if(path.endsWith(".js")) dataType = "application/javascript";
else if(path.endsWith(".png")) dataType = "image/png";
else if(path.endsWith(".gif")) dataType = "image/gif";
else if(path.endsWith(".jpg")) dataType = "image/jpeg";
else if(path.endsWith(".ico")) dataType = "image/x-icon";
else if(path.endsWith(".xml")) dataType = "text/xml";
else if(path.endsWith(".pdf")) dataType = "application/pdf";
else if(path.endsWith(".zip")) dataType = "application/zip";
File dataFile = SPIFFS.open(path.c_str(), "r");
if (server.hasArg("download")) dataType = "application/octet-stream";
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
}
dataFile.close();
return true;
}
Ce qui donne :

Pour récupérer une donnée , c’est bien , mais si je désire récupérer plusieurs données , cela devient vite un peu plus compliquer . Heuresement jquery , permet de récupérer facilement des données graces aux format JSON.
Parlons de JSON
JSON (que l’on peut prononcer à l’anglaise comme le prénom Jason ( par exemple jason bourne ) signifie JavaScript Object Notation . C’est une façon d’écrire les informations dans un fichier qui soit facilement compréhensible pour le Javascript.A quoi ça ressemble ?
Voici un exemple de syntaxe JSON :
{
"cle":"valeur",
"Temperatue" : "25"
}Je pourrais créer le fichier par une simple chaine de caractére , mais je cherche une solution simple pour écrire le fichier , afin d’envoyer plus d’info.
Pour cela , je vais utiliser la bibliotheque JSON . ( récuperer la bibliotheque sur le site Github , en version 5.13.2 au moment ou j’écris cet article ).
Sur la doc officiel de la librairie JSON , il y a un avertissement qui indique que l’interface Arduino à tendance a vouloir installer la version 6 , mais cette dernière étant en beta , il est recommandé de rester sur une version 5.

Une fois récupéré , copier le dossier arduino.json-master , dans votre dossier librairies .
Comment utiliser cette bibliothèque :
#include <ArduinoJson.h>
//json – création de l’instance JSONInfo
StaticJsonBuffer<200> jsonBuffer;
JsonObject& JSONInfo = jsonBuffer.createObject();
Puis pour ajouter des données , il suffit d’utiliser l’instance créé , en indiquant la clé puis la valeur . Par exemple dans ce script , j’enregistre 3 infos ( la température avec la clé T , l’humidité avec la clé H et l’info confortstatus avec la clé confort.
JSONInfo[« T »] = temperature;
JSONInfo[« H »] = humidity;
JSONInfo[« Confort »] = comfortStatus;
Puis pour finaliser ma chaine JSON , j’utilise la fonction printTO(nom-de-la-sortie) .
JSONInfo.printTo(Info);
Il ne me reste plus qu’a envoyer le tout
server.send(200, « application/json »,Info); }
Ci dessous le script final , à téléverser dans votre module Wemos.
/*
* webserver dynamique - temperature
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h> //Include SPIFFS
// bibliotheque temperature
#include <DHTesp.h>
#include <ArduinoJson.h>
// FTPserver
#include "ESP8266FtpServer.h"
unsigned long previousMillis=0 ;
unsigned long interval = 10000;
//WiFi Connection configuration
const char *ssid = "mon wifi";
const char *password = "mon mot de passe";
#define led 2
// init dht
DHTesp dht;
ComfortState cf;
// PIN ou est connecté l'info data du dht
int dhtPin = 16; // GPIO16 egale a D2 sur WEMOS D1R1 ou D0 pour les autres ( averifier selon esp )
float humidity ;
float temperature;
float heatIndex;
float dewPoint;
byte per;
String comfortStatus;
// on crée l'instance
FtpServer ftpSrv;
//json
StaticJsonBuffer<200> jsonBuffer;
JsonObject& JSONInfo = jsonBuffer.createObject();
//***********************************
//************* Gestion du serveur WEB
//***********************************
ESP8266WebServer server(80);
void handleRoot(){
server.sendHeader("Location", "/index.html",true); //Redirige vers page index.html sur SPIFFS
server.send(302, "text/plane","");
}
// fonction de traitement SETLED
void handleLED(){
String SetLED = server.arg("LED");
Serial.println(SetLED);
if (SetLED=="on") digitalWrite(led, LOW);
else digitalWrite(led, HIGH);
server.send(200, "text/plane",SetLED);
}
// fonction de traitement getInfo
void handleInfo() {
String Info;
JSONInfo["T"] = temperature;
JSONInfo["H"] = humidity;
JSONInfo["Confort"] = comfortStatus;
JSONInfo.printTo(Info);
server.send(200, "application/json",Info);
}
void handleWebRequests(){
if(loadFromSpiffs(server.uri())) return;
String message = "File Not Detected\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
Serial.println(message);
}
//********** fin serveur web
void setup() {
Serial.begin(115200);
Serial.println();
// Conexion WIFI
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
//demarrage file system
if (SPIFFS.begin()) {
Serial.println("Demarrage file System");
ftpSrv.begin("esp8266","pass"); // demarrage serveur ftp avec user = esp8266 et mdp = password
}
else Serial.println("Erreur file System");
//Si connexion affichage info dans console
Serial.println("");
Serial.print("Connection ok sur le reseau : ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//Initialize Webserver
server.on("/",handleRoot);
server.on("/setLED",handleLED); //Rpour gerer led
server.on("/getInfo",handleInfo); //Rpour récupérer info module
server.onNotFound(handleWebRequests); //Set setver all paths
server.begin();
pinMode(led, OUTPUT);
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT11);
delay(1000);
humidity = dht.getHumidity();
temperature = dht.getTemperature();
JSONInfo["T"] = temperature;
JSONInfo["H"] = humidity;
}
void loop() {
//service web
server.handleClient();
ftpSrv.handleFTP();
// recup temp
if( millis() - previousMillis >= interval) {
previousMillis = millis();
humidity = dht.getHumidity();
temperature = dht.getTemperature();
heatIndex = dht.computeHeatIndex(temperature,humidity);
dewPoint = dht.computeDewPoint(temperature,humidity);
float cr = dht.getComfortRatio(cf,temperature,humidity);
per = dht.computePerception(temperature, humidity);
switch(cf) {
case Comfort_OK:
comfortStatus = "OK";
break;
case Comfort_TooHot:
comfortStatus = "Trop Chaud";
break;
case Comfort_TooCold:
comfortStatus = "Trop froid";
break;
case Comfort_TooDry:
comfortStatus = "Trop Sec";
break;
case Comfort_TooHumid:
comfortStatus = "Trop humide";
break;
case Comfort_HotAndHumid:
comfortStatus = "Chaud et Humide";
break;
case Comfort_HotAndDry:
comfortStatus = "Chaud et Sec";
break;
case Comfort_ColdAndHumid:
comfortStatus = "Froid et humide";
break;
case Comfort_ColdAndDry:
comfortStatus = "Froid et Sec";
break;
default:
comfortStatus = "Unknown:";
break;
}
Serial.println(" T:" + String(temperature) + "°C H:" + String(humidity) + "% I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus+" et per :"+ String(per));
}
}
// gestion du not found.
bool loadFromSpiffs(String path){
String dataType = "text/plain";
if(path.endsWith("/")) path += "index.htm";
if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
else if(path.endsWith(".html")) dataType = "text/html";
else if(path.endsWith(".htm")) dataType = "text/html";
else if(path.endsWith(".css")) dataType = "text/css";
else if(path.endsWith(".js")) dataType = "application/javascript";
else if(path.endsWith(".png")) dataType = "image/png";
else if(path.endsWith(".gif")) dataType = "image/gif";
else if(path.endsWith(".jpg")) dataType = "image/jpeg";
else if(path.endsWith(".ico")) dataType = "image/x-icon";
else if(path.endsWith(".xml")) dataType = "text/xml";
else if(path.endsWith(".pdf")) dataType = "application/pdf";
else if(path.endsWith(".zip")) dataType = "application/zip";
File dataFile = SPIFFS.open(path.c_str(), "r");
if (server.hasArg("download")) dataType = "application/octet-stream";
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
}
dataFile.close();
return true;
}
Si vous executez sur une page web , la requete suivante :
http://adresseIP-du_module/getInfo , vous obtiendrez l’info suivante :
{"T":28,"H":43,"Confort":"OK"}La chaine JSON , à bien été construite.
Afin de l’exploitez , il va falloir modifier le script jquery de votre page index html.
Pour tester tout de suite , il suffit de remplacer la ligne : $( « #Temp » ).load( « /getInfo »); par la fonction $.getJSON qui permet de lire un fichier JSON.
Ce qui donne :
$.getJSON(‘/getInfo’, function(jthermo) {
$(‘#Temp’).text(jthermo.T); // permet de récupérer la clé T qui correspond à la température
});
Je vous laisse modifier le fichier , afin d’afficher les autres infos.
Améliorer le rendu HTML
Afin de donner une touche plus moderne , a notre page WEB , je vais expliquer comment activer bootstrap sur le module.
Bootstrap est un framework WEB , qui permet de construire rapidement des sites web dynamique et full responsive.
Pour cela , il suffit de téléchargé , vous allez récupérer les dossiers et fichiers suivants :
Il y a deux fichiers à récuperer et à coller dans votre dossier data :
bootstrap.min.css et bootstrap.min.js
Uploader le tout avec la commande arduino ide : ESP8266 sketch data upload . Par la suite pour la modification de votre fichier HTML , je vous conseille de passer par le serveur FTP. Ça sera plus rapide.
Comment integrez bootstrap ,dans votre fichier html
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Demo ESP8266 dynamique</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<link rel="stylesheet" href="bootstrap.min.css" media="screen">
</head>Retrouvez les script sur mon github.








2 commentaires sur “WEMOS ( EP8266 ) et serveur Web Dynamique”
Encore un bel article bien détaillé 🙂
Merci 🙂