Envoi d'un fichier stocké sur une carte SD depuis un esp32

Bonjour,

J'utilise une carte ESP32 qui me permet de faire de l’acquisition de données (capteur de force) et d'afficher les informations sur une page web. Pour mes besoins, je fais une acquisition à environ 80 Hz (80 points par secondes) . Les données sont stockées sur une carte SD. J'ai choisi une carte SD externe car le fichier peut devenir volumineux (1 minute de mesures représente plus de 52'000 caractères. Je n'ai pas de problème pour écrire les données mais si je veux lire les données cela se complique... Aujourd'hui j'utilise le code suivant:

  // ---  Envoi du graph en JSON (GET) ---//
  server.on("/requestGraph", HTTP_GET, [](AsyncWebServerRequest *request) {
    File file;
    String buffer = "";
    file = SD.open(fileName);
    while (file.available()) {
      buffer += file.readStringUntil('\n');
    }
    file.close();
    String json = "{\"graph\":\"" + buffer + "\"}";
    SD.remove(fileName);
    fileName = "";
    request->send(200, "application/json", json);
  });

Je récupère le json en javascript pour afficher un graphique et permettre à l'utilisateur d'enregistrer les données.

Le problème, passé 25 secondes de mesure l'esp32 plante car la string "buffer" devient trop grande... Ma technique n'est donc pas adaptée. Je pensais à envoyer le fichier de la carte SD sur la page web mais je bloque. Je ne trouve pas d'exemple... Avez vous des pistes?

utilisez vous ESPAsyncWebServer ?

Bonjour,

Oui j’utilise ESPAsyncWebServer.

la bibliothèque sait envoyer directement le contenu d'un fichier

jetez un oeil sur cet exemple (le premier que google m'a donné, j'ai pas testé) pour voir comment ils font

J'imagine que cette ligne correspond à la lecture d'une ligne du fichier. Ne serait il pas plus simple d'envoyer le contenu ligne par ligne?
Tu envoies d'abord l'entête 'graph' puis chaque ligne et l'accolade de fin.

Merci pour cette recherche! J'ai aussi cherché mais je n'ai pas trouvé ces informations. Concernant le premier lien, j'utilise cette méthode pour mes pages web et mes fichier css et javascript mais cela fonctionne avec SPIFFS (mémoire de l'esp32). Le deuxième semble être une bibliothèque qui copie ce que fait SPIFFS mais pour une carte SD externe. Une très bonne piste que je vais étudier.

Concernant la lecture du fichier les informations sont mises les une après les autres donc le fichier est lu en une fois! Je peux changer avec du ligne par ligne mais cela risque d'être très long. Pour une minute j'ai environ 4800 lignes que je dois envoyer et traiter. La vitesse avec le navigateur pour traiter une requête varie mais est environ de 0.05 seconde ce qui va faire 240 secondes... C'est très long. Je me trompe peut être dans la vitesse du navigateur mais je pense que ce n'est pas trop loin...

Un grand merci J-M-L!

J'ai un peu cherché suite à votre message et je suis tombé sur cette information:

Cela m'a permis de constater que je peux utiliser autre chose que le SPIFFS. Mon code de test:

  server.on("/test", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SD, "/test.txt", "text/plain");
  });

Et cela fonctionne!!! Je mets 192.168.1.250/test et le contenu de mon fichier test.txt (qui est sur ma carte SD) est affiché sur ma page! Donc il me reste plus que de trouver comment traiter ce fichier avec javascript!

Oui la bibliothèque offre plusieurs prototype pour la signature de send

void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback)
void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback)
void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback)

donc vous pouvez passer un file system (SD) et un chemin etc...

Je vous donne ma solution qui sera peut être utile à une autre personne!

J'ai créé une fonction qui me permet de créer la première partie de mon json dans un fichier .txt (filename):

void storeJsonHeaderToSDCard(fs::FS &fs) {
  File file;
  file = fs.open(fileName, FILE_APPEND);
  file.print("{\"UnNomLibre\":\"");
  file.close();
}

Remplacer un nom libre par le nom désiré.

J’ appels cette fonction au lancement de ma mesure:

storeJsonHeaderToSDCard(SD);

J'écris dans mon fichier les données voulues

Ensuite je crée une fonction de fermeture de mon JSON:

void storeJsonFooterToSDCard(fs::FS &fs) {
  File file;
  file = fs.open(fileName, FILE_APPEND);
  file.print("\"}");
  file.close();
}

J’ appels cette fonction à la fin de ma mesure:

storeJsonFooterToSDCard(SD);

Ensuite on fait l'envoi du fichier:

  server.on("/requestGraph", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SD, fileName, "text/plain");
  });

Et côté javascript il suffit de récupérer le JSON et de le traiter!

Merci de m'avoir mis sur la piste!

bravo :wink:

bonne continuation