PrécédentQuestionnaire9 / 10Suivant5 Appendix
4. Les serveurs Web

Langage HTML

L'objectif de ce chapitre est de créer un serveur Web pour contrôler la led interne de l'ESP12, une carte basée sur les ESP8266 (Broche D4)

La led interne de l'ESP
La led interne de l'ESP

La section suivante présente le langage HTML qui va être utilisé pour la suite.

Langage HTML

Le HTML est un langage contenant des balises, c'est à dire des marqueurs spécifiques pour organiser la page Web.

Il existe deux types principaux de balises:

Une balise commence par un chevron ouvrant et se termine par un chevron fermant. Toutes les balises fermantes (pour les balises en paire) sont de la forme $$

Toute page HTML commencer par la balise htmlhtml

💡

Pour mettre du code en commentaire, c'est à dire ne pas le visualiser dans la page Web de rendu, il faut mettre le code entre $$

Première balise HTML

La forme de la page

La page Web est scindée en 2 entités:

Page minimaliste HTML

L'en-tête

L'en-tête va contenir les informations et les paramètres de la page, notamment :

L'en-tête Titre de la page

Le corps

Le corps va contenir l'ensemble des informations affichées sur la page

Ajout des titres

Un titre en HTML est vue avec un niveau hiérarchique. Un titre de page est au niveau 1, un sous-titre avec un niveau 2, etc...

Pour mettre un titre, il faut donc écrire CMT$

Titre

$, un sous-titre c'est
CMT$

Sous-titre

$

Ajout des images

Pour ajouter une image, il faut connaître son emplacement dans le système (ordinateur) ou bien sur Internet (url).

Il s'agit de la balise orpheline CMT$$

Ajout d'une image Impossible de charger l'image

Impossible de charger l'image

Ajout des liens

Pour ajouter une image, il faut connaître son emplacement dans le système (ordinateur) ou bien sur Internet (url).

Il s'agit de la balise orpheline CMT$$

Ajout d'un lien Texte du lien Les liens permettent de pointer sur d'autres pages, que ce soit sur le serveur courant ou bien un autre.

Présentation des modules ESP12

Une carte ESP12 NodeMCU
Une carte ESP12 NodeMCU

Les cartes ESP12 sont des microcontrôleurs basés sur la puce ESP8266 qui permet de se connecter en Wifi à des réseaux ou bien de créer son propre réseau. Une des sous-famille est la NodeMCU.

Cette carte possède un certains nombre de broches dites GPIO, qui, comme les cartes Arduino, sont utilisées pour interagir avec des capteurs et des actionneurs.

Voici la disposition des broches sur les ESP12.

Les broches de l'ESP12
Les broches de l'ESP12

Les broches GPIO de l'ESP12 sont en 3.3V, contrairement aux cartes Arduino qui sont en 5V. Il existe néanmoins une broche (VIN) pour alimenter des périphériques en 5V

Architecture du mini-projet

Pour communiquer entre le client (utilisateur) et l'ESP12, nous utiliserons un routeur qui servira de passerelle.

Architecture du projet
Architecture du projet

L'ESP12 se connecte dans un premier temps au routeur. Une fois connecté, tout client sur le même réseau peut se connecter à l'ESP12 en saisissant l'adresse de l'ESP12 dans le navigateur.

Base des requêtes

Dès que nous allons sur une page Web, nous faisons une requête, c'est à dire que l'on va demander l'affichage d'une page Web à un serveur distant.

Architecture client-serveur
Architecture client-serveur

Afin de récupérer une page sur le serveur, nous avons besoin de connaître 3 éléments :

Une petite explication sur les ports

Pour recevoir et transmettre des données à d’autres ordinateurs, un ordinateur (ou serveur) a besoin de ports. Cependant, les ports physiques tel que le port Ethernet communiquent avec beaucoup de services.

Ainsi, des ports virtuels ont été créés.

Chaque port virtuel est codé sur 16 bits et permet de faire communiquer un service ou un logiciel. [1]. Il y a donc potentiellement 65536 ports disponibles. Certains numéros de port sont réservés à certains services
Les ports de 0 à 1023 sont déjà réservés à des services particuliers et le port par défaut pour les serveurs Web est le 80.

