ESP8266 (Web Serveur – Partie 4) : ArduinoJson, charger, enregistrer des fichiers (SPIFFS)

Dans ce 4ème tutoriel consacré à la programmation Web Server des ESP8266, nous allons traiter du stockage des fichiers dans le système de fichier SPIFFS. Nous allons poursuivre le développement de la mini station météo et stocker les mesures dans un objet JSON à l’aide de la librairie ArduinoJson. Il est très facile d’enregistrer un objet JSON sous la forme d’une chaine de caractères dans un fichier texte et le recharger au démarrage de l’ESP8266 pour poursuivre l’acquisition de données.

Installer la librairie ArduinoJson

Il est possible de créer une structure pour gérer les données mais le format JSON (déjà expliqué dans le tutoriel précédent) offre de nombreux avantages. La librairie ArduinoJson développée par Benoît Blanchon est un modèle du genre. Très bien documentée, elle est très simple de mise en oeuvre. Seul bémol, manipuler des objets JSON n’est pas sans conséquences sur le programme Arduino. En effet, l’objet JSON est stocké en mémoire, ce qui limite grandement nos ambitions. Si vous avez besoin de créez un système d’acquisition de données, cette librairie n’est pas la mieux adaptée. Dans le cadre de ce projet, elle est très intéressante car il est très facile de manipuler les données et les envoyer vers l’interface Web (juste en 2 lignes de code !).

Dans un prochain tutoriel, nous verrons comment enregistrer directement des données dans un fichier avec un séparateur (‘,’ par exemple), facilement récupérable sur un tableur (Excel, Libre Office…).

Pour installer la librairie ArduinoJson, allez tout simplement dans le gestionnaire de bibliothèque.

arduinojson esp8266 json charger enregistrer spiffs historique acquisition donnees

Préparation du buffer et de l’objet JSON

Ensuite, on ajoute une déclaration en début de programme

La librairie ArduinoJson est très bien documentée (le wiki sur trouve sur GitHub). Je vous propose un exemple d’utilisation typique dans lequel nous allons réaliser les manipulations suivantes :

  • Création d’un objet JSON
  • Ajout de clés : timestamp, t (température), h (humidité), pa (pression atmosphérique), bart et barh (données classifiées pour construire un histogramme en barre)
  • Exporter et enregistrer le JSON dans la zone SPIFFS
  • Recharger le fichier de données depuis la zone SPIFFS et recréer l’objet JSON correspondant

On commence donc par créer un Buffer qui va contenir l’objet JSON. Il est possible de laisser la librairie changer dynamiquement la taille du buffer, mais les performances en seront affectée. Pour déterminer la taille du buffer, reportez vous à cette page (section Memory Usage). Estimons la taille pour ce projet. On va enregistrer 12 mesures durant 7 heures, soit 84 points par grandeur physique.

  • 4 tableaux de 84 éléments (temps, température, pression atmosphérique) = 4 x ( 8 + 12 x 84 ) = 4064 bytes
  • 2 tableaux de 7 éléments (pour histogramme en barre) = 2 x ( 8 + 12 x 7 ) = 184 bytes

Soit un total de 4248 bytes. Par sécurité, on va arrondir à 4400 bytes. S’il manque un peu de place, tous les points de mesure ne pourront pas être enregistrés.

Maintenant, on créé l’objet JSON root  dans ce buffer

Puis on créé les clés qui vont contenir les tableaux de données.On a le choix entre ajouter un tableau (createNestedArray) ou un objet (createNestedObject). Ici, on ajoute 5 tableaux. La taille des tableaux n’est pas fixée d’avance, à nous à calculer l’espace nécessaire au moment de la création du buffer. S’il n’y a plus de place dans le buffer, il ne sera plus possible d’ajouter des données supplémentaires.

On en profite également pour créer un buffer qui servira aux exportations. Si on doit exporter les données (ce qui est généralement le cas), il faudra donc diviser la mémoire disponible en deux, la première partie pour le JSON, la seconde pour le tampon d’exportation.

Manipuler le JSON : Ajout, modification, suppression de données

Maintenant que l’objet JSON est prêt, on va pouvoir ajouter des points régulièrement. Ici, on va stocker dans le JSON un point toutes les 5 minutes. On dispose de plusieurs fonctions pour manipuler les données dans le JSON :

  • add(data) : ajoute une nouvelle données à la suite. On pousse une nouvelle valeur dans un tableau par exemple.
  • removeAt(index) : on supprime la données à l’index indiqué.
  • set(index,data) : on actualise la données à l’index indiqué.

