Search code examples
javascriptjsonwebserveresp32

ESP32 doesn't process data sent as JSON from the web app while the data is being sent correctly to the ESP32


how are you?.

I'm making an application where a ESP32 is being used as web server, currently I have a web page made to configure the device.

In this pages is a <form> element, once the submit button is pressed the configuration is sent to the ESP32, I know the data is sent because I'm watching it with wireshark like seen in the following image

Datos capturadoes

and I know the ESP32 is receiving the POST request because of several println sentences that I have in the code, so, the code for processing the request is as follows

server.on("/forma-dato", HTTP_POST, [](AsyncWebServerRequest *request) {
    if(!request->authenticate(usuarioHTTP, claveHTTP)) {
      return request->requestAuthentication();
    };
    request->send(200);
    Serial.println("Solicitud de carga de archivos enviada.");
    ultimaPaginaCargada = "/config.html";
  }, manejaJson);

the callback manejaJSON is defined as follows and was extracted from this page

void manejaJson(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
  Serial.println("Recibiendo configuración de la dirección IP ." + request->client()->remoteIP().toString() + " " + request->url());
  if(!filename) {
    Serial.println("No hay archivo.");
  }
  if(!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
    Serial.println("Carga Iniciada" + String(filename));
  }
  if(len) {
    request->_tempFile.close();
    Serial.println("Escribiendo archivo: " + String(filename) + ", tamaño: " + String(len));
  }
  if(final) {
    request->_tempFile.close();
    Serial.println("Carga completa: " + String(filename) + ", tamaño: " + String(index + filename));
    request->redirect("/");
  }
}

as you can see there are several println sentences to know what the program is doing but none of the messages inside manejaJson callback is being printed so I think the manejaJson callback is not being executed, in addition I don't have any return value from manejaJson and that void definition is made because is the same that defining it as an ArUploadHandlerFunction as declared int the .on definition made in WebServer.cpp of AsyncWebServer library.

bellow is the code to send the data from the web page

if(document.getElementById("forma") != null) {              // Si encuentra la forma con la id igual a "forma",
    var elementoForma = document.getElementById("forma");   // extrae los valores completos.
    elementoForma.addEventListener("submit", function(e) {
        e.preventDefault();
        var datosForma = {};
        var formaDatos = new FormData(elementoForma);
        for(var [k,v] of formaDatos) {
            datosForma[k] = v;
        }
        console.log(datosForma);
        var datosJson = JSON.stringify(datosForma)
        console.log(datosJson);
        var config = new Blob([datosJson], {type: 'application/json'});
        fetch("forma-dato", {
            method: "POST",
            body: config
        });
        /*fs.writeFile('config.json', datosJson, 'utf-8', (err) => {
            if(err) {
                throw err;
            }
            console.log("Archivo guardado correctamente");
        });*/
        console.log(config);
        /*var envioForma = new XMLHttpRequest();
        envioForma.open("POST", "forma-dato", true);
        envioForma.send(config);*/
    });
}

right know the data is being sent by using a fetch method but commented are another two pieces of code to send the data, one with writefile and the other with XMLHttpRequest, the writefile right now doesn't like too much because of the use of node.js in a completely offline app.

So, what can I do to solve this and being able to process the incomming data.

Thanks in advance for the help.

NOTE: this question is the exact copy of the this post that I previously made but people in electronics stackexchange advice me to make the post here because is mor related to software than firmware.


Solution

  • Just to let them all to know, I was able to solve the problem with code found on the internet, the problem seems to be that the default methods of AsyncWebServer API for managing incoming requests doesn't manage requests with JSON data in the body by default.

    For managing the data one must use asyncjson.h and arduinojson.h and the code is like follows

      AsyncCallbackJsonWebHandler* manejadorJson = new AsyncCallbackJsonWebHandler("/forma-dato", [](AsyncWebServerRequest *request, JsonVariant &docJson) {
        auto&& jsonObj = docJson.as<JsonObject>();
        Serial.print("La fecha actual es :");
        Serial.println((const char *) jsonObj["fecha"]);
        Serial.print("El horario del domingo en la tarde es: ");
        Serial.println((const char *) jsonObj["domingo-tarde-fin"]);
        request->send(200);
        Serial.println("Configuración recibida.");
      });
      server.addHandler(manejadorJson);
    

    of course all the print sentences are written by me to being able to know if the data was processed.

    NOTE: in the readme of AsyncWebServer API is an example almost like the one bellow instead of using the line

    auto&& jsonObj = docJson.as<JsonObject>()
    

    is used

    JsonObject& jsonObj = docJson.as<JsonObject>()
    

    the example written with the previous line (only one &) didn't work for me, I look over there and apparently the problem with that sentence is that one can't reference variables that haven't been initializated.