Projet station météo ESP8266 (Partie 1). Créer l'interface HTML, stockage SPIFFS • Domotique et objets connectés à faire soi-même

u7lrvjdlmjx8er9s6098-1536451

Code source

Dans ce premier article consacrée à la fabrication d’une station météo avec interface Web, nous allons créer le code de l’interface HTML indépendamment du code Arduino du projet ESP8266. 

Dans l’article précédent, nous avons vu comment créer un serveur web sur l’ESP8266 (Web Server) qui permet d’afficher une interface HTML depuis un navigateur internet. Cette interface permet d’afficher des données (venant d’un capteur connecté à l’ESP8266) et/ou de réaliser des actions (piloter le GPIO).

Le code de l’interface HTML est intégré dans le code Arduino du projet. Cette approche devient rapidement ingérable lorsque l’interface devient complexe. Dans ce cas, il est préférable (nécessaire) de séparer le code de l’interface (code HTML, style CSS…) du code Arduino du projet.

Le code HTML a été entièrement développé à l’aide du pseudo-langage Pug. Avant de commencer, je vous conseille de lire de découverte

Préparer le projet

Il existe deux librairies qui permettent de manipuler des fichiers sur un ESP8266 (presque) comme sur un ordinateur. La librairie LittleFS et FS.h qui est une implémentation de SPIFFS pour l’ESP8266. Pour ce projet, nous utiliserons la librairie FS.h.

Choisir la taille de la zone mémoire

Les modules ESP8266 disposent d’une mémoire flash (similaire aux clés USB). La mémoire flash est découpée et chaque espace est réservée pour chaque fonction :

  • Sketch code C++ du projet
  • OTA update zone tampon utilisée pour télécharger une nouvelle mise à jour du sketch
  • File System (FS) c’est ce qui nous intéresse ici
  • EEPROM une petite zone mémoire qui simule l’EEPROM de l’Arduino. On pourra y stocker des paramètres
  • WiFi config est une zone réservée pour le stockage des paramètres de connexion lorsqu’on développe directement en C++ avec le SDK ESP-IDF
|--------------|-------|---------------|--|--|--|--|--|
^ ^ ^ ^ ^
Sketch OTA update File system EEPROM WiFi config (SDK)

La taille de la mémoire flash varie d’un fabricant à un autre mais la norme est de 4Mo.

Sélectionner votre carte ESP8266 depuis le menu Outils -> Carte de développement

Puis vous pourrez choisir la quantité de mémoire flash allouée au système de fichier depuis le menu Outils -> Flash Size

Par exemple pour la LoLin – WeMos d1 Mini, il existe 4 choix possibles : aucune allocation 1Mo 2Mo ou 3Mo.

g3mhvhs85q65dwyjstjv-6138500

Comment organiser les fichiers puis le transférer dans la zone SPIFFS depuis l’IDE Arduino ?

Tous les fichiers de l’interface devront être stockés dans un dossier data situé à la racine du projet (au même niveau que le fichier principal du projet). Voici un exemple d’organisation.

Il faudra téléverser manuellement les fichiers avant le premier démarrage et à chaque modification depuis l’IDE Arduino. Pour cela, il faudra installer le plugin ESP8266fs (ou ESP8266 Sketch Data Upload) qui ajoute une options au menu outil de l’IDE Arduino. Tout est expliqué dans ce tutoriel.

Préparation de l’interface HTML

Nous allons donc utiliser le langage Pug pour préparer le code de l’interface HTML.

Entête de la page (header)

Pour créer notre interface, nous allons avoir besoin de nouvelles ressources. Dans un premier temps, nous allons simplement aller les chercher sur internet.

Nous verrons dans le prochain tutoriel qu’il est possible d’ajouter dans la zone SPIFFS toutes les ressources nécessaire.

On va donc créer une entête (Head) qui indique les ressources que doit charger le navigateur, ici jquery, bootstrap.js, bootstrap-table.js, bootstrap.css et bootstrap-table.css.

