Accueil > NodeMCU > Créer des pages WEB dynamiques avec AJAX

Créer des pages WEB dynamiques avec AJAX

Le but de cet article est d’expliqué l’utilisation d’AJAX (Asynchrone Javascript and XML) qui va permettre de créer des pages dynamiques sans avoir besoin de recharger la page complètetement à chaque mise à jour.

AJAX va permettre de transférer des données au format XML (eXtensible Markup Language de Microsoft) ou JSON (JavaScript Object Notation) entre votre programme tournant sur votre contrôleur préféré à base d’ESP8266 (NodeMCU Lolin ou Wemos D1 mini par exemple) et le client qui accède à votre page WEB.

L’exemple mis en oeuvre va consister à affcher une page WEB avec 2 boutons ON et OFF.
Le contenu du programme est le suivant :

/*
 * Exemple d’utilisation sans AJAX
 */
// Ajout librairie gestion WIFI
#include <ESP8266WiFi.h>
// Ajout librairie Web Server
#include <ESP8266WebServer.h>
// Création d’une instance serveur
ESP8266WebServer server(80); // port d’écoute 80
String ssid = « votre_ssid »;  // SSID
String password = « votre_mot_de_passe »;  // mot de passe pour la connexion au point d’accès
// Page HTML
const char SITE_index[] PROGMEM = R »=====(
<!DOCTYPE HTML>
<meta name= »viewport » content= »width=device-width, initial-scale=1″ />
<meta http-equiv= »Content-Type » content= »text/html; charset=utf-8″ />
<title>Test</title>
<form action= »/bouton » method= »POST »>
  <input type= »submit » name= »bouton_on » value= »On »>
  &nbsp&nbsp
  <input type= »submit » name= »bouton_off » value= »Off »>
</form>
</HTML>
)===== »;
void setup()
{
  Serial.begin(115200);
  WiFi.mode(WIFI_STA); // configure le WIFI en mode station
  WiFi.disconnect();  // on se déconnecte si on été déjà connecté à un point d’accès WiFi
  WiFi.begin(ssid.c_str(), password.c_str()); // connexion au point d’accès WiFi
  while (WiFi.waitForConnectResult() != WL_CONNECTED) // on attend la connexion
  {
    Serial.println(« Erreur de connexion »);
  }
  // affectation des actions à effectuer
  server.on(« / », page_html); // page par défaut
  server.on(« /bouton », traite_bouton); // on traite l’action si click sur bouton on ou off
  server.begin(); // démarre le serveur WEB
}
void page_html()
{
  server.send_P(200, « text/html », SITE_index); // envoie la page principale
}
void traite_bouton()
{
  server.send_P(200, « text/html », SITE_index); // envoie la page principale
  if (server.hasArg(« bouton_on »)) { Serial.println(« Appuie sur le bouton ON »); }
  if (server.hasArg(« bouton_off »)) { Serial.println(« Appuie sur le bouton OFF »); }
}
void loop()
{
  server.handleClient(); // une requête HTTP ?
}
Donc à partir du navigateur internet on tape l’adresse IP du module et si on appuie sur chacun des 2 boutons, un état s’affiche sur le moniteur série.
Voyons les étapes essentielles du programme :
– La page HTML est stockée dans la mémoire Flash de l’ESP8266 via l’utilisation de PROGMEM; la mémoire Flash du modèle ESP8266 ESP12E est de 4 Mo pour le stockage des programmes et des données. Attention à bien respecter la syntaxe PROGMEM = R »=====( code HTML )===== »; cela permet de mettre le code HTML sans indiquer de retour à la ligne.
server.on(« / », page_html) : on affecte pour la page racine / la fonction page_html
  server.on(« /bouton », traite_bouton) : on affecte pour la page /bouton la fonction traite_bouton
