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 :

[ESP32] ESPAsyncWebserver POST - Réceptionner un POST client et extraire les données.


Sujet :

Arduino

Vue hybride

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut [ESP32] ESPAsyncWebserver POST - Réceptionner un POST client et extraire les données.
    Bonjour à tous,
    Un fichier HLML envoyé à un client, permet la saisie de données de type texte.
    A la fin de la saisie, un bouton permet la lecture des données et les stocke dans une variable String (msg), puis envoit le contenu de cette variable vers le serveur par un POST.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let listeBouton = document.querySelectorAll(".bouton");     //tous les boutons de la page
    listeBouton.forEach(function(k){
        k.addEventListener("click", function(f){
            touche = f.target.innerHTML;
            //debut de la saisie
            if(touche=="RAM"){
                lectureSaisie();
                //ecriture en RAM
                prgServeur("/API?Cmd=2AA");
                sauvegardeOk=true;
                //window.close();
            }......
    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){
        fetch(url, {
            method: 'POST',
            headers:{"Content-Type": "Text/Plain"},
            body: msg
        })
            .then(response => response.text())
            .then(response => alert(response))
            .catch(err => console.log(err));
    }
    Mon problème: la réponse est vide et si je consule la console log de chrome, j'ai ces messages:
    Nom : ConsoleLog.JPG
Affichages : 82
Taille : 10,1 Ko
    Donc, tout laisse à penser qu'il y a un problème côté serveur, ce que m'a confirmé NOSMOKING sur le forum Javascript.
    Côté serveur, j'utilise la librairie ESPAsyncWebServer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //****API****
      serveur.on("/API?Cmd=2AA", HTTP_POST, [](AsyncWebServerRequest *req){ 
        req->send(200, "text/plain", "OK");
        String x = req->getHeader(x)->value();
        afficLcd2String(x,"");
        String message = req->getParam(message)->value();
        afficLcd2String(message,"");
        delai('s',5);   
      });
    A vrai dire, je ne suis pas sûr du tout que cette syntaxe soit bonne. Est-ce la bonne façon d'accuser réception? Est-ce la bonne façon de récupérer les données?
    Merci d'un coup de main.

    J'ai trouver mon problème:
    J'utile l'URL "API" pour faire le POST mais je l'utilise aussi pour des GET ce qui doit procurer une incompréhension du serveur.
    J'ai simplement mis "Toto" à la place et cela a fonctionné.
    Désolé pour le dérangement
    Images attachées Images attachées  

  2. #2
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    vous ne pouvez pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     serveur.on("/API?Cmd=2AA"...
    il faut utiliser l'URL de base
    et ensuite vous regardez si vous avez un paramètre Cmd

    cela dit, ce que vous montrez ressemble plus à un GET qu'à un POST

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Bonjour Jay M

    cela dit, ce que vous montrez ressemble plus à un GET qu'à un POST
    Je ne vois pas pourquoi cela n'est pas un POST.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function prgServeur(url) {
        fetch(url, {
            method: 'POST',
            body: msg,
            headers: {"Content-Type": "text/plain"}
        })
            .then(response => response.text())
            .then(response => alert(response))
            .catch(error => alert("Erreur: " + error))
     
    }
    Un GET n'a pas de body.

    Pour appeler la fonction je fais maintenant:
    Et maintenant je reçois bien une réponse du serveur.
    Mais cette réponse n'est pas satisfaisante car je n'arrive pas à récupérer les données envoyées. J'ai msg="Non recues".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    const char* MSG = "message";
    serveur.on("/Toto", HTTP_POST, [](AsyncWebServerRequest *req){
        String msg ="";
        if(req->hasParam(MSG,true)){
          msg=req->getParam(MSG,true)->value();
        }
        else{
          msg="Non recues";
        }
        req->send(200, "text/plain", msg);     
        afficLcd2String("Reception", msg.substring(0,15));     
      });
    La librairie ESPAsyncWebServer est super et on peut remercier l'auteur mais par contre pour arriver à comprendre comment l'utiliser pour un amateur, ça se résume souvent à pomper des exemples ça et là sur le Net sans vraiment comprendre ce que l'on fait. Sur GitHub il y a des quantités d'explications, mais je n'ai pas réussi à y voir quelquechose de clair. Moi je veux simplement envoyer d'un client un message, le récupérer sur le serveur (ESP32) et utiliser le résultat. Comme ce message est long, j'ai pensé que le POST étatit plus approprié.

    Merci Jay M de consacrer tout ce temps.

  4. #4
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Citation Envoyé par mormic Voir le message
    Je ne vois pas pourquoi cela n'est pas un POST.
    si vous passez le paramètre dans l'URL avec /API?Cmd=2AA c'est plutôt le format d'un GET - c'est ce que je voulais dire

    ----------
    essayez avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Content-Type: application/x-www-form-urlencoded
    "text/plain" : est utilisé pour les données textuelles simples sans formatage spécial. Dans ce cas, le corps de la requête est traité comme une simple chaîne de texte.

    "application/x-www-form-urlencoded" : est utilisé pour envoyer des données sous forme de paires clé-valeur, similaires à la manière dont les données sont envoyées via un formulaire HTML.

    Je serai tenté de dire que la méthode hasParam() de AsyncWebServerRequest attend ce format et qu'il sera alors capable de lire le body Cmd=2AA

    à essayer?

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Bonjour Jay M

    Pour faire simple, je veux envoyer une simple chaîne de texte ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function prgServeur(/Toto) {
        fetch(url, {
            method: 'POST',
            body: "Portez ce vieux whisky au juge blond qui fume sa pipe" ,
            headers: {"Content-Type": "text/plain"}
        })
            .then(response => response.text())
            .then(response => alert(response))
            .catch(error => alert("Erreur: " + error))
     
    }
    Et la récupérer sur mon serveur dans une variable x.
    En fin de compte la commande "API?Cmd=2AA" ne me sert a rien. Je l'avais prévu pour pouvoir sélectionner d'autres actions. Je prévois de faire cette sélection dans le corps du message, si un jour j'arrive à le relire côté serveur!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    serveur.on("/Toto", HTTP_POST, [](AsyncWebServerRequest *req){
        String x= req-> ??????????????????       //récupération du texte envoyé par le client
        req->send(200, "text/plain", "OK");     
        afficLcd2String("message reçu",x);     
      });
    Avouez que ce n'est pas clair au niveau de la librairie pour simplement récupérer un texte.

  6. #6
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    OK donc vous voulez récupérer le body d'une requête POST
    dans la doc il y a une section sur https://github.com/me-no-dev/ESPAsyn...-data-handling mais c'est vrai que ce n'est pas assez détaillé

    voici un exemple (mettez le SSID et mot de passe de votre réseau WiFi dans le code là où il y a les xxx)

    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
     
    #include <Arduino.h>
    #ifdef ESP32
    #include <WiFi.h>
    #include <AsyncTCP.h>
    #elif defined(ESP8266)
    #include <ESP8266WiFi.h>
    #include <ESPAsyncTCP.h>
    #endif
    #include <ESPAsyncWebServer.h>
     
    const char*   ssid = "xxx"; // <==== A REMPLIR
    const char*   password = "xxx"; // <==== A REMPLIR
    AsyncWebServer server(80);
     
    const char index_html[] PROGMEM = R"rawliteral(
    <!DOCTYPE html>
    <html lang="fr">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>POST avec BODY</title>
      </head>
      <body>
        <button onclick="envoyerRequetePost()">POST AVEC BODY</button>
     
        <script>
          function envoyerRequetePost() {
            const url = window.location.origin + '/handleBody'; 
            const corpsTexte = "Portez ce vieux whisky au juge blond qui fume sa pipe";
     
            fetch(url, {
              method: 'POST',
              headers: { 'Content-Type': 'text/plain' },
              body: corpsTexte
            })
            .then(response => response.ok ? response.text() : Promise.reject('La réponse du réseau n\'est pas valide'))
            .then(data => console.log('Réponse du serveur:', data))
            .catch(error => console.error('Erreur:', error));
          }
        </script>
      </body>
    </html>
    )rawliteral";
     
     
    void notFound(AsyncWebServerRequest *request) {
      request->send(404, "text/plain", "Not found");
    }
     
    void pageRacine(AsyncWebServerRequest *request) {
      request->send_P(200, "text/html", index_html);
    }
     
    void gestionBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
      if (!index) Serial.printf("Debut du body: %u octets\n", total);
      for (size_t i = 0; i < len; i++) Serial.write(data[i]);
      if (index + len >= total) Serial.printf("\nFin du body: %u octets\n", total);
    }
     
    void reponseBody(AsyncWebServerRequest * request) {
      Serial.println("Fin de le requête pour le body.");
      request->send(200);
    }
     
    void setup() {
      Serial.begin(115200);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.printf("Erreur WiFi!\n");
        while (true) yield();
      }
      Serial.println("Connecté au WiFi");
     
      Serial.print("Ouvrir http://"); Serial.println(WiFi.localIP());
     
      server.on("/", HTTP_GET, pageRacine);
      server.on("/handleBody",   HTTP_POST, reponseBody, nullptr, gestionBody);
      server.onNotFound(notFound);
     
      server.begin();
    }
     
    void loop() {}
    quand vous chargez ce code sur votre ESP32, le moniteur série dira


    Connecté au WiFi
    Ouvrir http://10.116.1.22


    (l'IP va varier en fonction de votre réseau)

    vous copiez le http://10.116.1.22 et collez cela dans l'URL de votre navigateur web qui est sur le même réseau WiFi et vous avez une page web toute simple avec un seul bouton
    Nom : web.png
Affichages : 72
Taille : 64,3 Ko
    vous clickez sur le bouton et ça déclenche un javascript sur le navigateur web
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    function envoyerRequetePost() {
      const url = window.location.origin + '/handleBody';
      const corpsTexte = "Portez ce vieux whisky au juge blond qui fume sa pipe";
     
      fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'text/plain' },
        body: corpsTexte
      })
      .then(response => response.ok ? response.text() : Promise.reject('La réponse du réseau n\'est pas valide'))
      .then(data => console.log('Réponse du serveur:', data))
      .catch(error => console.error('Erreur:', error));
    }
    qui crée une requête POST sur /handleBody (ça peut s'appeler /Toto si vous voulez) et dont le body est "Portez ce vieux whisky au juge blond qui fume sa pipe"


    le serveur voit donc arriver /handleBody et donc ça correspond à la règle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      server.on("/handleBody",   HTTP_POST, reponseBody, nullptr, gestionBody);
    (on aurait mis /Toto à la place si le JS disait Toto ==> server.on("/Toto", HTTP_POST, reponseBody, nullptr, gestionBody);)

    qui dit appeler la fonction gestionBody() tant qu'il y a du contenu qui arrive pour le body (ça peut être appelé plusieurs fois en cas de long contenu / chunks et les paramètres vous permettent de savoir où vous en êtes dans la réception du contenu) et une fois que tout le body a été transmis, ça appelle reponseBody() qui se charge d'envoyer la réponse au code JS dans le navigateur (ici je renvoie juste un code 200 pour dire que tout est OK).

    dans le moniteur série de votre ESP32 vous verrez que les 2 fonctions gestionBody() et reponseBody() sont bien appelées

    Debut du body: 53 octets
    Portez ce vieux whisky au juge blond qui fume sa pipe
    Fin du body: 53 octets
    Fin de le requête pour le body.



    ==> à vous de modifier la fonction gestionBody() pour faire ce que vous voulez (capturer le texte dans un buffer par exemple) puis utilisez reponseBody() pour traiter ce que vous venez de capturer (vous saurez quand reponseBody() est appelée que tout le body a été transmis).

    ça vous aide ?

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Merci Jay M oui cela m'aide beaucoup.
    Je suis en train de l'adapter à mon projet mais lorque que l'ESP32 est installé sur mon montage (carte électronique), je ne peux pas utiliser la liaison série. D'ailleurs l'affichage sur l'écran de l'ordi n'est pas la finalité.
    Donc pas d'affichage sur l'écran d'ordi (tous les Serial.print ne sont pas utilisables) et pour utiliser la message reçu, je dois le mettre dans une variable, car ce message contient un ensemble de paramètres saisis par le client et qui sera décortiqué.

  8. #8
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    OK

    L’usage des print était juste pour montrer ce qu’il se passe. Bien sûr à adapter à votre cas d’usage.

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Justement pour l'adapter à mon projet, j'ai encore quelques difficultés:
    J'ai compris que data[i] contenant le body, mais, par exemple, si ce message est:
    Nom : captureAlert.JPG
Affichages : 73
Taille : 13,2 Ko
    où tous les caractères ou messages entre les virgules doivent être exploités, comment puis-je faire?
    J'ai pensé pettre dans un String puis rechercher les virgules les unes après les autres?

  10. #10
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    vous déclarez un buffer en variable globale assez gros pour mémoriser tout le body
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    const size_t tailleMaxBody = 512;
    char bufferBody[tailleMaxBody];
    La fonction gestionBody() va remplir le buffer en utilisant les paramètres len, index et total
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void gestionBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
    len est le nombre d'octets dans le paquet courant (donc data pointe vers len octets)
    total est la taille en octets du body total (vérifiez donc avant de le recevoir que total est < tailleMaxBody)
    index est le nombre d'octets déjà reçus dans les appels précédents
    donc un memcpy(bufferBody+index, data, len); va permettre d'accumuler les données du body dans le buffer et quand vous êtes à la fin, mettre un '\0' pour terminer le buffer et pouvoir utiliser les fonctions de parsing.
    if (index + len >= total) bufferBody[total] = '\0'; // on a tout reçu, on marque la fin de la cString

    Dans le fonction reponseBody() vous pouvez utilisez strtok(), strtol() etc pour analyser le contenu de votre body en fonction de la grammaire.

    une autre approche serait d'envoyer le body en format JSON et d'utiliser la bibliothèque ArduinoJSON pour le décodage. ça vous simplifiera la vie si vous n'êtes pas à l'aise avec les fonction C de parsing.

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    merci beaucoup pour toutes ces explications.
    envoyer le body en format JSON
    J'y avais bien pensé mais, nouveau problème, la lecture de la saisie se fait dans une boucle avec des tableaux indicés:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function lectureSaisie(){
        progNum=document.getElementById("prog_num").value;
        msg = touche + "," + progNum;
        for(let i=0;i<10;i++){
    .....................
    msg += "," + i.toString() + "," + adEquipe[i] + "," + numRelais[i] + "," + typeEquipe[i] +
                "," + typeAction[i] + "," + paramAction[i] + "," + heureAction[i] ;
    Donc si je rajoute un nom devant les valeurs pour respecter le formant "clé":valeur, tous les noms seront identiques et je ne pourrai pas les identifier côté serveur; enfin je crois.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function lectureSaisie(){
        progNum=document.getElementById("prog_num").value;
        msg = "dest:" + touche + ",prog:" + progNum;
        for(let i=0;i<10;i++){
    ..................
            msg += ",man:" + i.toString() + ",add:" + adEquipe[i] + ",rel:" + numRelais[i] + ",type:" + typeEquipe[i] +
                ",action:" + typeAction[i] + ",param:" + paramAction[i] + ",hr:" + heureAction[i] ;
        }
    si vous n'êtes pas à l'aise avec les fonctions C de parsing.
    Oui c'est bien le cas, alors JSON aurait été la solution.

  12. #12
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Il faudrait un peu plus d’infos mais si vous savez générer un body non formatté, ce doit être possible de générer la même chose en JSON

    Pouvez vous poster un exemple de ce à quoi ressemble la chaîne générée ?

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Le client connecté demande une feuille de saisie pour programmer des évènements pilotés par la domotique(ESP32).
    Après avoir saisie un ensemble de 10 manoeuvres pour un programme (j'usqu'à 10 programmes) le client peu soit charger ce programme en RAM soit le stocker en SPIFFS (ROM).
    La feuille de saisie est lue et envoyée au serveur pour traitement.

    Pouvez vous poster un exemple de ce à quoi ressemble la chaîne générée ?
    Juste avant d'envoyer le POST j'affiche le message constitué:

    Nom : captureAlert.JPG
Affichages : 62
Taille : 10,1 Ko
    -entete-
    A -> à enregistrer en RAM O -> en ROM
    6 -> N° du programme (0 à 9)

    -champs de la manoeuvre N° 0
    0 -> N° de la manoeuvre (0 à 9)
    1 -> adresse de l'équipement (1 à 9 /A à F)
    0 -> pas de relais auxiliaire (add 1 à 8)
    V -> l'équipement commande un volet L-> relais Local D-> relais distant
    O -> Ouverture F-> Fermeture
    025 -> de 25% taux d'ouverture de 1 à 100%
    08:15 -> à 8h15¨


    -champs de la manoeuvre N°1
    1 -> N° manoeuvre
    2 -> adresse de l'équipement
    etc
    soit 132 octets si je ne me trompe pas.

    Je pourrais encore simplifier en omettant le N° de manoeuvre puisque c'est dans l'ordre.
    Je pourrais limiter le taux d'ouverture à 2 caratères sachant que 00 serait interprété pour 100%

    En espérant que ces explications soient assez claires.

  14. #14
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    OK je vois pour le début mais à quoi correspond 60000100700001008000010090000100

    pour les commandes je vois bien un JSON comme cela
    Nom : JSON.png
Affichages : 59
Taille : 111,6 Ko

    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
     
    {
      "entete": {
        "type": "A",
        "programme": 6
      },
      "manoeuvres": [
        {
          "numero": 0,
          "adresse": "1",
          "relais": 0,
          "commande": {
            "type": "V",
            "action": "O",
            "pourcentage": 25,
            "heure": "08:15"
          }
        },
        {
          "numero": 1,
          "adresse": "2",
          "relais": 0,
          "commande": {
            "type": "V",
            "action": "O",
            "pourcentage": 30,
            "heure": "08:16"
          }
        },
        {
          "numero": 2,
          "adresse": "3",
          "relais": 4,
          "commande": {
            "type": "L",
            "action": "O",
            "pourcentage": 100,
            "heure": "10:10"
          }
        },
        {
          "numero": 3,
          "adresse": "4",
          "relais": 8,
          "commande": {
            "type": "D",
            "action": "O",
            "pourcentage": 100,
            "heure": "11:00"
          }
        },
        {
          "numero": 4,
          "adresse": "0",
          "relais": 0,
          "commande": {
            "type": "V",
            "action": "F",
            "pourcentage": 100,
            "heure": "22:00"
          }
        },
        {
          "numero": 5,
          "adresse": "2",
          "relais": 0,
          "commande": {
            "type": "F",
            "action": "F",
            "pourcentage": 100,
            "heure": "23:30"
          }
        }
      ]
    }
    pour alléger bien sûr on peut réduire les clés.

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    à quoi correspond 60000100700001008000010090000100
    C'est la même chose que précédemment (manoeuvres 6 7 8 9) sauf que je n'ai pas rempli l'ensemble du formulaire et ce sont des valeurs par défaut souvent des 0 mise à part le taux à 100%.

    Oui je vois bien cette construction JSON; mais est-ce que cela ne va pas être trop lourd à gérer (création dans Javascript côté client) (extraction des données côté serveur ESP32)?
    Ce qui me fait peur ce sont tous ces {} [] "" qu'il faut ajouter. Je pense qu'il faut d'abord créer un objet Javascript puis avec STRINGIFY() le transformer en JSON.
    Je vais essayé de le faire; ce sera une première pour moi!

  16. #16
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    ça sera certes plus lourd à générer et transmettre mais le décodage sera simple si vous ne voulez pas jouer avec les fonctions du C++

  17. #17
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    j'ai voulu voir si c'était si compliqué que cela à décoder, pas tant que ça car chaque manoeuvre a le même nombre d'octets donc avec sscanf ça se fait bien

    essayez cela:

    j'ai crée des structures pour stocker le contenu analysé

    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
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
     
    enum Destination : char  {EN_RAM = 'A', EN_ROM = 'O'};
    enum Equipement : char  {VOLET = 'V', RELAIS_LOCAL = 'L', RELAIS_DISTANT = 'D'};
    enum Sens : char  {OUVERTURE = 'O', FERMETURE = 'F'};
     
    struct Manoeuvre {
      byte numero;
      char adresse;
      byte relaisAuxiliaire;
      Equipement equipement;
      Sens sens;
      byte taux;
      byte heure;
      byte minute;
      bool active;
    };
     
    const byte nbMaxManoeuvres = 10;
     
    struct Commande {
      Destination destination;
      byte numero;
      Manoeuvre manoeuvres[nbMaxManoeuvres];
    };
     
     
    bool analyse(Commande &commande, char *texte) {
      char *ptr = texte;
      char buffer[4]; // Pour stocker temporairement les sous-chaînes extraites
     
      // Analyse de l'entête
      if (sscanf(ptr, "%c%1d", &commande.destination, &commande.numero) != 2) return false;
      ptr += 2;
     
      for (int i = 0; i < nbMaxManoeuvres; i++) commande.manoeuvres[i].active = false;
     
      // Analyse des manoeuvres
      for (int i = 0; i < nbMaxManoeuvres; i++) {
        if (strlen(ptr) >= 13) {
          Manoeuvre &manoeuvre = commande.manoeuvres[i];
          if (sscanf(ptr, "%1d%1c%1d%1c%1c%3d%2d:%2d", &manoeuvre.numero, &manoeuvre.adresse, &manoeuvre.relaisAuxiliaire, &manoeuvre.equipement, &manoeuvre.sens, &manoeuvre.taux, &manoeuvre.heure, &manoeuvre.minute) == 8) {
            manoeuvre.active = true;
            ptr += 13; // Avance le pointeur de texte pour passer à la prochaine manoeuvre
          } else return false;
        } else {
          // le texte restant est trop court, on dit que cela signifie qu'il n'y a plus de manoeuvres à analyser
          break;
        }
      }
      return true;
    }
     
    void printCommande(Commande & commande) {
      Serial.print("Programme Numero: ");
      Serial.print(commande.numero);
      Serial.print(" => en ");
      switch (commande.destination) {
        case EN_RAM: Serial.println("RAM") ; break;
        case EN_ROM: Serial.println("ROM") ; break;
        default: Serial.println("??") ; break;
      }
     
      for (int i = 0; i < 10; i++) {
        Manoeuvre &manoeuvre = commande.manoeuvres[i];
        if (!manoeuvre.active) continue;
        Serial.print("Manoeuvre ");
        Serial.print(manoeuvre.numero);
        Serial.println(": ");
        Serial.print("\tAdresse: ");
        Serial.println(manoeuvre.adresse);
        Serial.print("\tRelais Auxiliaire: ");
        Serial.println(manoeuvre.relaisAuxiliaire);
        Serial.print("\tEquipement: ");
        switch (manoeuvre.equipement) {
          case VOLET: Serial.println("Volet") ; break;
          case RELAIS_LOCAL: Serial.println("RELAIS LOCAL") ; break;
          case RELAIS_DISTANT: Serial.println("RELAIS DISTANT") ; break;
          default: Serial.println("??") ; break;
        }
        Serial.print("\tSens: ");
        Serial.println((char)manoeuvre.sens);
        Serial.print("\tTaux: ");
        Serial.print(manoeuvre.taux);
        Serial.println("%");
        Serial.print("\tHeure: ");
        Serial.print(manoeuvre.heure);
        Serial.print(":");
        Serial.println(manoeuvre.minute);
      }
    }
     
     
    void setup() {
      char body[] = "A6010VO02508:15120VO03008:16234LO10010:10348DO10011:00400VF10022:00520DF10023:30";
     
      Serial.begin(115200);
      Commande commande;
      if (analyse(commande, body)) {
        printCommande(commande);
      } else {
        Serial.println("Erreur d'analyse");
      }
    }
     
    void loop() {}
     
     
     
    /*
      en tête
      x -> A à enregistrer en RAM,  O -> en ROM
      x -> N° du programme (0 à 9)
     
      x -> N° de la manoeuvre (0 à 9)
      x -> adresse de l'équipement (1 à 9 /A à F)
      x -> adresse relais auxiliaire (1 à 8) ou 0 pour pas de relais
      x -> l'équipement commandé un V pour un volet,  L pour relais Local et D pour relais distant
      x -> sens de la commande O pour Ouverture F pour Fermeture
      xxx -> le taux de %age d'ouverture de 000 à 100 (en %)
      hh:mm -> l'heure sous format heure:minutes
    */
     
     
    /*
      A
      6
     
      0         N° de la manoeuvre (0 à 9)
      1         adresse de l'équipement (1 à 9 /A à F)
      0         adresse relais auxiliaire
      V         équipement commandé
      O         sens de la commande
      025       taux
      08:15     hh:mm
     
      1
      2
      0
      V
      O
      030
      08:16
     
      2
      3
      4
      L
      O
      100
      10:10
     
      3
      4
      8
      D
      O
      100
      11:00
     
      4
      0
      0
      V
      F
      100
      22:00
     
      5       N° de la manoeuvre (0 à 9)
      2       adresse de l'équipement (1 à 9 /A à F)
      0       adresse relais auxiliaire
      D       équipement commandé
      F       sens de la commande
      100     taux
      23:30   hh:mm
    */

    Pour l'analyse de A6010VO02508:15120VO03008:16234LO10010:10348DO10011:00400VF10022:00520DF10023:30
    la sortie sur la console série (à 115200 bauds) donne

    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
     
    Programme Numero: 6 => en RAM
    Manoeuvre 0: 
    	Adresse: 1
    	Relais Auxiliaire: 0
    	Equipement: Volet
    	Sens: O
    	Taux: 25%
    	Heure: 8:15
    Manoeuvre 1: 
    	Adresse: 2
    	Relais Auxiliaire: 0
    	Equipement: Volet
    	Sens: O
    	Taux: 30%
    	Heure: 8:16
    Manoeuvre 2: 
    	Adresse: 3
    	Relais Auxiliaire: 4
    	Equipement: RELAIS LOCAL
    	Sens: O
    	Taux: 100%
    	Heure: 10:10
    Manoeuvre 3: 
    	Adresse: 4
    	Relais Auxiliaire: 8
    	Equipement: RELAIS DISTANT
    	Sens: O
    	Taux: 100%
    	Heure: 11:0
    Manoeuvre 4: 
    	Adresse: 0
    	Relais Auxiliaire: 0
    	Equipement: Volet
    	Sens: F
    	Taux: 100%
    	Heure: 22:0
    Manoeuvre 5: 
    	Adresse: 2
    	Relais Auxiliaire: 0
    	Equipement: RELAIS DISTANT
    	Sens: F
    	Taux: 100%
    	Heure: 23:30

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

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Bonjour Jay M
    Cette dernière solution experte conviendrait certainement pour une nouvelle application. Mon problème c'est que ce nouveau développement (saisie d'une programmation horaire à distance) doit s'intégrer dans un programme déjà assez lourd (enfin pour moi).
    Aussi j'ai essayé d'utiliser les conseils que vous m'avez proposés précédemment, à savoir stocker les infos dans un buffer par memcpy, puis extraire ces données et les intégrer dans mon programme existant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //********Réception d'un POST*********
      serveur.on("/GestionPost", HTTP_POST, reponseReception, nullptr, gestionReception);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void reponseReception(AsyncWebServerRequest *req) {
      req->send(200,"Content-type: text/plain", "Ok");
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //****Gestion réception des POST******************
    void gestionReception(AsyncWebServerRequest *req, uint8_t *data, size_t len, size_t index, size_t total) {
      memcpy(bufBody + index,data,len);
      if(index + len >= total) {
        bufBody[total] = '\0';
        gestionPost();
      }
    }
    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
    char cmdCm[13]     //buffer d'utilisations diverses
    //******************Gestion du post reçu pour la programmation********************
    void gestionPost(){
      char dest = bufBody[0];         //destination RAM ou ROM
      cmdCl[1] = bufBody [1];         //N° du programme horaire
      uint8_t k=0;
      for(uint8_t i=0;i<10;i++){              //scan les 10 manoeuvres
        cmdCl[2] = bufBody[2+k];      //N° de la manoeuvre  0 a 9
        cmdCl[3] = bufBody[6+k];      //type de manoeuvre   O/F/B/D
     
        if(bufBody[3+k]=='B'){        //si c'est un relais de la Base
          cmdCl[4] = bufBody[4+k];    //adresse de l'équipement
          cmdCl[5] = bufBody[6+k];    //N° du relais
          cmdCl[6] = bufBody[7+k];    //type de relais 0/A
        }
        else if(bufBody[3+k]=='D'){   //si c'est un relais distant
          char c = bufBody[3+k];      //adresse de l'équipement
          char r = bufBody[4+k];      //N° du relais
          cmdCl[4] = char(ci(c) * 10 + ci(r));     //integre le caractere ASCII
          cmdCl[5] = bufBody[7+k];    //si relais temporisé  secondes x 10
          cmdCl[6] = bufBody[8+k];    //si relais temporisé  secondes
        }
        else{
          cmdCl[4] = bufBody[3+k];    //adresse de l'équipement
          cmdCl[5] = bufBody[7+k];    //dizaine du taux
          cmdCl[6] = bufBody[8+k];    //unité du taux   00=100%
        }
        cmdCl[7] = bufBody[9+k];    //dizaine de l'heure
        cmdCl[8] = bufBody[10+k];   //unité de l'heure
        cmdCl[9] = bufBody[12+k];   //dizaine des minutes
        cmdCl[10] = bufBody[13+k];  //unité des minutes
     
        for(int8_t j=0;j<8;j++){
          pg[ci(cmdCl[1])][ci(cmdCl[2])*8 + j] = cmdCl[j+3];    //enregistrement en RAM
        }
        k += 12;    //position des premiers champs 2 14 26 38 50 62 74 86 98 110
      }
     
      if(dest=='O'){
        cmdCl[0] = '6';     //Code de commande ecriture en SPIFFS
        //cmdCl[1]  numéro du programme
        cmdCl[2] = '\0';
        commandeRecu = true;   //dans loop cela lance la commande d'écriture en SPIFFS
      }  
    }
    Les manipulations sont stockées dans un tableau pg[10][80] 10 programmes(0-9) 10 manips(0-9) de 8 octets.
    ci(char x) est une fonction de conversion caractère-> int.
    Lorsque j'établis une programmation horaire par le clavier de service, cela fonctionne parfaitement.
    Je pense que c'est l'extraction des données de bufBody qui ne fonctionne pas.

    A titre indicatif, voici le schéma de mon système:Domotique.pdf

  19. #19
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Je pense que c'est l'extraction des données de bufBody qui ne fonctionne pas.
    essayez d'imprimer le body pour voir si c'est OK

    n'appelez pas gestionPost(); dans le callback du body, faites le traitement du body dans le callback qui est déclenché à la fin de la réponse

  20. #20
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    revoici mon exemple où le body est envoyé et stocké au fil de l'eau (j'ai mis un gros body donc on voit plusieurs requêtes)

    Au lieu d'imprimer le body dans reponseBody(), c'est là qu'il faut faire l'analyse


    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
     
    #include <Arduino.h>
    #ifdef ESP32
    #include <WiFi.h>
    #include <AsyncTCP.h>
    #elif defined(ESP8266)
    #include <ESP8266WiFi.h>
    #include <ESPAsyncTCP.h>
    #endif
    #include <ESPAsyncWebServer.h>
     
    const char*   ssid = "***";
    const char*   password = "***";
    AsyncWebServer server(80);
     
     
    const char index_html[] PROGMEM = R"rawliteral(
    <!DOCTYPE html>
    <html lang="fr">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>POST avec BODY</title>
      </head>
      <body>
        <button onclick="envoyerRequetePost()">POST AVEC BODY</button>
     
        <script>
          function envoyerRequetePost() {
            const url = window.location.origin + '/handleBody'; 
            const corpsTexte = "DEBUT abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 FIN";
     
            fetch(url, {
              method: 'POST',
              headers: { 'Content-Type': 'text/plain' },
              body: corpsTexte
            })
            .then(response => response.ok ? response.text() : Promise.reject('La réponse du réseau n\'est pas valide'))
            .then(data => console.log('Réponse du serveur:', data))
            .catch(error => console.error('Erreur:', error));
          }
        </script>
      </body>
    </html>
    )rawliteral";
     
     
    const size_t tailleMaxBody = 8196;// prévoir assez grand
    char bufferBody[tailleMaxBody];
    bool bodyPret;
     
     
    void notFound(AsyncWebServerRequest *request) {
      request->send(404, "text/plain", "Not found");
    }
     
    void pageRacine(AsyncWebServerRequest *request) {
      request->send_P(200, "text/html", index_html);
    }
     
    void gestionBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
      if (index == 0) {
        bodyPret = false;
        Serial.printf("\nDébut du body: %zu octets\n", total);
     
      }
      if (total >= tailleMaxBody) Serial.println("Le body est trop grand");
      else {
        Serial.printf("\n---- NOUVEL APPEL len=%zu et index = %zu ----\n", len, index);
        memcpy(bufferBody + index, data, len);
        if (index + len >= total) bufferBody[total] = '\0';
        if (index + len >= total) {
          Serial.printf("\nFin du body: %zu octets\n", total);
          bodyPret = true;
        }
      }
    }
     
    void reponseBody(AsyncWebServerRequest * request) {
      Serial.println("Fin de le requête pour le body.");
      if (bodyPret) {
        Serial.println("Le body que j'au reçu est:");
        Serial.println(bufferBody);
     
      }
     
      request->send(bodyPret ? 200 : 413); // 413 est le code d'erreur HTTP pour "Payload Too Large"
    }
     
    void setup() {
      Serial.begin(115200);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.printf("Erreur WiFi!\n");
        while (true) yield();
      }
      Serial.println("Connecté au WiFi");
     
      Serial.print("Ouvrir http://"); Serial.println(WiFi.localIP());
     
      server.on("/", HTTP_GET, pageRacine);
      server.on("/handleBody",   HTTP_POST, reponseBody, nullptr, gestionBody);
      server.onNotFound(notFound);
     
      server.begin();
    }
     
    void loop() {}

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Appeler un programme sur le poste client avec <object>
    Par ouioui2000 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 22/08/2005, 14h40
  2. [Forms5]ouvrir un executable sur un poste client
    Par anthony8 dans le forum Forms
    Réponses: 2
    Dernier message: 30/06/2005, 14h26
  3. [CR][VB6]PB sur poste Client
    Par Angusy dans le forum SDK
    Réponses: 8
    Dernier message: 16/04/2005, 20h20
  4. communication entre poste client windows et db mysql distant
    Par gabole dans le forum Bases de données
    Réponses: 3
    Dernier message: 24/08/2004, 16h59
  5. [CR10][ASP.NET]Impression sur le poste Client
    Par David.V dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 30/04/2004, 13h41

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