Projet de station météo avec interface HTML sur ESP8266 (DHT22 + BMP180)

Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram
code source projet station meteo esp8266 avec interface web

Code source

Nous allons développer une mini station météo avec une interface HMTL accessible depuis un ordinateur ou smartphone en WiFi. Dans la série d’articles précédents, nous avons découvert comment programmer une interface HTML pour ESP8266 avec du code Arduino.

 

Voici une série d’article pour débuter avec la programmation de l’interface HTML des ESP8266.

A LIRE AUSSI :
ESP8266. Débuter sur IDE Arduino. Librairies, GPIO, programmation Web Serveur, Client Web, drivers
A LIRE AUSSI :
ESP8266. Comprendre le code Arduino d'un serveur web avec interface HTML
A LIRE AUSSI :
Interface HTML pour ESP8266. Améliorer le design avec Bootstrap
A LIRE AUSSI :
Interface HTML pour ESP8266. Changer de thème Bootstrap avec Bootswatch et bootstrapCDN

Nous allons aller encore plus loin avec ce nouveau projet en apprenant comment gérer séparément le code de l’interface Web qui sera entièrement stocké dans la zone mémoire de l’ESP8266 à l’aide du système de fichier SPIFFS. Nous verrons également comment stocker les mesures (température, humidité, pression atmosphérique) au format JSON dans un fichier dans la zone mémoire. Ces données seront utilisées pour tracer un historique de mesure à l’aide de la librairie Google Charts.

Présentation du projet de station météo avec un ESP8266

Nous allons aborder de nombreuses notions dans ce projet de station météo connectée réalisée à l’aide d’un ESP8266.

Mais tout d’abord, voici à quoi ressemblera l’interface de la station météo.

esp8266 web server spiffs bootstrap dht22 bmp180 google charts

L’interface HTML sera développée à l’aide de Bootstrap. Les informations sont accessibles via 4 onglets :

  • Mesures affiche les mesures des capteurs DHT22 et BMP180
  • Graphiques historique des mesures à l’aide de la librairie Google Charts
  • GPIO pour tester le pilotage du GPIO de l’ESP8266 depuis l’interface WEB. On pourrait par exemple piloter l’ouverture/fermeture des stores, des volets…
  • Configuration

 

Il y a énormément de notions et d’aspects techniques abordés dans ce projet, il a donc été découpé en 5 parties.

logo github

Code source

Partie 1 Comment séparer et développer l’interface HTML de la station météo du code Arduino

  • Comment développer le code HTML de interface Web
    • Pour cela, nous utiliserons le langage Pug (auparavant appelé Jade) qui permet de simplifier l’écriture
    • Notions d’HTML abordées : menu de navigation, image, fixer le bas de page (footer), meilleure gestion “responsive” pour les petits écrans
  • Comment changer le thème de l’interface
    • Comment stocker le choix pour recharger le thème au prochain chargement de l’interface
  • Comment préparer et utiliser la zone SPIFFS pour stocker les fichiers HTML, JS, CSS, images
    • et les envoyer sur l’ESP8266
    • Premier test de l’interface WEB sur l’ESP8266
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 1). Créer l'interface HTML, stockage SPIFFS
logo github

Code source

Partie 2 Comment interagir avec le code Arduino

  • Intercepter les actions sur les boutons de l’interface et actualiser les affichages lorsque l’action a été réalisée (Javascript + jQuery)
    • Récupérer les requêtes sur l’Arduino, exécuter la demande et envoyer la réponse
  • Actualiser régulièrement (et automatiquement) le tableau de mesures et les afficheurs (Javascript)
    • Mettre à jour les symboles si la valeur actuelle est supérieure ou inférieure à la précédente
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 2). Piloter le code Arduino depuis l'interface HTML

Partie 3 Comment récupérer l’heure depuis internet sur un serveur de temps à l’aide de la librairie NtpClientLib

Nous verrons comment stocker la date et l’heure dans un fichier sur la zone mémoire à l’aide du système de fichier SPIFFS

A LIRE AUSSI :
Projet station météo ESP8266 (Partie 3). Récupérer l'heure avec NTPClient et stockage SPIFFS

Partie 4 Comment collecter les mesures et créer un historique de mesures

  • Manipuler les données à l’aide de la librairie ArduinoJSON
  • Enregistrer des données (historique de mesure) dans un fichier au format JSON sur la zone SPIFFS
  • Recharger le fichier historique au démarrage de l’ESP8266
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 4). ArduinoJson, charger, enregistrer des fichiers (SPIFFS)
logo github

Code source

Partie 5 Comment ajouter des graphiques et des jauges sur l’interface HTML à l’aide de la librairie Google Charts

  • Evolution de la température et de l’humidité moyenne sur les 7 dernières heures (histogramme en barre)
  • Affichage de la mesure courante sous la forme d’une gauge thématique : thermomètre (température), goutte d’eau (humidité), gauge (pression atmosphérique)
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 5). Afficher des jauges et graphiques Google Charts

Logiciels nécessaires

Comme vous le savez, il est possible de programmer l’ESP8266 en C++ depuis l’IDE Arduino. C’est une très bonne solution pour débuter car on trouve beaucoup plus facilement des exemples, informations, librairies, forums et l’accès aux débutants et plus facile.

A LIRE AUSSI :
ESP8266. Débuter sur IDE Arduino. Librairies, GPIO, programmation Web Serveur, Client Web, drivers

Pour ceux d’entre vous qui êtes plus avancés, vous pouvez vous tourner vers PlatformIO sur VSCode, une solution plus flexible et professionnelle

A LIRE AUSSI :
Débuter avec PlatformIO IDE sur VSCode (Windows, macOS, Raspbian, Linux)

Il est possible d’écrire directement le code HTML dans le code Arduino mais pour des projets de grande envergure (tel que cette station météo), cela devient vite difficile à maintenir.

Pour contourner ce problème, il est préférable de séparer le code de l’interface HTML ainsi que les feuilles de style CSS et le code Javascript du code Arduino.

Il est également possible d’écriture du code HTML en développant le code de l’interface avec un pseudo-langage. Je vous conseille d’utiliser le langage Pug (ancien Jade). Pug permet de simplifier la mise au point du code car on ne gère plus la fermeture des balises.

N’importe quel éditeur de code fera l’affaire. Si vous êtes sur Raspberry Pi OS (nouveau nom de Raspbian), vous pouvez utiliser Geany. Visual Studio Code de Microsoft reste toutefois une référence et dispose d’un très grand nombre d’extensions qui facilitent la vie.

A LIRE AUSSI :
Découverte du langage Pug (Jade) pour développer des interfaces HTML avec VSCode ou Geany

Matériel nécessaire

Coté matériel, nous allons rester dans le classique, l’objectif et d’avoir à disposition des données à afficher. Le code Arduino du projet est adapté au DHT22 qui permettra de récupérer la température et l’humidité environnante. Le BMP180 permettra de récupérer la pression atmosphérique.

Coté ESP8266, nous utiliserons une LoLin – WeMos d1 mini disposant de 3Mo de mémoire flash attribuable au système de fichier SPIFFS.

esp8266 Wemos D1 mini Module ESP8266, par exemple une LoLin (Wemos) D1 Mini
chargeur raspbery pi 3 5v 3000ma Alimentation 5/3A micro-usb

L’ESP8266 est sensible à la qualité de l’alimentation (risque de plantage). Une alimentation de qualité est recommandée.

BMP180 Capteur de pression atmosphérique

BMP180

Broches DHT22 Capteur de température et d’humidité

DHT11 ou DHT22

jumper dupont Des Jumpers Dupont
breadboard Une Breadboard

Stockage des fichiers

Les fichiers de l’interface HTML (fichiers HTML, feuilles de styles CSS, images, fichiers javascripts…) seront stockés sur la mémoire flash de l’ESP8266 dans la zone réservée au système de fichier

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.

Comment 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.