– server.send_P(200, « text/html », SITE_index) : on envoi au client la page. Attention avec l’utilisation de PROGMEM il faut utilliser la commande server.send_P et non server.send.
– server.handleClient() : le serveur Web est à l’écoute d’une requête http.
et enfin les étapes pour le code HTML :
<form action= »/bouton » method= »POST »> : s’il y a un click sur un bouton, j’envoie une requête http /bouton.
<input type= »submit » name= »bouton_on » value= »On »> : on définit une entrée de type submit (cela revient à afficher un bouton avec un texte dedans contenue par « value« ) et on lui affecte un nom qui sera traité par le programme.
C’est très bien cela mais comment savoir sur ma page, si j’ai appuyé sur le bouton On ou Off sans utiliser le moniteur série !!!!
Et bien grâce à Ajax cela va être possible en mettant en oeuvre l’utilisation de Javascript et XML pour la communication.
Dans l’exemple d’utilisation AJAX, nous allons griser le bouton quand il est sélectionné et afficher un état.
Voilà le programme qui va rendre votre page dynamique en fonction des actions :
/*
 * Exemple d’utilisation avec AJAX
 */
// Ajout librairie gestion WIFI
#include <ESP8266WiFi.h>
// Ajout librairie Web Server
#include <ESP8266WebServer.h>
// Création d’une instance serveur
ESP8266WebServer server(80); // port d’écoute 80
String ssid = « votre ssid »; // SSID
String password = « votre mot de passe »;  // mot de passe pour la connexion au point d’accès
String XML; // variable qui permet les échanges en XML
String bouton_status = «  »; // gestion des boutons pour les activer ou désactiver
// Page HTML
const char SITE_index[] PROGMEM = R »=====(
<!DOCTYPE HTML>
<meta name= »viewport » content= »width=device-width, initial-scale=1″ />
<meta http-equiv= »Content-Type » content= »text/html; charset=utf-8″ />
<title>Test</title>
xmlHttp=createXmlHttpObject();
function createXmlHttpObject()
{
  if(window.XMLHttpRequest) { xmlHttp=new XMLHttpRequest(); }
  else { xmlHttp=new ActiveXObject(‘Microsoft.XMLHTTP’); }
  return xmlHttp;
}
function process()
{
  if(xmlHttp.readyState==0||xmlHttp.readyState==4)
  {
    xmlHttp.onreadystatechange=function()
    {
      if(xmlHttp.readyState==4&&xmlHttp.status==200)
      {
        xmlDoc=xmlHttp.responseXML;
        xmlmsg=xmlDoc.getElementsByTagName(’bouton_status’)[0].firstChild.nodeValue;
        document.getElementById(’bouton’).innerHTML=xmlmsg;
        if (xmlmsg== « on »)
        {
          document.getElementById(’bouton_on’).disabled=true;
          document.getElementById(’bouton_off’).disabled=false;
        }
        if (xmlmsg== « off »)
        {
          document.getElementById(’bouton_on’).disabled=false;
          document.getElementById(’bouton_off’).disabled=true;
        }
      }
    }
    xmlHttp.open(‘PUT’,’traite_xml’,true);
    xmlHttp.send(null);
  }
}
<BODY onload= »process() »>
<form action= »/ » method= »POST »>
  <input type= »submit » name= »bouton_on » id= »bouton_on » value= »On »>
  &nbsp&nbsp
  <input type= »submit » name= »bouton_off » id= »bouton_off » value= »Off »>
</form>
</br>
Appuie sur le bouton <A id= »bouton »> </A>
</BODY>
</HTML>
)===== »;
void setup()
{
  Serial.begin(115200);
  WiFi.mode(WIFI_STA); // configure le WIFI en mode station
  WiFi.disconnect();  // on se déconnecte si on été déjà connecté à un point d’accès WiFi
  WiFi.begin(ssid.c_str(), password.c_str()); // connexion au point d’accès WiFi
  while (WiFi.waitForConnectResult() != WL_CONNECTED) // on attend la connexion
  {
    Serial.println(« Erreur de connexion »);
  }
  // affectation des actions à effectuer
  server.on(« / », page_html); // page par défaut
  server.on(« /traite_xml », traite_xml); // on traite le msg XML reçu
  server.begin(); // démarre le serveur WEB
}
void page_html()
{
  server.send_P(200, « text/html », SITE_index); // envoie la page principale
  if (server.hasArg(« bouton_on »)) { bouton_status = « on »; }
  if (server.hasArg(« bouton_off »)) { bouton_status = « off »; }
  buildXML();
  server.send(200, « text/xml », XML); // envoie le XML
}
void buildXML()
{
  XML = « <?xml version=’1.0′?> »;
  XML += « <xml> »;
  XML += « <bouton_status> »;
  XML += String(bouton_status);
  XML += « </bouton_status> »;
  XML += « </xml> »;
}
void traite_xml()
{
  buildXML(); // construit le XML
  server.send(200, « text/xml », XML); // envoie le XML
}
void loop()
{
  server.handleClient(); // une requête HTTP ?
}
Donc à partir du navigateur internet on tape l’adresse IP du module et si on appuie sur chacun des 2 boutons, chaque bouton passe en grisé et un état s’affiche sur la page Web :
Voici les étapes essentielles du programme et on commence par le code HTML :
– On a ajouté deux balises et qui indique qu’il y a du Javascript entre ces 2 balises.
– On commence par instancier une nouvelle requête XML :
xmlHttp=createXmlHttpObject();
function createXmlHttpObject()
{
if (window.XMLHttpRequest) { xmlHttp=new XMLHttpRequest(); }
else { xmlHttp=new ActiveXObject(‘Microsoft.XMLHTTP’); }
return xmlHttp;

}