Quelques remarques :

  • L’ordre n’a aucune importance
  • On récupère les versions “minifiées”, plus compactes mais difficile à comprendre
  • La balise name=’viewport’ est réservée à Bootstrap.
  • La balise http-equiv=’refresh’ qui permettait de demander au navigateur d’actualiser l’affichage régulièrement a été supprimée. Nous allons gérer l’actualisation de l’affichage autrement.
head
  meta(name='viewport')
  script(src='https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js')
  script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
  link(rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.css")
  script(src="http://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.js")
  link(href='https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css', rel='stylesheet' title="main")
  title Demo ESP8266 SPIFFS + Boostrap - www.projetsdiy.fr

Ajout d’une barre de navigation (body)

Passons au corps de la page (body). En dessous du titre du projet (balise h1), nous allons ajouter une barre de navigation qui permet de regrouper les informations par thème (mesures, graphiques GPIO, configuration).

Avec Bootstrap, elle est gérée par les classes .nav et .nav-tabs. Chaque onglet (tab) est composé d’une balise li.

L’attribut active permet d’indiquer l’onglet actif par défaut.

Une balise a permet d’indiquer le titre de l’onglet et surtout d’indiquer vers quel élément se rendre lorsqu’on clique (href=”#iddestination”).

L’attribut data-toggle rend “cliquable” l’onglet.

ul#tab.nav.nav-tabs
  li.active
    a(href="#tab_mesures" data-toggle="tab") Mesures
  li
    a(href="#tab_graphs" data-toggle="tab") Graphiques
  li
    a(href="#tab_gpio" data-toggle="tab") GPIO  
  li
   a(href="#tab_configuration" data-toggle="tab") Configuration

Ensuite il ne reste plus qu’à créer une div de classe tab-content puis une div tab-pane pour chaque onglet.

Ce qui donne par exemple

div.tab-content
  div#tab_mesures.tab-pane
    h1 Onglet Mesures
  div#tab_graphs
    h1 Onglet Graphiques

Pour rendre l’affichage plus sympa, on peut aussi ajouter une animation lorsqu’on passe d’un onglet à l’autre :

div#tab_mesures.tab-pane.fade.in

De même, on indique le premier onglet actif par défaut (pour la première ouverture de la page).

div#tab_mesures.tab-pane.fade.in.active

Il n’y a rien de plus à programmer pour créer une barre de navigation et naviguer d’un onglet à l’autre !

Ajout d’une table Bootstrap-table

Bootstrap-table est un plugin Bootstrap très connu et très puissant pour créer des tables et réaliser des opérations (page du projet sur GitHub). Elle permet entre autre d’être actualisée très facilement). Pour le moment, on va juste la poser dans l’onglet Mesures.

On créé un champ table. On va simplement placer une balise th pour chaque colonne.

On affecte à chaque colonne une source de données data-field qui sera associé à une clé du JSON envoyé par le code Arduino.

Enfin on attribue un data-formatter, c’est une fonction qui est appelée à chaque fois qu’une ligne est ajoutée au tableau et qui permet de mettre en forme le contenu.

Nous verrons dans le prochain tutoriel comment remplir cette table.

table(id='tab_mesures' data-toggle='table' data-show-colunns='true')
  thead
    tr
      th(data-field='mesure' data-align='left' data-sortable='true' data-formatter='labelFormatter') Mesure
      th(data-field='valeur' data-align='left' data-sortable='true' data-formatter='valueFormatter') Valeur
      th(data-field='precedente' data-align='left' data-sortable='true' data-formatter='vpFormatter') Valeur Précédente

Voici ce qu’on va obtenir (avec le thème Bootstrap par défaut).

xhowamr9y8bh1ynxsayj-8206997

Bas de page (footer)

Fonction gadget, mais utile pour apprendre d’autres notions d’HTML, un bas de page (footer) fixé. Le bas de page ne bouge pas lorsqu’on passe d’un onglet à l’autre. Vous pouvez utiliser cette zone pour indiquer toutes sortes d’informations (date, heure, qualité de réception Wi-Fi, charge CPU…) Pour fixer le bas de page, on va juste ajouter un ligne (row) et lui donner les paramètres dans l’attribut HTML style

  • position:absolute la ligne (row) est positionnée de manière absolue
  • bottom:0, en bas de la page à 0 pixels du bords
  • width:100%, et cette ligne prend toute la largeur du navigateur disponible

Dans cette ligne on va ajouter 3 colonnes. La première va contenir une image (mon logo  🙂 ), et deux liens. Le contenu n’est pas important, ce qui est important est de voir comment rendre le contenu responsive, c’est à dire qu’il s’adapte à tous les écrans et comment on charge une image depuis la zone SPIFFS.

Pour afficher une image, on ajoute une balise img, dans la source src, on indique le chemin sous la forme repertoire/image.jpg. On peut aussi imposer la taille width=”30″(largeur de 30 pixels) et height=”30″ (hauteur).

Bootstrap utilise un système de grilles. Si on diminue la taille du navigateur, les cellules vont commencer à se réduire puis et se mettre les unes sous les autres. Pour cela, on utilise les classes col-md-x.
La somme des x ne doit pas dépasser 12 (l’écran est divisé en 12 colonnes). Pour s’adapter aux plus petits écrans (smartphone notamment), on peut par exemple combiner avec une classe col-xs-x.
C’est une approche très simpliste mais ça fonctionne et ce n’est pas l’objectif principal de l’article.

row(style="position:absolute; bottom:0; width:100%")
  .col-xs-2.col-md-2
    img(src="img/logo.png" width="30" height="30")
  .col-xs-5.col-md-5
    p
      a(href='http://www.projetsdiy.fr') Version francaise : www.projetsdiy.fr
  .col-xs-5.col-md-5
    p
      a(href='http://www.diyprojects.io') English version : www.diyprojects.io

Voici le rendu obtenu pour différentes largeurs d’écran. Taille normale

apjwfka95nxeeyur0gov-5131319

Taille réduite.

Smartphone (simulée)

pdtcisg0fisweewagixf-9510063

Comment changer le thème Bootstrap sans actualiser la page

Nous allons introduire les premières notions de javascript et de jquery pour changer le thème bootstrap.

Nous allons utiliser le framework Bootstrap pour créer l’interface HTML

ainsi que les thèmes Bootswatch mis à disposition par BootstrapCDN pour améliorer le design de l’interface

On va commencer par modifier la liste de sélection.

Le champ caché qui servait à stocker le thème sélectionné puis envoyé au code Arduino à l’aide d’une requête HTTP de type POST n’est plus utile.

On va intercepter un clic sur la classe change-style-menu-item et on va récupérer le style sélectionné contenu dans l’attribut rel.

Le code HTML de la boite de sélection devient donc le suivant.

.btn-group
  button#labelTheme.btn.btn-default Theme
  button.btn.btn-default.dropdown-toggle(data-toggle='dropdown')
    span.caret
  ul.dropdown-menu
    li
      a.change-style-menu-item(href='#' rel='bootstrap') Boostrap
    ....

Maintenant on ajoute un script. Lorsqu’on intercepte un clic sur la classe change-style-menu-item à l’aide d’une commande jQuery.

On récupère la valeur de l’attribut rel avec la commande $(this).attr(‘rel’).

This contient l’objet qui vient d’être cliqué. On accède à l’attribut avec la méthode attr()

jQuery(function($){
  ('body').on('click', '.change-style-menu-item', function() {
    var theme_name = $(this).attr('rel');
    console.log("Changement de theme " + theme_name);
    var theme_url = get_themeUrl(theme_name);
    console.log("URL theme : " + theme_url);
    set_theme(theme_url);
  });
});

Pour comprendre et voir ce qui se passe, vous pouvez ouvrir les outils pour développeurs de votre navigateur et mettre un point d’arrêt.

xttghmkx4rc3vilnfouv-1007264

Maintenant qu’on connait le thème sélectionné, on construit l’URL qui pointe vers le site internet correspondant.

On en profite pour actualiser le libellé du bouton en y incluant le nom du nouveau thème.

Enfin, si le stockage dans la base de données locale est disponible (cela va dépendre du navigateur utilisé, pas de l’ESP8266), on enregistre le thème.

function get_themeUrl(theme_name){
  $('#labelTheme').html("Thème : " + theme_name);
  var url_theme = "";
  if ( theme_name === "bootstrap" ) {
    url_theme = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css";
  } else {
    url_theme = "https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/" + theme_name + "/bootstrap.min.css";
  }
  if (supports_storage) {
    // Enregistre le theme sélectionné en local - save into the local database the selected theme
    localStorage.theme = theme_name;
  }
  return url_theme;
}

Maintenant il ne reste plus qu’à reconstruire la page avec ce thème. Pour que cela puisse fonctionner, il faut ajouter un attribut title=”main” dans le lien vers le CDN Bootstrap

link(href='https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css', rel='stylesheet' title="main")

On modifie le href du link[title=”main”].

function set_theme(theme_url) {
  $('link[title="main"]').attr('href', theme_url);
}

Il nous reste encore deux fonctions à écrire, la première retourne vrai si le stockage en ligne est disponible

function supports_html5_storage(){
  try {
    return 'localStorage' in window && window['localStorage'] !== null;
  } catch (e) {
    return false;
  }
}

Et enfin la dernière fonction qui permet de recharger le thème s’il a été enregistré dans la base locale.

var supports_storage = supports_html5_storage();
  if (supports_storage) {
    var theme = localStorage.theme;
    console.log("Recharge le theme " + theme);
    if (theme) {
      set_theme(get_themeUrl(theme));
    }
}

Voilà, maintenant tout se passe directement sur le navigateur, l’ESP8266 n’est plus chargé de reconstruire la page à chaque changement d thème, ce rôle est dévolu au navigateur.

Code complet de la première partie

u7lrvjdlmjx8er9s6098-1536451

Code source

Voici les codes Arduino et HTML. Rien n’est encore fonctionnel à ce stade du développement (à l’exception du changement dynamique du thème).

Code Arduino compatible ESP8266

Créez un nouveau projet et collez le code suivant.

  • On appel la librairie FS.h qui permet d’accéder de monter le système de fichier SPIFFS
  • Pour pouvoir accéder aux fichiers stockés dans la zone SPIFFS, il faut initialiser la librairie en appelant la fonction SPIFFS.begin() dans le setup()
  • On indique au serveur les pages et les ressources statiques qui doivent être misent à disposition du navigateur, pour le moment /img et la racine du site (/) qui pointe vers la page index.html.

N’oubliez pas de changer le SSID et le PASSWORD du réseau WiFi dans le code avant de téléverser.

#include 
#include 
#include 
#include 

#define ssid      "xxxx"      // WiFi SSID
#define password  "xxxx"      // WiFi password
#define DHTTYPE   DHT22       // DHT type (DHT11, DHT22)
#define DHTPIN    D4          // Broche du DHT / DHT Pin
const uint8_t GPIOPIN[4] = {D5,D6,D7,D8};  // Led
float   t = 0 ;
float   h = 0 ;
float   pa = 0;

// Création des objets / create Objects
DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP085 bmp;
ESP8266WebServer server ( 80 );

void setup() {
  for ( int x = 0 ; x < 5 ; x++ ) {
    pinMode(GPIOPIN[x], OUTPUT);
  }
  
  Serial.begin ( 115200 );
  // Initialisation du BMP180 / Init BMP180
  if ( !bmp.begin() ) {
    Serial.println("BMP180 KO!");
    while (1);
  } else {
    Serial.println("BMP180 OK");
  }

  WiFi.begin ( ssid, password );
  // Attente de la connexion au réseau WiFi / Wait for connection
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 ); Serial.print ( "." );
  }
  // Connexion WiFi établie / WiFi connexion is OK
  Serial.println ( "" );
  Serial.print ( "Connected to " ); Serial.println ( ssid );
  Serial.print ( "IP address: " ); Serial.println ( WiFi.localIP() );

  if (!SPIFFS.begin())
  {
    // Serious problem
    Serial.println("SPIFFS Mount failed");
  } else {
    Serial.println("SPIFFS Mount succesfull");
  }

  server.serveStatic("/img", SPIFFS, "/img");
  server.serveStatic("/", SPIFFS, "/index.html");

  server.begin();
  Serial.println ( "HTTP server started" );

}

