IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

AsyncWebServerRequest Récupération des données FormData (clé/valeur) [Arduino ESP32]


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut AsyncWebServerRequest Récupération des données FormData (clé/valeur)
    Bonjour à tous
    Mon client renvoit les données d'un formulaire de saisie par cette routine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    prgServeur("/CapteurPost");
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function prgServeur(url) {
        fetch(url, {
            method: 'POST',
            headers: {'Content-Type' : 'multipart/form-data'},
            body: new FormData(document.getElementById('formulaire'))
         })
            .then(response => response.ok ? response.text() : Promise.reject("Reponse non valide"))
            .then(data => console.log("Reponse: ", data))
            .catch(error => alert("Erreur1: " , error))
    }
    Quelle méthode dois-je utiliser pour récupérer mes données côté serveur ESP32?

  2. #2
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 122
    Billets dans le blog
    47
    Par défaut
    Salut,

    Tu as dû déjà le faire il me semble, avec un écouteur sur l'url :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    server.on("/CapteurPost", HTTP_POST, [](AsyncWebServerRequest *request){
     
      // traitement des données en paramètre
     
      });

  3. #3
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    bonjour, merci pour ton aide,
    oui j'ai déjà traité un post mais c'était avec un flux de données à la queue leuleu.
    Là c'est un FormData (clé/valeur, style JSON) et je ne sais pas comment récupérer les éléments.

  4. #4
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 122
    Billets dans le blog
    47
    Par défaut
    La bibliothèque arduinoJson est pas mal pour traiter du json.

  5. #5
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    merci mais ce n'est pas un fichier JSON que j'envoie; c'est un FormData constitué de paires 'name' / 'value' d'éléments HTML.
    Il y a des quantités d'infos sur la façon de créer cette entité FormData du côté client, mais rien du côté serveur: comment retrouver mes paires de données?
    Une méthode précédemment concluante avec un flux de données renvoie "Erreur1" systématiquement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    serveur.on("/CapteurPost", HTTP_POST, reponseCaptRecep, nullptr, gestionReception);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //****Gestion de la réception des POST******************
    void gestionReception(AsyncWebServerRequest *req, uint8_t *data, size_t len, size_t index, size_t total) {
      afficInfo(MSG15);
      if(index==0){
        bodyPret = false;
      }
      if(total >=tailleMaxBody) afficErreurs(MSG14);    //body too big
      else{
        memcpy(bufBody + index,data,len);
        if(index + len >= total){
          bufBody[total] = '\0';
          bodyPret=true;
        }
      }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //****Analyse de la réception du POST de la programmation des capteurs**************
    void reponseCaptRecep(AsyncWebServerRequest *req) {
      if(bodyPret){
        afficInfo(MSG15);
        int nbParams = req->params();
        for(i=0;i<nbParams;i++){
          const AsyncWebParameter* p = req->getParam(i);
          sprintf(bufBody,"POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
          afficInfo(bufBody);
        } 
        req->send(200,"Content-type: text/plain", "Ok");
      }    
      else  req->send(413,"Content-type: text/plain", "NOk");
    Le premier affichage MSG15 de la gestionReception() ne s'affiche jamais.
    J'ai légèrement modifié le POST côté client ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //************************envoi de la saisie**********************************************
    function prgServeur(url) {
        const formData = new FormData(document.querySelector('#formulaire'))
        fetch(url, {
            method: 'POST',
            body: formData
        })
            .then(response => response.ok ? response.text() : Promise.reject("Reponse non valide"))
            .then(data => console.log("Reponse: ", data))
            .catch(error => alert("Erreur1: " , error));   
    }
    Mais cela n'a rien changé.

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 884
    Par défaut
    regardez la doc sur "get-post-and-file-parameters"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    //List all parameters
    int params = request->params();
    for(int i=0;i<params;i++){
      AsyncWebParameter* p = request->getParam(i);
      if(p->isFile()){ //p->isPost() is also true
        Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
      } else if(p->isPost()){
        Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
      } else {
        Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
      }
    }
     
    //Check if GET parameter exists
    if(request->hasParam("download"))
      AsyncWebParameter* p = request->getParam("download");
     
    //Check if POST (but not File) parameter exists
    if(request->hasParam("download", true))
      AsyncWebParameter* p = request->getParam("download", true);
     
    //Check if FILE was uploaded
    if(request->hasParam("download", true, true))
      AsyncWebParameter* p = request->getParam("download", true, true);
     
    //List all parameters (Compatibility)
    int args = request->args();
    for(int i=0;i<args;i++){
      Serial.printf("ARG[%s]: %s\n", request->argName(i).c_str(), request->arg(i).c_str());
    }
     
    //Check if parameter exists (Compatibility)
    if(request->hasArg("download"))
      String arg = request->arg("download");

  7. #7
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Merci Jay M mais cette doc est sur ma table de chevet et je m'en suis inspiré; si vous regardez le fil N°5 c'est exactement ce que j'ai écrit, mis à part le fait que le Serial.printf ne me convient pas et que je l'ai remplacé par un sprintf pour l'afficher sur mon LCD:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void reponseCaptRecep(AsyncWebServerRequest *req) {
      if(bodyPret){
        req->send(200,"Content-type: text/plain", "Ok");
        int nbParams = req->params();
        for(i=0;i<nbParams;i++){
          const AsyncWebParameter* p = req->getParam(i);
          sprintf(bufBody,"POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
          afficInfo(bufBody);
        } 
      }    
      else  req->send(413,"Content-type: text/plain", "NOk");
    }
    Ce que je ne comprends pas, pourquoi le client affiche "Erreur1: " en retour catch du fetch POST.

  8. #8
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 884
    Par défaut
    Pouvez vous afficher la requête reçue ?

  9. #9
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    non je ne peux pas, rien ne s'affiche comme si le body n'était pas prêt.

  10. #10
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 884
    Par défaut
    pouvez vous regarder la console de votre navigateur et faire afficher ce qui est vraiment envoyé ?

  11. #11
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut visualisation des données voulant être envoyées
    Oui en effet ça ne va pas fort.
    Mais pourquoi? Le CORS bloque, mais que faire? cela dépasse mes faibles compétences.

    J'ai modifié pour visualiser les données:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function prgServeur(url) {
        const formData = new FormData(document.querySelector('#formulaire'));
        for(let pair of formData.entries()){
            console.log(pair[0] + ', ' + pair[1]);
        }
        fetch(url, {
     
            method: 'POST',
            headers: {'content_type' : 'multipart/form-data'},
            body: formData
        })
            .then(response => response.ok ? response.text() : Promise.reject("Reponse non valide"))
            .then(data => alert("Reponse: ", data))
            .catch(error => alert("Erreur1: " , error));   
    }
    Ce qui donne sur la console de Chrome:

    Nom : ConsoleLog.JPG
Affichages : 123
Taille : 111,0 Ko
    Images attachées Images attachées  

  12. #12
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Je crois avoir trouver une partie du problème:
    dans le headers je mettais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     headers: {'Content_Type' : 'multipart/form-data'}
    alors que j'aurais du mettre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     headers: {'Content-Type' : 'multipart/form-data'}
    une stupide erreur de tiret!
    Cela ne fonctionne toujours pas mais la situation semble meilleure.
    La console m'indique maintenant:
    Nom : ConsoleLog.JPG
Affichages : 109
Taille : 12,9 Ko

    Donc le serveur reçoit bien le message mais surement parceque bodyPret est false renvoit le code 413.

  13. #13
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Bonjour à mes correspondants
    N'ayant pas trouver de solution fonctionnelle, j'ai modifié l'envoi des données côté client ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function prgServeur(url) {
        const formData = new FormData(document.querySelector('#formulaire'));
        let m='mem'+ ':'+ actionServeur + ';';
        for(let pair of formData.entries()){
            m += pair[0] + ':' + pair[1] + ';';   
        }
        m += 'Z:Z;';
        alert(m);
     
        fetch(url, {       
            method: 'POST',
            headers: {'Content-Type' : 'text/plain' },  //'multipart/form-data'
            body: "m"
        })
            .then(response => response.ok ? response.text() : Promise.reject("Reponse non valide"))
            .then(data => alert("Reponse: ", data))
            .catch(error => alert("Erreur1: " , error));   
    }
    Comme vous pouvez le remarquer, pour envoyer en text/plain, j'ai formaté les données en séparant les paires par un ';' et séparé clé/valeur par ':' afin de "faciliter" le décodage côté serveur.
    Et comme à l'habitude, ça coince.
    Côté serveur(ESP32] ma routine de décodage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void analyseCaptRecep(AsyncWebServerRequest *req){
      if(bodyPret){
        afficInfo(MSG15);    //body received 
        char buf[20];   
        req->send(200,"Content-Type: text/plain", "Ok");
        const char * separateurs = ":;";
        char *mot = strtok(bufBody, separateurs);
        while(mot != NULL){
          sprintf(buf,"%s",mot);
          afficInfo(buf);
          mot = strtok(NULL,separateurs);
        }
      }   
      else  req->send(413,"Content-type: text/plain", "NOk");    
    }
    Au lieu d'afficher les mots un par un, il n'y a qu'une lettre qui s'affiche ('m') puis l'ESP se plante et se réinitialise.
    C'est peut-être avec la commande C qu'il y a un pb?

  14. #14
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 754
    Par défaut
    Hello,

    1) peux-tu montrer la déclaration de bufBody ?

    2) le sprintf() ligne 9 n'est pas nécessaire, remplace-le par strncpy(buf, mot, sizeof(buf));. De cette manière, tu seras sûr de ne pas dépasser la taille de buf.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 26/07/2018, 11h38
  2. [CR9]Masquer des données (colonnes) suivant valeur champ
    Par neo.51 dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 05/09/2005, 09h43
  3. [CR] Générer des espaces pour une valeur champ
    Par newpress dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 17/02/2005, 17h43
  4. conception : des millions de petites valeurs
    Par crossbow dans le forum Décisions SGBD
    Réponses: 4
    Dernier message: 02/06/2004, 14h21
  5. Réponses: 2
    Dernier message: 22/07/2002, 18h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo