ESP8266. Lire, écrire, modifier des fichiers SPIFFS avec la librairie FS.h • Domotique et objets connectés à faire soi-même

SPIFFS (Serial Peripheral Interface Flash File System) est un système de fichiers léger adapté (entre autre) aux micro-contrôleurs disposant d’une mémoire flash SPI tel que l’ESP8266. SPIFFS vous permet d’accéder à la mémoire flash comme s’il s’agissait d’un système de fichiers normal comme celui d’un ordinateur (en bien plus simple évidemment). On pourra lire, écrire et ajouter des données à un fichier et réaliser quelques opérations simples (formater, renommer, récupérer des informations…)

Présentation du système de fichier SPIFFS (SPI Flash File System)

SPIFFS (pour Serial Peripheral Interface Flash File System) est un système de fichier développé par Peter Andersson (page du projet sur GitHub) qui peut fonctionner sur n’importe quel mémoire flash NOR ou flash SPI.

La librairie développée pour les modules ESP8266 reprend l’essentiel des fonctionnalités avec quelques limitations supplémentaires du fait des limitations des micro-contrôleurs :

  • Arborescence il n’y a pas d’arborescence de fichier. Les fichiers sont placés à plat dans la zone de fichier. A la place, il est possible d’utiliser le caractère “\” dans le nom de fichier pour créer une pseudo arborescence.
  • Nom de fichier limité à 31 caractères utiles c’est la seconde limitation importante. Le caractère ‘\0’ est réservé et automatiquement ajouté à la fin du nom de fichier pour la compatibilité avec les chaînes de caractère du langage C. Attention, l’extension de fichier consomme en général 4 caractères sur les 31 utiles.
  • Pas de message d’alerte en cas d’erreur aucun message d’erreur n’apparaîtra à la compilation ou à l’exécution si la limites de 32 caractères est dépassée. Si le programme ne fonctionne pas comme prévu, pensez à vérifier le nom de fichier.

Autres limitations utiles à connaître :

  • Il ne faut pas utiliser d’espace(s) ou de caractère(s) accentué(s) dans le nom de fichier
  • Il n’y a pas de file d’attente
  • Le temps d’écriture est variable d’un fichier à l’autre
  • SPIFFS est destiné aux petits périphériques à mémoire flash, ne dépassez pas 128 Mo de stockage
  • Il n’y a pas de mécanisme de détection de blocs défectueux

Découverte de la librairie FS.h, API et méthodes disponibles

La librairie FS.h est installée en même temps que le SDK ESP8266. Toutes les méthodes proposées par la librairie FS.h sont très bien documentées ici.

Pour accéder au système de fichier, il suffit de la déclarer au début du croquis

#include "FS.h"

Comment formatter un nom (chemin) de fichier ?

SPIFFS ne gère pas l’arborescence.

On pourra toutefois créer une pseudo arborescence en utilisant le caractère “/” dans le nom de fichier sans dépasser la limite de 31 caractères utiles.

Le chemin de fichier doit toujours commencer par le caractère “/”, par exemple /fichier.txt

Les méthodes (API) de la librairie FS.h

SPIFFS.begin()

Cette méthode monte le système de fichiers SPIFFS et doit être appelée avant que n’importe quelle autre méthode FS ne soit utilisée. Renvoie true si le système de fichiers a été monté avec succès.

Il est conseillé de monter le système de fichier dans le setup

void setup() { 
  // Launch SPIFFS file system | Démarre le système de fichier SPIFFS 
  if(!SPIFFS.begin()){ 
    Serial.println("An Error has occurred while mounting SPIFFS");  
  }
}

SPIFFS.format()

Formate le système de fichier. Renvoie true si le formatage a réussi. Attention, si des fichiers sont présents dans la zone mémoire, ils seront supprimés de façon irréversible.

SPIFFS.open(path, option)

Ouvre un fichier

path doit être un chemin absolu commençant par une barre oblique (par exemple /dir/nom_fichier.txt).

option est une chaîne spécifiant le mode d’accès. Il peut s’agir de

  • “r” read, lecture seule
  • “r+” lecture et écriture. Le pointeur est positionné au début du fichier
  • “w” write, écriture. Le contenu existant est supprimé. Le fichier est créé s’il n’existe pas
  • “w+” ouvre le fichier en lecture et à l’écriture. Le fichier est créé s’il n’existe pas, sinon il est tronqué. Le pointeur est positionné au début du fichier
  • “a” append, ouvre un fichier en ajout de données. Le fichier est créé s’il n’existe pas. Le pointeur est positionné à la fin du fichier s’il existe déjà
  • “a+” append, ouvre un fichier en ajout de données. Le fichier est créé s’il n’existe pas. La pointeur est positionné au début du fichier en lecture et à la fin du fichier pour l’écriture (ajout)

Renvoie l’objet File. Pour vérifier si le fichier a été ouvert avec succès, utilisez l’opérateur booléen.

Une fois que le fichier est ouvert, voici les méthodes qui permettent de le manipuler

file.seek(décalage, mode)

Cette fonction se comporte comme la fonction fseek du langage C. En fonction de la valeur de mode, le pointeur est positionné dans le fichier comme ceci

SeekSet la position est définie pour décaler les octets par rapport au début
SeekCur la position actuelle est déplacée par octets de décalage
SeekEnd la position est définie pour décaler les octets à partir de la fin du fichier

La fonction renvoie true si la position a été définie avec succès

file.position()

Renvoie la position actuelle dans le fichier en octets.

file.size()

Renvoie la taille du fichier en octets.

file.name()