Sélectionner la dimension de la zone mémoire de l'ESP8266 depuis le menu outil de l'IDE Arduino

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

Tous les fichiers de l’interface seront 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.

Dossier data d'un projet ESP8266

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. Lisez ce tutoriel pour en savoir plus

A LIRE AUSSI :
ESP8266. Sketch data upload pour IDE Arduino. Téléverser des fichiers vers la zone SPIFFS

Si vous débutez avec le système de fichier SPIFFS, commencez par lire ce tutoriel

A LIRE AUSSI :
ESP8266. Lire, écrire, modifier des fichiers SPIFFS avec la librairie FS.h

Code complet du projet

Le code complet du projet est entièrement disponible sur le dépôt GitHub du blog sur cette page.

Voici toutefois le code final du projet pour gagner du temps

Code HTML de l’interface WEB

Le code HTML de la page.

Suivez ce tutoriel qui explique comment téléverser le fichier HTML de la page dans la zone SPIFFS de l’ESP8266

<!DOCTYPE html>
<html charset="UTF-8">
  <head>
    <meta name="viewport">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.css">
    <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</title>
  </head>
  <body>
    <div class="container-fluid">
      <h1>ESP8266 Web Server + SPIFFS + Bootstrap + Google Charts </h1>
      <ul class="nav nav-tabs" id="tab">
        <li class="active"><a href="#tab_mesures" data-toggle="tab">Mesures</a></li>
        <li><a href="#tab_graphs" data-toggle="tab">Graphiques</a></li>
        <li><a href="#tab_gpio" data-toggle="tab">GPIO  </a></li>
        <li><a href="#tab_configuration" data-toggle="tab">Configuration</a></li>
      </ul>
      <div class="tab-content">
        <div class="tab-pane fade in active" id="tab_mesures">        
          <h2>Mini station m&eacute;t&eacute;o (DHT22 + BMP180)</h2>
          <ul class="nav nav-pills">
            <li class="active"><a href="#">
                <div class="span badge pull-right" id="temperature">-</div> Temp&eacute;rature</a></li>
            <li><a href="#">
                <div class="span badge pull-right" id="humidite">-</div> Humidit&eacute;</a></li>
            <li><a href="#">
                <div class="span badge pull-right" id="pa">-</div> Pression atmosph&eacute;rique</a></li>
          </ul><br>
          <table id="table_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>
                <th data-field="valeur" data-align="left" data-sortable="true" data-formatter="valueFormatter">Valeur</th>
                <th data-field="precedente" data-align="left" data-sortable="true" data-formatter="vpFormatter">Valeur Pr&eacute;c&eacute;dente</th>
              </tr>
            </thead>
          </table>
        </div>
        <div class="tab-pane fade" id="tab_graphs">
          <div class="panel panel-default">
            <div class="panel-heading">
              <div class="row panel-title"> 
                <div class="col-xs-4 col-md-4">
                  <div id="labelTemp"></div>
                </div>
                <div class="col-xs-4 col-md-4">
                  <div id="labelHumi"></div>
                </div>
                <div class="col-xs-4 col-md-4">
                  <div id="labelPa"></div>
                </div>
              </div>
            </div>
            <div class="panel body">
              <div class="row">
                <div class="col-xs-6 col-md-6">
                  <div class="div" id="chartTemp" style="width: 100%; height: 300px;"></div>
                </div>
                <div class="col-xs-6 col-md-6">
                  <div class="div" id="chartPA" style="width: 100%; height: 300px;"></div>
                </div>
              </div>
              <div class="row">
                <div class="col-xs-6 col-md-6">
                  <h2 class="label label-info" id="zeroDataTemp">Pas encore de données</h2>
                  <div class="div" id="barTemp" style="width: 100%; height: 300px;"></div>
                </div>
                <div class="col-xs-6 col-md-6">
                  <div class="div" id="gaugePA" style="width: 100%; height: 300px; margin-left: 25%;">    </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="tab-pane fade" id="tab_gpio">
          <h2>GPIO</h2>
          <div class="row">
            <div class="col-xs-4 col-md-4">
              <h4 class="text-left">D5
                <div class="span badge" id="D5_etat">OFF</div>
              </h4>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-success btn-lg" id="D5_On" type="button">ON</div>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-danger btn-lg" id="D5_Off" type="button">OFF</div>
            </div>
          </div>
          <div class="row">
            <div class="col-xs-4 col-md-4">
              <h4 class="text-left">D6
                <div class="span badge" id="D6_etat">OFF</div>
              </h4>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-success btn-lg" id="D6_On" type="button">ON</div>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-danger btn-lg" id="D6_Off" type="button">OFF</div>
            </div>
          </div>
          <div class="row">
            <div class="col-xs-4 col-md-4">
              <h4 class="text-left">D7
                <div class="span badge" id="D7_etat">OFF</div>
              </h4>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-success btn-lg" id="D7_On" type="button">ON</div>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-danger btn-lg" id="D7_Off" type="button">OFF</div>
            </div>
          </div>
          <div class="row">
            <div class="col-xs-4 col-md-4">
              <h4 class="text-left">D8
                <div class="span badge" id="D8_etat">OFF</div>
              </h4>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-success btn-lg" id="D8_On" type="button">ON</div>
            </div>
            <div class="col-xs-4 col-md-4">
              <div class="button btn btn-danger btn-lg" id="D8_Off" type="button">OFF</div>
            </div>
          </div>
        </div>
        <div class="tab-pane fade" id="tab_configuration">
          <h2>Configuration        </h2>
          <div class="btn-group">
            <button class="btn btn-default" id="labelTheme">Theme</button>
            <button class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
            <ul class="dropdown-menu">
              <li><a class="change-style-menu-item" href="#" rel="bootstrap">Boostrap</a></li>
              <li><a class="change-style-menu-item" href="#" rel="cerulean">Cerulean</a></li>
              <li><a class="change-style-menu-item" href="#" rel="cosmo">Cosmo</a></li>
              <li><a class="change-style-menu-item" href="#" rel="cyborg">Cyborg</a></li>
              <li><a class="change-style-menu-item" href="#" rel="darkly">Darkly</a></li>
              <li><a class="change-style-menu-item" href="#" rel="flatly">Flatly</a></li>
              <li><a class="change-style-menu-item" href="#" rel="journal">Journal</a></li>
              <li><a class="change-style-menu-item" href="#" rel="lumen">Lumen</a></li>
              <li><a class="change-style-menu-item" href="#" rel="paper">Paper</a></li>
              <li><a class="change-style-menu-item" href="#" rel="readable">Readable</a></li>
              <li><a class="change-style-menu-item" href="#" rel="sandstone">Sandstone</a></li>
              <li><a class="change-style-menu-item" href="#" rel="simplex">Simplex</a></li>
              <li><a class="change-style-menu-item" href="#" rel="slate">Slate</a></li>
              <li><a class="change-style-menu-item" href="#" rel="spacelab">Spacelab</a></li>
              <li><a class="change-style-menu-item" href="#" rel="superhero">Superhero</a></li>
              <li><a class="change-style-menu-item" href="#" rel="united">United</a></li>
              <li><a class="change-style-menu-item" href="#" rel="yeti">Yeti  </a></li>
            </ul>
          </div>
        </div>
      </div>
      <div class="row" style="position:absolute; bottom:0; width:100%;">
        <div class="col-xs-2 col-md-2"><img src="img/logo.png" width="30" height="30"></div>
        <div class="col-xs-5 col-md-5">
          <p><a href="https://www.projetsdiy.fr">Version francaise : www.projetsdiy.fr</a></p>
        </div>
        <div class="col-xs-5 col-md-5">
          <p><a href="http://www.diyprojects.io">English version : www.diyprojects.io</a></p>
        </div>
      </div>
    </div>
    <!--script(src='js/script.js')-->
    <script>
      var Timer_UdpateMesures;
      var tab_pane;
      google.charts.load('current', {packages: ['corechart', 'line', 'bar', 'gauge']});
      google.charts.setOnLoadCallback(drawChart);
      
      function drawChart(){
        // https://developers.google.com/chart/interactive/docs/reference?csw=1#datatable-class
        var options1 = {
          title: 'Température et humidité - DHT22',
          legend: 'bottom',
          series: {
            // Gives each series an axis name that matches the Y-axis below.
            0: {axis: 'temperature'},
            1: {axis: 'humidite'}
          },
          axes: {
            // Adds labels to each axis; they don't have to match the axis names.
            y: {
              temperature: {label: 'Température (°C)'},
              humidite: {label: 'Humidité (%)'}
            }
          }
        }
        var options2 = {
          title: 'Pression Atmosphérique - BMP180',
          legend: {position: 'none'},
        }
        var optionsGauge = {           
          redFrom: 960, 
          redTo: 990,
           
          yellowFrom: 990, 
          yellowTo: 1030, 
           
          greenFrom: 1030, 
          greenTo: 1080, 
           
          minorTicks: 10,
           
          min: 960, 
          max: 1080, 
           
          animation: {
              duration: 400, 
              easing: 'out',
          },
        };
        // Objets graphiques - Charts objects
        var chartTemp = new google.visualization.AreaChart(document.getElementById('chartTemp'));
        var barTemp = new google.charts.Bar(document.getElementById('barTemp'));
        var chartPA = new google.visualization.AreaChart(document.getElementById('chartPA'));
        var gaugePA = new google.visualization.Gauge(document.getElementById('gaugePA'));
        // Données - Data
        dataGaugePA = new google.visualization.DataTable();
        dataChartTemp = new google.visualization.DataTable();
        dataBarTemp = new google.visualization.DataTable();
        dataChartPA = new google.visualization.DataTable();
        
        // Gauge Pression Atmospherique - Gauge Atmosph. pressure
        dataGaugePA.addColumn('string', 'Label');
        dataGaugePA.addColumn('number', 'Value');
        dataGaugePA.addRows(1);
        
        // Line chart temp/humidity
        dataChartTemp.addColumn('timeofday', 'Temps');
        dataChartTemp.addColumn('number', 'Température');
        dataChartTemp.addColumn('number', 'Humidité');
        
        // Bar temp/humidity
        dataBarTemp.addColumn('string', 'Moyennes');
        dataBarTemp.addColumn('number', 'Température');
        dataBarTemp.addColumn('number', 'Humidité');
        
        // Line Chart PA
        dataChartPA.addColumn('timeofday', 'Temps');
        dataChartPA.addColumn('number', 'Pression Atmosphérique');        
        
        // Force l'actualisation du graphique au 1er lancement - Force chart update first launch
        var firstStart = true;
        updateGraphs();
        // Actualise à intervalle régulier les graphiques - auto-update charts 
        setInterval(updateGraphs, 60000); //60000 MS == 1 minutes
        
        function updateGraphs(){     
          // Uniquement si le panneau des graphs est actif - only if chart panel is active
          if (tab_pane=='#tab_graphs' | firstStart ){
            firstStart = false;
            $.getJSON('/graph_temp.json', function(json){
              //console.log("Mesures envoyees : " + JSON.stringify(data) + "|" + data.t + "|" + data.h + "|" + data.pa) ;
              var _dataT = [];
              var _dataPA = [];
              var _dataBarTemp = [];
              var _dataBarPA = [];
              
              // Data line chart  
              for ( var i = 0; i < json.timestamp.length; i++ ) {
                var d = new Date(json.timestamp[i] * 1000);
                _dataT.push(
                  [
                    [d.getHours(), d.getMinutes(), d.getSeconds()],
                    json.t[i],
                    json.h[i]
                  ]
                )
                _dataPA.push(
                  [
                    [d.getHours(), d.getMinutes(), d.getSeconds()],
                    json.pa[i]
                  ]
                )                
              }
              for ( var i = 0; i < json.bart.length; i++ ) {
                _dataBarTemp.push(
                  [
                   i - 7 + "h",,
                   json.bart[i],
                   json.barh[i]
                  ]
                ) 
              }  
      
              dataGaugePA.setValue(0, 0, 'mbar');
              dataGaugePA.setValue(0, 1, json.pa[0]);
              dataChartTemp.addRows(_dataT);
              dataChartPA.addRows(_dataPA);
              dataBarTemp.addRows(_dataBarTemp);
              
              // Efface les anciennes valeurs - Erase old data
              var nbRec = dataChartTemp.getNumberOfRows() - json.timestamp.length;
              if ( dataChartTemp.getNumberOfRows() > json.timestamp.length ) {
                dataChartTemp.removeRows(0, nbRec );
                dataChartPA.removeRows(0, nbRec );
              }
              nbRec = dataBarTemp.getNumberOfRows() - json.bart.length;
              if ( dataBarTemp.getNumberOfRows() > json.bart.length ) {
                dataBarTemp.removeRows(0, nbRec );
              }
              // Masque ou affiche l'histogramme - hide or sho bar graph
              if ( dataBarTemp.getNumberOfRows() == 0 ) {
                $("#zeroDataTemp").show();
                $("#barTemp").hide();
              } else {
                $("#zeroDataTemp").hide();
                $("#barTemp").show();
              }
              // Affiche les graphiques - display charts
              gaugePA.draw(dataGaugePA,optionsGauge);
              chartTemp.draw(dataChartTemp, options1);
              barTemp.draw(dataBarTemp, options1);
              chartPA.draw(dataChartPA, options2);
            }).fail(function(err){
              console.log("err getJSON graph_temp.json "+JSON.stringify(err));
            });
          }
        }    
      }
               
      $('a[data-toggle=\"tab\"]').on('shown.bs.tab', function (e) {   
        //On supprime tous les timers lorsqu'on change d'onglet
        clearTimeout(Timer_UdpateMesures);  
        tab_pane = $(e.target).attr("href")  
        console.log('activated ' + tab_pane );  
      
        // IE10, Firefox, Chrome, etc.
        if (history.pushState) 
          window.history.pushState(null, null, tab_pane);
        else 
          window.location.hash = tab_pane;
        
        if (tab_pane=='#tab_mesures')  {
          $('#table_mesures').bootstrapTable('refresh',{silent:true, url:'/tabmesures.json'}); 
        }  
      });
      
      // Créé un timer qui actualise les données régulièrement - Create a timer than update data every n secondes
      $('#tab_mesures').on('load-success.bs.table',function (e,data){
        console.log("tab_mesures loaded");
        if ($('.nav-tabs .active > a').attr('href')=='#tab_mesures') {
          Timer_UdpateMesures=setTimeout(function(){
            $('#table_mesures').bootstrapTable('refresh',{silent: true, showLoading: false, url: '/tabmesures.json'});
            updateMesures();
          },10000);
        }                 
      });   
          
      function updateMesures(){
        $.getJSON('/mesures.json', function(data){
          //console.log("Mesures envoyees : " + JSON.stringify(data) + "|" + data.t + "|" + data.h + "|" + data.pa) ;
          $('#temperature').html(data.t);
          $('#humidite').html(data.h);
          $('#pa').html(data.pa); 
        }).fail(function(err){
          console.log("err getJSON mesures.json "+JSON.stringify(err));
        });
      };
      
      function labelFormatter(value, row){
        var label = "";
        if ( value === "Température" ) {
          label = value + "<span class='glyphicon " + row.glyph + " pull-left'></span>";
          $("#labelTemp").html("&nbsp;" + value + "&nbsp;" + "<span class='badge'> " + row.valeur + row.unite + "</span><span class='glyphicon " + row.glyph + " pull-left'></span>");
        } else if ( value === "Humidité" ) {
          label = value + "<span class='glyphicon " + row.glyph + " pull-left'></span>";
          $("#labelHumi").html("&nbsp;" + value + "&nbsp;" + "<span class='badge'> " + row.valeur + row.unite + "</span><span class='glyphicon " + row.glyph + " pull-left'></span>");
        } else if ( value === "Pression Atmosphérique" ) {
          label = value + "<span class='glyphicon " + row.glyph + " pull-left'></span>";
          $("#labelPa").html("&nbsp;" + value + "&nbsp;" + "<span class='badge'> " + row.valeur + row.unite + "</span><span class='glyphicon " + row.glyph + " pull-left'></span>");
        } else {
          label = value;
        } 
        return label;
      }
      function valueFormatter(value, row){
        //console.log("valueFormatter");
        var label = "";
        if ( row.valeur > row.precedente ) {
          label = value + row.unite + "<span class='glyphicon glyphicon-chevron-up pull-right'></span>";
        } else { 
          label = value + row.unite + "<span class='glyphicon glyphicon-chevron-down pull-right'></span>";
        }
        return label;
      }
      function vpFormatter(value, row){
        //console.log("valueFormatter");
        var label = "";
        if ( row.valeur > row.precedente ) {
          label = value + row.unite
        } else { 
          label = value + row.unite
        }
        return label;
      }  
      
      // Commandes sur le GPIO - GPIO change
      $('#D5_On').click(function(){ setBouton('D5','1'); });
      $('#D5_Off').click(function(){ setBouton('D5','0'); });
      $('#D6_On').click(function(){ setBouton('D6','1'); });
      $('#D6_Off').click(function(){ setBouton('D6','0'); });
      $('#D7_On').click(function(){ setBouton('D7','1'); });
      $('#D7_Off').click(function(){ setBouton('D7','0'); });
      $('#D8_On').click(function(){ setBouton('D8','1'); });
      $('#D8_Off').click(function(){ setBouton('D8','0'); });
      
      function setBouton(id, etat){
        $.post("gpio?id=" + id + "&etat=" + etat).done(function(data){
          //console.log("Retour setBouton " + JSON.stringify(data)); 
          var id_gpio = "#" + id + "_etat";
          //console.log(data);
          if ( data.success === "1" | data.success === 1 ) {
            if ( data.etat === "1" ) {
              $(id_gpio).html("ON");
            } else {
              $(id_gpio).html("OFF");
            }  
          } else {
            $(id_gpio).html('!');
          }      
        }).fail(function(err){
          console.log("err setButton " + JSON.stringify(err));
        });
      } 
      
      // Changement du theme - 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;
        console.log("Recharge le theme " + theme);
        if (theme) {
          set_theme(get_themeUrl(theme));
        }
      }
      
      // Nouveau theme sélectionne - New theme selected
      jQuery(function($){
        $('body').on('click', '.change-style-menu-item', function() {
          var theme_name = $(this).attr('rel');
          console.log("Change 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&egrave;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;
        }
      }
    </script>
  </body>
</html>

Accéder rapidement aux autres parties du projet

Voici les liens pour accéder aux autres parties du projet

A LIRE AUSSI :
Projet station météo ESP8266 (Partie 1). Créer l'interface HTML, stockage SPIFFS
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 2). Piloter le code Arduino depuis l'interface HTML
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 3). Récupérer l'heure avec NTPClient et stockage SPIFFS
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 4). ArduinoJson, charger, enregistrer des fichiers (SPIFFS)
A LIRE AUSSI :
Projet station météo ESP8266 (Partie 5). Afficher des jauges et graphiques Google Charts
Avez-vous aimé cet article ?
[Total: 0 Moyenne: 0]
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Vous avez aimé ce projet ? Ne manquez plus aucun projet en vous abonnant à notre lettre d’information hebdomadaire!

quel modèle esp8266 choisir
Quel modèle d'ESP8266EX choisir en 2020 ?
guide choix esp32 development board
Quel ESP32 choisir en 2020 ?

Vous rencontrez un problème avec ce sujet ?

Peut-être que quelqu’un a déjà trouvé la solution, visitez le forum avant de poser votre question

Nous serions ravis de connaître votre avis

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Domotique et objets connectés à faire soi-même