– Ensuite on crée la fonction de nom process qui va traiter les informations XML reçus. Pour comprendre le reste du programme nous enverrons au format XML le contenu suivant :
<?xml version=’1.0′?><xml><bouton_status>on ou off</bouton_status></xml>
if (xmlHttp.readyState==0||xmlHttp.readyState==4) : on teste que la requête a été créée (0) ou que les données ont été bien réceptionnées (4).
xmlHttp.onreadystatechange=function() :  Dans le cas d’une requête asynchrone, il faut spécifier une fonction de callback qui va contenir notre programme Javascript.
– if(xmlHttp.readyState==4&&xmlHttp.status==200) : on teste que les données ont bien été réceptionnées et que tout s’est bien passé (status 200).
xmlDoc=xmlHttp.responseXML : on stocke les données reçues au format XML (<xml><bouton_status>on ou off</bouton_status></xml>).
– Ensuite on récupère l’état on ou off par l’intermédiaire de cette ligne :
  xmlmsg=xmlDoc.getElementsByTagName(’bouton_status’)[0].firstChild.nodeValue;
document.getElementById(’bouton’).innerHTML=xmlmsg : on va mettre à jour le HTML qui possède le Tag ’bouton’ référencé par <A id= »bouton »> </A>.
– Puis ensuite on active ou désactive les boutons via leur Tag ID correspondant.
xmlHttp.open(‘PUT’,’traite_xml’,true) : on envoi l’information ‘traite_xml’ qui sera intercepté par le serveur Web. Ici nous pourrions envoyés d’autres informations que le programme devrait interpréter dans le cas d’une communication bi-directionnelle.
xmlHttp.send(null) : on a fini l’envoie.
<BODY onload= »process() »> : on charge le code HTML et on lance la fonction process.
Pour la partie programme :
– On a une fonction qui permet de créer le XML à envoyer via la commande server.send(200, « text/xml », XML).
Voilà c’est tout pour le fonctionement AJAX.
Un excellent site est disponible pour l’apprentissage du langage AJAX :
Catégories :NodeMCU Étiquettes : , ,
  1. vVDB
    07/07/2018 à 19:11

    Bonjour,
    C’est très bien cet exemple…
    Mais la galère pour copier/coller le code des caractères qui ne correspondent pas et des invisibles…
    Pourriez vous remettre ces exemples entre des balises pour que les suivants galère moins ?
    Merci encore

    • 02/10/2018 à 07:42

      Bonjour,
      Je sais. Je vais mettre les sources sur github

      • vVDB
        03/10/2018 à 14:32

        Le source, juste entre des balises

        
        				
  2. vVDB
    03/10/2018 à 14:34

    Balises : pré

  1. No trackbacks yet.

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l’aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

%d blogueurs aiment cette page :