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 :

AsyncWebserver POST FormData - Ne fonctionne pas [Arduino ESP32]


Sujet :

Arduino

  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 AsyncWebserver POST FormData - Ne fonctionne pas
    Re-Bonjour à tous.
    Je reviens avec la même question que pour mon fil précédent mais avec une maquette simplifiée au maximun et une visue sur la console du PC, ce qui devrait facilité les analyses. Autant vous dire que ça ne fonctionne toujours pas. J'ai l'impression que je suis un pionnier dans cette affaire.
    En passant, je n'ai pas remis ElegantOTA car avec les nouvelles versions d' EspWebServer, la compile se plante (à cause d'un pb avec RP2040 et Rasperry). J'ai laissé tombé, trop compliqué.
    Pour mon affaire, voici l'ensemble des écritures chargées dans l'ESP32:
    HTML:
    Code html : 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
    <!DOCTYPE html>
    <html lang="fr">
        <head>
            <meta charset="utf-8">
            <title>Essai serveur Ayncchrone</title>
            <link rel="icon" href="data:,">
            <link href="style.css" rel="stylesheet" type="text/css" />
            <script src="code.js" async></script>
        </head>
        <body>
            <h1>Essai simple FormData</h1>
            <form id="formulaire">
                <label for="p">premier</label>
                <input id="p" type="number" name="premier"  value="1234"/>
                <br><br>
                <label for="s">second</label>
                <input id="s" type="number" name="second"  value="2345"/>
                <br><br>
                <label for="t">troisième</label>
                <input id="t" type="number" name="troisième"  value="3456"/>
                <br><br>
                <label for="q">quatrième</label>
                <input id="q" type="number" name="quatrième"  value="4567"/>
                <br><br>
            </form>
            <button id="on">On</button>
        </body>
    </html>
    CSS:
    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    html{
        font-family: Arial, Helvetica, sans-serif;
        display: inline-block;
        text-align: center;
    }
    h1{
        color: blueviolet;
        padding: 4px 4px 1px 4px;
    }
    input{
        text-align: center;
    }
    Javascript:
    Code javascript : 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
    document.querySelector("#on").addEventListener("click",function(x){
        let bouton = x.target.innerHTML;
        if(bouton="On"){
          prgServeur('/envoiFormData');
        }
    });
     
    //************************envoi de la saisie**********************************************
    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'},  //'text/plain'
            body: formData          //"Bonjour, comment allez-vous?""
        })
            .then(response => response.ok ? response.text() : Promise.reject("Reponse non valide"))
            .then(data => alert("Reponse: ", data))
            .catch(error => alert("Erreur1: " , error));   
    }
    Main.cpp:
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    /*********************************************************************************
    ***********Maquette d'essai ESP32 en serveur Web - librairie ESPAsyncWebServer****
    ***********
    **************************************version 1.00 Michel MORICE novembre 2024****/
    #include <Arduino.h>
    #include <FS.h>
    #include <SPIFFS.h>
    #include <WiFi.h>
    #include <ESPAsyncWebServer.h>
    #include <AsyncTCP.h>
    #include "maBox.h"
    //#include <ElegantOTA.h>
     
    #define FORMAT_SPIFFS_IF_FAILED false
    #define HTTP_PORT 80 
     
    const char* SSID = SECRET_SSID;
    const char* PASS = SECRET_PASS;
    const char* DIR_HTML = "/index.html";     //page client
    const char* DIR_CSS  = "/style.css";      //mise en forme page client
    const char* DIR_JS   = "/code.js";        //code Javascript page client
     
    bool bodyPret=false;
    const size_t tailleMaxBody = 250;
    char bufBody[tailleMaxBody];
     
    //***************variables globales***********************
     
    String pageHTML = "", pageCSS="", pageJS="";
     
    //****************instantiations***********************
    AsyncWebServer serveur(HTTP_PORT);
     
    //*************** Chargement des pages annexes du serveur ************************
    void lectureData(const char* path){
      File fic = SPIFFS.open(path);
      if(!fic || fic.isDirectory()){
        Serial.println("Erreur ouverture fichier");
        return;
      }
      if(strcmp(path,DIR_HTML)==0){     //****client
        while(fic.available()) {pageHTML += char(fic.read());}
      }
      else if(strcmp(path,DIR_CSS)==0){
        while(fic.available()) {pageCSS += char(fic.read());}
      }
      else if(strcmp(path,DIR_JS)==0){
        while(fic.available()) {pageJS += char(fic.read());}
      }
      fic.close();
    }
    //****Gestion de la réception des POST******************
    void gestionReception(AsyncWebServerRequest *req, uint8_t *data, size_t len, size_t index, size_t total) {
      Serial.println("Debut analyse");
      if(index==0){
        bodyPret = false;
      }
      if(total >=tailleMaxBody)
        Serial.println("body too big");
      else{
        memcpy(bufBody + index,data,len);
        if(index + len >= total){
          bufBody[total] = '\0';
          bodyPret=true;
        }
      }
    }
    //****Analyse de la réception du POST de la programmation des capteurs**************
    void analyseReceptFormData(AsyncWebServerRequest *req){
      if(bodyPret){
        req->send(200,"Content-type: text/plain", "Ok");
        int nbParams = req->params();
        for(uint8_t i=0;i<nbParams;i++){
          const AsyncWebParameter* p = req->getParam(i);
          printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
        } 
      }    
      else  req->send(413,"Content-type: text/plain", "NOk");
    }
     
    //********************initialisation du SPIFFS***************************************
    void initSPIFFS(){
      if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
        Serial.println("SPIFFS Mount Failed");
      }
      else{
        lectureData(DIR_HTML);
        lectureData(DIR_CSS);
        lectureData(DIR_JS);
      }
    }
    //********************initialisation du serveur**************************************
    void initServeur(){
      serveur.on("/essaiFormData", HTTP_GET, [](AsyncWebServerRequest *req){
        req->send(200,"text/html", pageHTML);
      });
     
      serveur.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *req){
        req->send(200, "text/css", pageCSS);
      });
     
      serveur.on("/code.js", HTTP_GET, [](AsyncWebServerRequest *req){
        req->send(200, "application/javascript", pageJS);
      });
      serveur.on("/envoiFormData", HTTP_POST, analyseReceptFormData, nullptr, gestionReception);
     
      //ElegantOTA.begin(&serveur);
     
      serveur.begin();
    }
     
    //***************Evenements WIFI*********************************
    void connexion_BOX(WiFiEvent_t event, WiFiEventInfo_t info){
      Serial.println("connexion WiFi");
    }
    void obtention_IP(WiFiEvent_t event, WiFiEventInfo_t info){
      Serial.print("Adresse IP: "); Serial.println(WiFi.localIP());
    }
    void deconnexion_BOX(WiFiEvent_t event, WiFiEventInfo_t info){
      WiFi.begin(SSID,PASS);
    }
    //********************initialisation WiFi*********************************
    void initWiFi(){
      WiFi.mode(WIFI_STA);
      WiFi.onEvent(connexion_BOX,ARDUINO_EVENT_WIFI_STA_CONNECTED);       //attend une connexion wifi
      WiFi.onEvent(obtention_IP, ARDUINO_EVENT_WIFI_STA_GOT_IP);          //attend l'obtention d'adresse IP
      WiFi.onEvent(deconnexion_BOX, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);     //si une déconnexion survient
      WiFi.begin(SSID, PASS);
      while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
      }
    }
    //******************** paramétrage initial *********************************************************
    void setup() {
      Serial.begin(9600);
      initWiFi();
      delay(200);  
      initSPIFFS();
      delay(200);
      initServeur();                                           
    }
    //***************** boucle principale **************************************************************
    void loop() {
      //ElegantOTA.loop();  
    }
    Comme je développe avec VSCode, platformio.ini:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [env:az-delivery-devkit-v4]
    platform = espressif32
    board = az-delivery-devkit-v4
    framework = arduino
    upload_protocol = esptool
    board_build.partitions = min_spiffs.csv
    ;build_flags = -D ELEGANTOTA_USE_ASYNC_WEBSERVER=1
    lib_deps = 
    	mathieucarbou/ESPAsyncWebServer@3.1.0
        mathieucarbou/Async TCP@^3.1.4
    	;ayushsharma82/ElegantOTA@^3.1.6
    Lorsque je clique sue le bouton d'envoi, j'obtiens le message suivant sur la console Chrome du client:
    code.js:15 Fetch a fini de se charger : POST "http://192.168.1.34/envoiFormData".
    
    Mais aucun message sur la console du PC, mis à part :connexion WiFi et Adresse IP:192.......

    Si je modifie le body côté client pour envoyer un simple texte, le message console:
    code.js:15 Fetch a fini de se charger : POST "http://192.168.1.34/envoiFormData".
    Mais toujourrs rien côté server.

    En vous remerciant d'avance avoir bien voulu lire jusqu'au bout.

  2. #2
    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
    je lis sur mon tel donc feedback limité mais j'ai vu dans le JS
    je suggère à la place
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        if(bouton==="On"){
    ——————————————
    j'ai vu aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                <input id="t" type="number" name="troisième"  value="3456"/>
                <br><br>
                <label for="q">quatrième</label>
                <input id="q" type="number" name="quatrième"  value="4567"/>
    je me demande si les accents (ça devrait passer en UTF8) ne vont pas poser aussi un souci.


    ----

    affichez plus d'info sur la console arduino, par exemple l'état de bodyPret etc

  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 Jay M
    Les accents, c'est une étourderie de ma part. J'ai corrigé.
    Sur la console serveur, il y a un Serial.println("Debut analyse");
    Il ne s'affiche jamais.
    Je viens de mettre un controle du bodyPret, mais si le prmier ne s'affiche pas, il n'y a pas de chance que celui-là vienne!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        if(index + len >= total){
          bufBody[total] = '\0';
          bodyPret=true;
          Serial.println("Body pret");
        }
    Résutat sur la console Chromeclient:
    premier, 1234
    second, 2345
    troisieme, 3456
    quatrieme, 4567


    POST http://192.168.1.34/envoiFormData 413 (Request Entity Too Large)
    prgServeur @ code.js:15
    (anonyme) @ code.js:4
    code.js:15 Échec du chargement de Fetch*: POST "http://192.168.1.34/envoiFormData".
    prgServeur @ code.js:15
    (anonyme) @ code.js:4
    J'ai ajouté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    else{ 
        req->send(413,"Content-type: text/plain", "NOk");
        Serial.println("Body non pret");
      }
    Et en effet le body est non prêt.

  4. #4
    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 Solution trouvée
    Après pas mal d'heures de recherche et un peu d'imagination, pour ceux que cela intéresse de transmettre des données simplement en format FormData (clé/valeur) sans passer par JSON:
    HTML:
    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
    <!DOCTYPE html>
    <html lang="fr">
        <head>
            <meta charset="utf-8">
            <title>Essai serveur Ayncchrone</title>
            <link rel="icon" href="data:,">
            <link href="style.css" rel="stylesheet" type="text/css" />
            <script src="code.js" async></script>
        </head>
        <body>
            <h1>Essai simple FormData</h1>
            <form id="formulaire">
                <label for="p">premier</label>
                <input id="p" type="number" name="premier"  value="1234"/>
                <br><br>
                <label for="s">second</label>
                <input id="s" type="number" name="second"  value="2345"/>
                <br><br>
                <label for="t">troisieme</label>
                <input id="t" type="number" name="troisieme"  value="3456"/>
                <br><br>
                <label for="q">quatrieme</label>
                <input id="q" type="number" name="quatrieme"  value="4567"/>
                <br><br>
                <input type="submit"/>
            </form>
        </body>
    </html>
    Javascript:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //************************envoi de la saisie**********************************************
    formulaire.onsubmit = async (e) => {
        e.preventDefault();
        let response = await fetch('/envoiFormData', {
            method: 'POST',
            body: new FormData(formulaire)
        });
        let result = await response.text();
        alert(result.message);
    };
    main.cpp routine d'analyse du POST:
    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
    //****Analyse de la réception du POST **************
    void analyseReceptFormData(AsyncWebServerRequest *req){
      if(bodyPret){
        int nbParams = req->params();
        for(uint8_t i=0;i<nbParams;i++){
          const AsyncWebParameter* p = req->getParam(i);
          pair[i][0]=p->name().c_str();
          pair[i][1]=p->value().c_str();
          Serial.println(pair[i][0] + " : " + pair[i][1]);
        } 
        req->send(200,"Content-type : text/plain", "Ok");
      } 
      else{ 
        req->send(413,"Content-type: text/plain", "NOk");
        Serial.println("Body non pret");
      }
    }
    Encore plus simple et ça fonctionne très bien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      serveur.on("/envoiFormData", HTTP_POST, [] (AsyncWebServerRequest *req){ 
         int nbParams= req->params();
         for(uint8_t i=0;i<nbParams;i++){
          const AsyncWebParameter* p = req->getParam(i);
          pair[i][0]=p->name().c_str();
          pair[i][1]=p->value().c_str();
          Serial.println(pair[i][0] + " : " + pair[i][1]);
        } 
        req->send(200);
     
      });
    Il suffit ensuite d'adapter à ses besoins.

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

Discussions similaires

  1. post-save ne fonctionne pas
    Par azaazz dans le forum Django
    Réponses: 0
    Dernier message: 28/05/2021, 15h03
  2. [MySQL] Post comment ne fonctionne pas
    Par Elztx dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 30/09/2019, 14h49
  3. [Hook] Post-commit ne fonctionne pas
    Par lyrix dans le forum Subversion
    Réponses: 0
    Dernier message: 10/03/2009, 20h55
  4. FTP poste client ne fonctionne pas
    Par gifffftane dans le forum Windows XP
    Réponses: 0
    Dernier message: 30/05/2008, 09h34
  5. Script JSP qui ne fonctionne pas sur n'importe quel poste
    Par vannary dans le forum Servlets/JSP
    Réponses: 15
    Dernier message: 18/12/2006, 11h56

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