void loop() {
  // put your main code here, to run repeatedly:
  server.handleClient();
  t = dht.readTemperature();
  h = dht.readHumidity();
  pa = bmp.readPressure() / 100.0F;
  delay(100);
}

Sélectionnez l’ESP8266 (ici Wemos D1 mini) puis téléversez le projet dans l’ESP8266.

Code PUG de l’interface HTML

Avant de commencer, je vous conseille de lire ce tutoriel qui explique comment développer facilement des interfaces HTML à l’aide de Pug.

Aller dans le répertoire du projet et créer un nouveau dossier data. Créer un sous dossier img

Créer un nouveau document sous Geany ou VSCode et collez le code suivant.

Enregistrer le fichier en lui donnant le nom index.pug à la racine du dossier data.

Convertir le code PUG en HTML comme ceci

  • Sur Geany, compilez le code HTML à l’aide de pug-cli en appuyant sur la touche (F8)
  • Sur VSCode :
    • Créer un nouveau fichier,
    • Coller le code PUG et
    • Enregistrer le fichier sous le nom index.html
    • Sélectionner tout le code (Ctrl + A)
    • Convoquer la palette (CMD + SHIFT + P) puis exécuter pug2html
    • Enregistrer
html(charset='UTF-8')
    head
      meta( name='viewport')
      script(src='https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js')
      script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
      link(rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.css")
      script(src="http://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.js")
      link(href='https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css', rel='stylesheet' title="main")
      title Demo ESP8266 SPIFFS + Boostrap - www.projetsdiy.fr
    body
      .container-fluid
        h1 ESP8266 Webserver + SPIFFS + Bootstrap
        ul#tab.nav.nav-tabs
          li.active
            a(href="#tab_mesures" data-toggle="tab") Mesures
          li
            a(href="#tab_graphs" data-toggle="tab") Graphiques
          li
            a(href="#tab_gpio" data-toggle="tab") GPIO  
          li
            a(href="#tab_configuration" data-toggle="tab") Configuration
        div.tab-content
        
          div#tab_mesures.tab-pane.fade.in.active          
            
            h2 Mini station météo (DHT22 + BMP180)
            ul.nav.nav-pills
                li.active
                    a(href='#')
                        #temperature.span.badge.pull-right -
                        |  Température
                li
                    a(href='#')
                        #humidite.span.badge.pull-right -
                        |  Humidité
                li
                    a(href='#')
                        #pa.span.badge.pull-right -
                        |  Pression atmosphérique
            table(id='tab_mesures' data-toggle='table' data-show-colunns='true')
                thead
                    tr
                        th(data-field='mesure' data-align='left' data-sortable='true' data-formatter='labelFormatter') Mesure
                        th(data-field='valeur' data-align='left' data-sortable='true' data-formatter='valueFormatter') Valeur
                        th(data-field='precedente' data-align='left' data-sortable='true' data-formatter='vpFormatter') Valeur Précédente
          div#tab_graphs.tab-pane.fade
            h2 Graphs
            
          div#tab_gpio.tab-pane.fade
            h2 GPIO
            .row
                .col-xs-6.col-md-4
                  h4.text-left
                    | D5
                    #D5_etat.span.badge OFF
                .col-xs-6.col-md-4
                  #D5_On.button.btn.btn-success.btn-lg(type='button') ON
                .col-xs-6.col-md-4
                  #D5_Off.button.btn.btn-danger.btn-lg(type='button') OFF
                .col-xs-6.col-md-4
                  h4.text-left
                    | D6
                    #D6_etat.span.badge OFF
                .col-xs-6.col-md-4
                  #D6_On.button.btn.btn-success.btn-lg(type='button') ON
                .col-xs-6.col-md-4
                  #D6_Off.button.btn.btn-danger.btn-lg(type='button') OFF
                .col-xs-6.col-md-4
                  h4.text-left
                    | D7
                    #D7_etat.span.badge OFF
                .col-xs-6.col-md-4
                  #D7_On.button.btn.btn-success.btn-lg(type='button') ON
                .col-xs-6.col-md-4
                  #D7_Off.button.btn.btn-danger.btn-lg(type='button') OFF
                .col-xs-6.col-md-4
                  h4.text-left
                    | D8
                    #D8_etat.span.badge OFF
                .col-xs-6.col-md-4
                  #D8_On.button.btn.btn-success.btn-lg(type='button') ON
                .col-xs-6.col-md-4
                  #D8_Off.button.btn.btn-danger.btn-lg(type='button') OFF
          div#tab_configuration.tab-pane.fade
            h2 Configuration        

            .btn-group
              button#labelTheme.btn.btn-default Theme
              button.btn.btn-default.dropdown-toggle(data-toggle='dropdown')
                span.caret
              ul.dropdown-menu
                li
                    a.change-style-menu-item(href='#' rel='bootstrap') Boostrap
                li
                    a.change-style-menu-item(href='#' rel='cerulean') Cerulean
                li
                    a.change-style-menu-item(href='#' rel='cosmo') Cosmo
                li
                    a.change-style-menu-item(href='#' rel='cyborg') Cyborg
                li
                    a.change-style-menu-item(href='#' rel='darkly') Darkly
                li
                    a.change-style-menu-item(href='#' rel='flatly') Flatly
                li
                    a.change-style-menu-item(href='#' rel='journal') Journal
                li
                    a.change-style-menu-item(href='#' rel='lumen') Lumen
                li
                    a.change-style-menu-item(href='#' rel='paper') Paper
                li
                    a.change-style-menu-item(href='#' rel='readable') Readable
                li
                    a.change-style-menu-item(href='#' rel='sandstone') Sandstone
                li
                    a.change-style-menu-item(href='#' rel='simplex') Simplex
                li
                    a.change-style-menu-item(href='#' rel='slate') Slate
                li
                    a.change-style-menu-item(href='#' rel='spacelab') Spacelab
                li
                    a.change-style-menu-item(href='#' rel='superhero') Superhero
                li
                    a.change-style-menu-item(href='#' rel='united') United
                li
                    a.change-style-menu-item(href='#' rel='yeti') Yeti  
        .row(style="position:absolute; bottom:0; width:100%")
          .col-xs-2.col-md-2
            img(src="img/logo.png" width="30" height="30")
          .col-xs-5.col-md-5
            p
              a(href='http://www.projetsdiy.fr') Version francaise : www.projetsdiy.fr
          .col-xs-5.col-md-5
            p
              a(href='http://www.diyprojects.io') English version : www.diyprojects.io
        
      script().     
        // Un nouveau thème est sélectionné - New theme selected
        jQuery(function($){
          $('body').on('click', '.change-style-menu-item', function() {
            var theme_name = $(this).attr('rel');
            console.log("Changement de theme " + theme_name);
            var theme_url = get_themeUrl(theme_name);
            console.log("URL theme : " + theme_url);
            set_theme(theme_url);
          });
        });
        // Recupere l'adresse du theme - Get theme URL
        function get_themeUrl(theme_name){
          $('#labelTheme').html("Thème : " + theme_name);
          var url_theme = "";
          if ( theme_name === "bootstrap" ) {
            url_theme = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css";
          } else {
            url_theme = "https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/" + theme_name + "/bootstrap.min.css";
          }
          if (supports_storage) {
            // Enregistre le theme sélectionné en local - save into the local database the selected theme
            localStorage.theme = theme_name;
          }
          return url_theme;
        }
        // Applique le thème - Apply theme
        function set_theme(theme_url) {
          $('link[title="main"]').attr('href', theme_url);
        }
        // Stockage local disponible ? - local storage available ?
        function supports_html5_storage(){
          try {
            return 'localStorage' in window && window['localStorage'] !== null;
          } catch (e) {
            return false;
          }
        }

Vous pouvez aussi créer directement le fichier index.html dans le répertoire data et coller le code suivant. Le code ci-dessous a été généré à partir du code Pug précédent.



  
    
    
    
    
    
    
    Demo ESP8266 SPIFFS + Boostrap - www.projetsdiy.fr
  
  
    
      

Demo Webserver ESP8266 + Bootstrap

      
      
                 
          

Mini station météo (DHT22 + BMP180)

          
          
Mesure Valeur ValeuPrécédente

Graphs

GPIO

D5 OFF

ON OFF

D6 OFF

ON OFF

D7 OFF

ON OFF

D8 OFF

ON OFF

Configuration

Theme

Version francaise : www.projetsdiy.fr

English version : www.diyprojects.io

// Changement du thème - Change current theme // Adapté de - Adapted from : https://wdtz.org/bootswatch-theme-selector.html var supports_storage = supports_html5_storage(); if (supports_storage) { var theme = localStorage.theme; if ( typeof theme != 'undefined' ) { console.log("Recharge le theme " + theme); set_theme(get_themeUrl(theme)); } } // Un nouveau thème est sélectionné - New theme selected jQuery(function($){ $('body').on('click', '.change-style-menu-item', function() { var theme_name = $(this).attr('rel'); console.log("Changement de theme " + theme_name); var theme_url = get_themeUrl(theme_name); console.log("URL theme : " + theme_url); set_theme(theme_url); }); }); // Recupere l'adresse du theme - Get theme URL function get_themeUrl(theme_name){ $('#labelTheme').html("Thème : " + theme_name); var url_theme = ""; if ( theme_name === "bootstrap" ) { url_theme = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"; } else { url_theme = "https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/" + theme_name + "/bootstrap.min.css"; } if (supports_storage) { // Enregistre le theme sélectionné en local - save into the local database the selected theme localStorage.theme = theme_name; } return url_theme; } // Applique le thème - Apply theme function set_theme(theme_url) { $('link[title="main"]').attr('href', theme_url); } // Stockage local disponible ? - local storage available ? function supports_html5_storage(){ try { return 'localStorage' in window && window['localStorage'] !== null; } catch (e) { return false; } }

Le projet doit avoir (environ) cette arborescence

Fermer le moniteur série.

Allez dans le menu Outils et sélectionnez la vitesse d’upload speed de 921600 bauds.

Enfin, allez dans le menu Outils puis cliquez sur ESP8266 Sketch Data Upload. L’opération démarre immédiatement.

aer2qop8uwuntrkd0xjl-6050584

Une fois le téléchargement achevé, repassez la vitesse d’upload à 115200 bauds et ouvrez le terminal pour vérifier que l’ESP8266 est correctement connecté au réseau WiFi. Récupérez l’adresse IP.

Ouvrez un navigateur et saisissez l’adresse IP de l’ESP8266.

Bravo, ça fonctionne !

En résumé, nous avons vu comment créer une interface HTML de toute pièce à l’aide du langage Pug.

On peut changer dynamiquement le thème Bootstrap et stocker le choix dans la base de données du navigateur pour le prochain chargement.

On a mis en place une barre de navigation qui permet de regrouper les éléments par thèmes.

On sait comment utiliser la zone SPIFFS pour y stocker tous les fichiers nécessaires au fonctionnement de l’interface. Il reste encore beaucoup à faire !

Accéder rapidement aux autres parties du projet

Voici les liens pour poursuivre le projet de station météo

Vous êtes ici

Avez-vous aimé cet article ?