Les types de requêtes

Lorsque nous nous connectons à un serveur Web, nous faisons principalement deux types de requêtes [2]

Connexion au routeur

La carte ESP12 a besoin du nom du routeur ainsi que de son mot de passe. Dans le programme FILEserveur\_Web\_simple.ino, il faut préciser le nom et le mot de passe sur les lignes suivantes :

C++

Identifiant et mot de passe

//Par exemple
const char* ssid     = "Creafab_invite";
const char* password = "MonTraficEstJournalise";
//Il faut mettre le nom du routeur chez soi et le mot de passe associé

Lancement du programme

Pour sélectionner la carte ESP12, veuillez vous reporter à l'annexe UTILISATION DE L’ESP12 SOUS ARDUINO.

⚠️

Il faudra activer la liaison série de la carte. Pour cela, lors du choix de la carte dans le logiciel Arduino, dans la section Outils - Types de cartes - ESP12 NodeMCU, il faut bien vérifier que la case Serial est activée

Une fois le programme téléversé, il vous faudra récupérer l'adresse IP de l'ESP12.

Pour cela, une fois que le code est téléversé, veuillez ouvrir la fenêtre du moniteur série, l’adresse IP de l'ESP va apparaître au bout de quelques secondes.

Affichage de l'adresse IP
Affichage de l'adresse IP

Si aucune données n’apparaît, faite un reset de la carte ESP12 en appuyant sur la touche RSTRST de la carte.

Il ne vous reste plus qu'à rentrer l’adresse IP obtenue dans un navigateur internet.
En l’occurrence, l'adresse IP dans ce cas là est IP192.168.0.102

Connexion au serveur
Connexion au serveur

Le résultat doit être le suivant

Résultat
Résultat

Explication du programme

Une explication du langage HTML est disponible en annexe (section HTML)

En tête du code

Après avoir importé les bibliothèques liées à l'ESP12, nous définissons un objet ESP8266WebServer qui attend comme argument le port du serveur, c'est à dire le 80.

C++

Importation des bibliothèques

#include 
#include 
#include 
        
#define PORT 80 //Port par défaut
#define LED D4  //Broche de la LED
        
ESP8266WebServer server(PORT);

On précise ensuite le mot de passe et le nom du routeur de communication.

C++

Identifiant et mot de passe du routeur

const char* ssid     = "Nom-reseau-Internet";
const char* password = "Mot-de-passe-Routeur";

Ensuite, nous allons définir et créer notre page HTML.

Deux versions de pages Web seront proposées:

Fonction setup

Lançons nous dans le code de la fonction setup

On définit la led en sortie et on se connecte au routeur.

C++

Initialisation