Renvoie le nom du fichier dans une constante au format const char *.

file.close()

Ferme le fichier

SPIFFS.exists(chemin)

Renvoie true si un fichier avec un chemin donné existe, false dans le cas contraire.

SPIFFS.openDir(chemin)

Ouvre un répertoire en fonction de son chemin absolu. Renvoie un objet Dir.

SPIFFS.remove(chemin)

Supprime le fichier en fonction de son chemin absolu. Renvoie vrai si le fichier a été supprimé avec succès.

SPIFFS.rename(pathFrom, pathTo)

Renomme le fichier de pathFrom à pathTo. Les chemins doivent être absolus. Renvoie true si le fichier a été renommé avec succès.

SPIFFS.info(fs_info)

Remplit la structure FSInfo avec des informations sur le système de fichiers. Renvoie vrai en cas de succès.

SPIFFS.end()

Démonte le système de fichier

Comment transférer des fichiers dans la zone mémoire SPIFFS ?

Il est possible de téléverser directement des fichiers dans le système de fichier SPIFFS à l’aide du plugin pour l’IDE Arduino ESP8266 Sketch Data Upload.

Pour cela, il suffit de créer un dossier nommé data au même niveau que le fichier principal du projet Arduino. Il est préférable d’éviter de créer des sous-dossiers.

En effet, le système de fichier SPIFFS ne gère pas l’arborescence de fichier. Lors du transfert, les fichiers seront mis “à plat”, c’est à dire que le fichier prendra comme nom le chemin d’accès.

Pour en savoir plus, lisez ce tutoriel qui explique tout en détail.

Récupérer les informations de la zone SPIFFS et la liste des fichiers

Voici un petit exemple de code qui permet de récupérer les informations de la zone mémoire ainsi que la liste des fichiers présents dans la zone mémoire.

#include "FS.h"
 
void setup()
{
    Serial.begin(112500);
 
    delay(500);
 
    Serial.println(F("Initializing FS..."));
    if (SPIFFS.begin()){
        Serial.println(F("SPIFFS system mounted with success"));
    }else{
        Serial.println(F("An Error has occurred while mounting SPIFFS"));
    }
 
    // Get all information about SPIFFS
    FSInfo fsInfo;
    SPIFFS.info(fsInfo);
    
    Serial.println("File system info");
    
    // Taille de la zone de fichier
    Serial.print("Total space:      ");
    Serial.print(fsInfo.totalBytes);
    Serial.println("byte");
    
    // Espace total utilise
    Serial.print("Total space used: ");
    Serial.print(fsInfo.usedBytes);
    Serial.println("byte");
 
    // Taille d un bloc et page
    Serial.print("Block size:       ");
    Serial.print(fsInfo.blockSize);
    Serial.println("byte");
 
    Serial.print("Page size:        ");
    Serial.print(fsInfo.totalBytes);
    Serial.println("byte");
 
    Serial.print("Max open files:   ");
    Serial.println(fsInfo.maxOpenFiles);
 
    // Taille max. d un chemin
    Serial.print("Max path lenght:  ");
    Serial.println(fsInfo.maxPathLength);
 
    Serial.println();
 
    // Open folder
    Dir dir = SPIFFS.openDir("/");
    // Affiche le contenu du dossier racine | Print dir the content
    while (dir.next()) {
        // recupere le nom du fichier | get filename
        Serial.print(dir.fileName());
        Serial.print(" - ");
        // et sa taille | and the size
        if(dir.fileSize()) {
            File f = dir.openFile("r");
            Serial.println(f.size());
            f.close();
        }else{
            Serial.println("file is empty");
        }
    }
}
 
void loop(){
 
}

Comment écrire dans un fichier par programmation avec FS.h

On a vu comment créer un fichier depuis un ordinateur puis le téléverser depuis l’IDE Arduino.

La librairie fs.h met à disposition plusieurs méthodes simples pour accéder et manipuler les fichiers depuis un programme Arduino. Toutes les méthodes sont détaillées sur la documentation officielle du SDK ESP8266.

Ajouter ce code juste après le ligne file.close();

file = SPIFFS.open("/test.txt", "w");
  if(!file){
    // File not found | le fichier de test n'existe pas
    Serial.println("Failed to open test file");
    return;
  } else {
    file.println("Hello From ESP8266 :-)");
    file.close();
  }

Que fait ce code ?

Cette fois, on ouvre le fichier avec l’option “w” pour indiquer qu’on souhaite modifier le fichier. Le contenu précédent sera effacé

Pour écrire dans un fichier, on peut utiliser les méthodes print() ou println(). La méthode println() ajoute un retour à la ligne. On l’utilisera pour créer un tableau de données par exemple.

Ici, on actualise le contenu précédent

file.println("Hello From ESP8266 :-)");

Téléverser pour visualiser ce qui se passe

Comment ajouter des données à un fichier par programmation ?

Pour ajouter des données à un fichier, il suffit d’ouvrir de fichier avec l’option “a” (append) pour ajouter des données à la fin du fichier.

Si le fichier n’existe pas, il sera automatiquement créé.

Voici un petit exemple qui enregistre un compteur chaque seconde.

void loop(){
  File file = SPIFFS.open("/counter.txt", "a");
  if(!file){
    // File not found | le fichier n'existe pas
    Serial.println("Failed to open counter file");
    return;
  } else {
    counter+=1;
    file.println(counter);
    file.close();
  }
  delay(1000);
}

Mises à jour

11/08/2020 Première publication de l’article

Avez-vous aimé cet article ?

[Total: 2 Moyenne: 3.5]