La fonction addPtToHist suivante permet d’ajouter un point de mesure pour chaque grandeur à intervalle régulier (ici intervalHist = 5000 ms). Le temps est récupéré sur le serveur NTP à l’aide de la méthode NTP.getTime() présentée dans le tutoriel précédent. On limite le nombre de chiffres significatifs pour les nombres décimaux à l’aide de la méthode double_with_n_digits(variable, nombre_chiffre_significatif). 

Enfin, comme on est obligé de limiter le nombre de mesures enregistrées (ici 84 par variable), on doit supprimer la plus ancienne. Pour cela il suffit de tester la taille du tableau, si elle est supérieure à la taille définie, on supprime le premier élément de chaque tableau à l’aide de la méthode removeAt(index). Il est ainsi très facile de mettre en place un buffer tournant.



D’autres fonctions utiles :

  • size(). Retourne la taille d’un tableau (tableau.size())
  • success(). Retourne vrai si un tableau a été correctement parsé (converti d’une chaine en objet JSON) ou alloué

Exporter le JSON et l’enregistrer dans la zone SPIFFS

Vous avez du remarquer l’appel à la fonction saveHistory() dans la fonction précédente. Voyons comment faire pour exporter un objet JSON et l’enregistrer dans un simple fichier texte dans l’espace SPIFFS.

Petits rappels :

  • On appel la librairie FS.h en début de programme
  • 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().

Maintenant, on peut accéder au système de fichier SPIFFS.  Exporter le JSON dans un fichier texte, c’est trois lignes de code avec les librairies ArduinoJson et FS !.

  • On ouvre le fichier avec la méthode SPIFFS.open(nom_fichier, methode). Ici on va accéder au fichier en écriture (w). Si le fichier n’existe pas, il sera créé.
  • La méthode printTo permet de sérialiser (serialize), c’est à dire de transformer l’objet JSON en une chaine de caractère. On indique la sortie de la fonction, ici le fichier ouvert (historyFile).
  • On referme le fichier (close).
  • C’est terminé.

La méthode printTo est très pratique, elle permet donc de sérialiser le JSON et de l’envoyer aussi bien vers un fichier que vers le port série pour la mise au point du programme. Il existe également la variante prettyPrintTo qui permet de rendre plus lisible (pour un humain !) l’objet JSON comme le fait http://jsonlint.com/.

Importer et parser un fichier texte en JSON : recharger l’historique

On va recharger l’historique sauvegardé précédemment au démarrage de l’ESP8266 et poursuivre l’acquisition de données. Pour parser une chaine de caractères en objet JSON, on doit disposer d’un buffer dont la taille correspond à l’objet JSON final. Comme on va recharger l’historique courant, on dispose déjà du buffer root. Inutile d’en créer un nouveau. On ouvre le fichier avec la méthode SPIFFS.open mais cette fois en lecture uniquement (paramètre r). Avant de faire la conversion, il est préférable de tester si le fichier n’est pas vide (file.size()).

On charge le contenu du fichier dans un buffer (source) temporaire (buf). On appel ensuite la méthode jsonBuffer.paseObject en lui passant en paramètre le contenu du buffer (buf.get()).

Attention. Il faudra assez de mémoire pour recharger le JSON.

La méthode success permet de vérifier que l’objet JSON est correct.

Dans le prochain tutoriel nous verrons comment préparer une réponse à partir d’éléments extraits du JSON avant de l’envoyer à l’interface WEB.

Exemples utilisés pour l’écriture de l’article

JSON :  https://github.com/bblanchon/ArduinoJson/wiki
SPIFFS : https://github.com/esp8266/Arduino/issues/1685
SPIFFS : https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/ConfigFile/ConfigFile.ino

Inscrivez-vous à la newsletter hebdomadaire

Aucun spam et aucun autre usage ne sera fait de votre email. Vous pouvez vous désinscrire à tout moment.

Tags:

  • didier

    Bonjour,
    Grace à votre site j’ apprend beaucoup sur l’ESP 8266. un grand merci.
    Sur cette partie du projet, la compilation du code arduino ne se fait pas car il me signale l’erreur suivante:’HISTORY_FILE’ was not declared in this scope. Merci de m’indiquer comment y remédier .