void setup() {
      
    pinMode(LED, OUTPUT);   //LED en sortie
    digitalWrite(LED, LOW); //LED éteinte
    Serial.begin(115200);   //Communication à 115200 bits/s
    WiFi.begin(ssid, password); //Connexion
    Serial.println("");         //Retour à la ligne

Puis on vérifie que nous sommes bien connecté et on affiche les informations de connexion.

C++

Vérification de la connexion

while (WiFi.status() != WL_CONNECTED) 
    
        delay(500);
        Serial.println(">>> Impossible de se connecter au réseau...");
    //Fin while
      
    Serial.print(">>> Connexion au réseau ");
    Serial.println(ssid);
    Serial.print("avec l'adresse IP : ");
    Serial.println(WiFi.localIP());

Enfin on vérifie que le MDSN [3] est activé (optionnel)

C++

Vérification de la connexion

if (MDNS.begin("esp8266")) 
       //Multicast DNS 
        Serial.println(">>> Serveur MDNS activé");
    

On définit (toujours dans le setup) les pages accessibles par le client ainsi que la fonction appelée lors de la requête. Il s'agit de l'emplacement '/' et sa fonction associées est la fonction mainPage

C++

Redirection sur la page principale

server.on("/", mainPage);           //Affichage de la page principale si requête sur '/' -> saisir IP dans le navigateur
On redirige également l'utilisateur sur une page dédiée si l'adresse demandée n'existe pas.
C++

Redirection en cas d'erreur

server.onNotFound(notFoundPage);    //Affichage de la page d'erreur si adresse non valide

Enfin, on initialise le serveur.

C++

Initialisation du serveur

server.begin();                     //Initialisation du serveur
    Serial.println(">>> démarrage du serveur");

Fonction loop

Le code à l'intérieur de la fonction loop se contente de gérer de manière transparente le comportement du serveur.

C++

Fonction principale

void loop() 

    server.handleClient(); //Gestion des clients sur le serveur
//Fin loop

Fonction mainPage

Le code à l'intérieur de la fonction mainPage permet de gérer la LED en fonction des valeurs passées via l'URL.

C++

Fonction mainPage

void mainPage() //Page principale
{

if(server.arg("LED")=="ON") //Lecture de l'argument 'LED' digitalWrite(LED, LOW); //On allume la led //Fin if else if(server.arg("LED")=="OFF") digitalWrite(LED, HIGH); //On eteint la led //Fin else if else //nothing

server.send(200, "text/html", fullPageContent); //On envoie la page principale }//Fin mainPage

Tout appui sur un bouton va exécuter cette fonction.
La fonction server.send() permet d'envoyer la page au client lorsque celui-ci la demande. La valeur 200 correspond au code d'erreur de la page : 200 veut dire qu'il n'y a pas eu d'erreur  [4].

Code complet

💡

Le code complet est disponible en faisant un clic-droit puis Copy link Adress sur le lien suivant :

C++

Code complet

#include 
#include 
#include 
    
#define PORT 80 //Port par défaut
#define LED D4  //Broche de la LED
    
ESP8266WebServer server(PORT);
    
const char* ssid     = "Nom-reseau-Internet";
const char* password = "Mot-de-passe-Routeur";
    
//Page principale
const String minimalPageContent = "\
\
    Serveur Web CREPP\
     \
    \
    \
    

Led ESP8266


\

Contrôle de la LED sur la broche D4


\ \ \ \ "; const String fullPageContent = "\ \ Serveur Web CREPP\ \ \ \ Led ESP8266
\

Contrôle de la LED sur la broche D4


\ \ \ \ "; void setup() { pinMode(LED, OUTPUT); //LED en sortie digitalWrite(LED, LOW); //LED éteinte Serial.begin(115200); //Communication à 115200 bits/s WiFi.begin(ssid, password); //Connexion Serial.println(""); //Retour à la ligne while (WiFi.status() != WL_CONNECTED) delay(500); Serial.println(">>> Impossible de se connecter au réseau..."); Serial.print(">>> Connexion au réseau "); Serial.println(ssid); Serial.print("avec l'adresse IP : "); Serial.println(WiFi.localIP()); if (MDNS.begin("esp8266")) //Multicast DNS Serial.println(">>> Serveur MDNS activé"); server.on("/", mainPage); //Affichage de la page principale si requête sur '/' -> saisir IP dans le navigateur server.onNotFound(notFoundPage); //Affichage de la page d'erreur si adresse non valide server.begin(); //Initialisation du serveur Serial.println(">>> démarrage du serveur"); }//Fin setup void loop() server.handleClient(); //Gestion des clients sur le serveur //Fin loop void mainPage() //Page principale { if(server.arg("LED")=="ON") //Lecture de l'argument 'LED' digitalWrite(LED, LOW); //On allume la led //Fin if else if(server.arg("LED")=="OFF") digitalWrite(LED, HIGH); //On eteint la led //Fin else if else //nothing server.send(200, "text/html", fullPageContent); //On envoie la page principale }//FIn mainPage void notFoundPage() //Gestion si mauvaise URL server.send(404, "text/plain", "Page introuvable !"); //Fin notFoundPage

Notes

  1. Par exemple, le service SSH communique sur le port 22

  2. Les webSockets ne seront pas abordées

  3. Multicast DNS, un serveur de résolution de nom de domaine

  4. L'erreur 404 indique une page inexistante.