ESPAsyncWebServer send an answer

Hello everyone,
I use a server installed in an ESP8266 to open my garage door with a code sent by Domoticz. This code is turning it can only be used once.
In the attached sketch I recover the opening code with the Get_http but I cannot send the new code via Response of ESPAsyncWebServer .
Can anyone help me?

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

const int len=12;  // longueur du code porte
char lastCode[len] = "Init";  // a la mise sous tension

AsyncWebServer server(80);

const char* ssid = "******";
const char* password = "I***********";
const char* PARAM_KEY = "key";

const char DzUrl[]="http://192.168.0.45:18080";
const char DzJSON[]="/json.htm?type=command&param=updateuservariable&vname=PGnextCode&vtype=string&vvalue=";


void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

void PGrecData (AsyncWebServerRequest *request){
    Serial.println("Je suis dans PGrecData");
    String message;  // char n'est pas accepté par Request
    if (request->hasParam(PARAM_KEY)) {
      message = request->getParam(PARAM_KEY)->value(); 
      request->send(200, "text/plain", "Hello, GET: " + message);
      Serial.print("Message dans l'URL: ");
      Serial.println(message);
      Serial.print("lastCode value: ");
      Serial.println(lastCode);      

      // convert message in Char
      char codePG[len];
      for (unsigned int i = 0; i <= len; i++) {
        codePG[i]= message[i];
      }
      codePG[len+1]=0;   // 13em char = fin de chaine

      //compare receive Code with the last one send 
      if (strcmp(codePG,lastCode)== 0) {
        Serial.println("OK: j'ouvre la porte");
        digitalWrite(LED_BUILTIN, LOW); 
        delay(1000);
        digitalWrite(LED_BUILTIN, HIGH); 
        }
      else {
        Serial.println("Les Codes ne sont pas identiques ! ");
      }

      Serial.println(" Attendre 1 seconde ... ");
      delay(1000);  // laisse du temps a DZ

// Génère le Nouveau code
      char code[len]="Hello!";   // juste pour init de la chaine
      for (unsigned int i = 0; i <= len; i++) {
          //car spéciaux http://192.168.0.15/get?key=kjgkjgkkjhhg1234567890?,.;/:%C2%A7!%C3%A9~%27{[-|
          code[i]= random(48,123); // & interdit!
      }
      code[len+1]=0;  // end of string for serial printing
      Serial.print("New code value: ");
      Serial.println(code); 
      
// Response send newCode to Domoticz
    StaticJsonDocument<100> JSONData;
    // Use the object just like a javascript object or a python dictionary
    JSONData["key"] = code;
    // You can add more fields
      serializeJson(JSONData, Serial); // ex:{"key":"?Ae6c40EBHvwu"}
    char data[100];
    // Converts the JSON object to String and stores it in data variable
    serializeJson(JSONData,data);
    // Set content type as application/json and send the data
    //MARCHE PAS! AsyncWebServerResponse *response = request->beginResponse(200, "text/html",  data);
    // MARCHE PAS AsyncWebServerResponse *response = request->beginResponse(200, "text/html", "<html><head></head><body>Hello World!</body></html>");
    //response->addHeader("Domoticz","PGcode");
    request->send(response);
  //request->send(200,"application/json",data);
  
    }     
    else { message = "BAD json receive"; }
 
}

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
    digitalWrite(LED_BUILTIN, HIGH);  // eteind la LED
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.println(""); // print a new line
    Serial.print("Connecting .");
    while (WiFi.status() != WL_CONNECTED) {  //Wait for connection
      delay(500);
      Serial.print(".");
    }
    Serial.println(""); // print a new line

    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

    // Send a GET request to <IP>/PG/get?key=<message>
    server.on("/PG/get", HTTP_GET, PGrecData);
    
    // Send a POST request to <IP>/post with a form field message set to <message>
    server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
        String message;
        if (request->hasParam(PARAM_KEY, true)) {
            message = request->getParam(PARAM_KEY, true)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, POST: " + message);
    });

    server.onNotFound(notFound);

    server.begin();
    Serial.print("Server listening, Open ");
    Serial.print(WiFi.localIP());
    Serial.println(" in your browser.");
}

void loop() {
}


Here the result in the serial monitor:
19:02:35.090 -> Message dans l'URL: 12/07/1950
19:02:35.090 -> lastCode value: Init
19:02:35.090 -> Les Codes ne sont pas identiques !
19:02:35.090 -> Attendre 1 seconde ...
19:02:36.105 -> New code value: ;O<Jcv6IY[XDS
19:02:36.105 -> {"key":";O<Jcv6IY[XDS"}

you overflow your array. Index goes from 0 to len-1 to get len characters.

you should stop before reaching len and later you use strcmp() which requires a cString, so you should have space for the trailing null char

      char codePG[len+1]; // +1 for the trailing null char
      for (unsigned int i = 0; i < len; i++)  codePG[i]= message[i]; // or use memcpy
       codePG[len] = '\0'; // terminate the cString

Thank you for your reply J-M-L.
Indeed I did not count the 0 which means that my code is 13 characters long with a risk of overflow. But the main problem with my request is that Domoticz tells me that the JSON response is empty so I assume that the ESP response is not correctly formulated. Do you have an idea ...

if you overflow the code has bugs and the behaviour cannot be predicted....

fix those first.

OK I made the modifications as you indicated to me and codePG is the expected length now. :wink:
As I expected Domoticz responds still 'no data available '

can you post the new code and what you see in the Serial monitor ?

Attached is the current code and the results :

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

const int len=12;  // longueur du code porte
char lastCode[len] = "Init";  // a la mise sous tension

AsyncWebServer server(80);

const char* ssid = "*******";
const char* password = "************";
const char* PARAM_KEY = "key";

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

void PGrecData (AsyncWebServerRequest *request){
    Serial.println("Je suis dans PGrecData");
    String message;  // char n'est pas accepté par Request
    if (request->hasParam(PARAM_KEY)) {
      message = request->getParam(PARAM_KEY)->value(); 
      request->send(200, "text/plain", "Hello, GET: " + message);
      Serial.print("Message dans l'URL: ");
      Serial.println(message);
      Serial.print("lastCode value: ");
      Serial.println(lastCode);      

      // convert message in Char
      char codePG[len+1]; // +1 for the trailing null char
      for (unsigned int i = 0; i < len; i++)  // JML July 14
        codePG[i]= message[i]; // or use memcpy
        codePG[len] = '\0'; // terminate the cString

      //compare receive Code with the last one send 
      if (strcmp(codePG,lastCode)== 0) {
        Serial.println("OK: j'ouvre la porte");
        digitalWrite(LED_BUILTIN, LOW); 
        delay(1000);
        digitalWrite(LED_BUILTIN, HIGH); 
        }
      else {
        Serial.println("Les Codes ne sont pas identiques ! ");
      }

      Serial.println(" Attendre 1 seconde ... ");
      delay(1000);  // laisse du temps a DZ

      // Generate New Code
      char code[len+1]="Hello!";   // juste pour init de la chaine
      for (unsigned int i = 0; i <= len; i++) {
          //car spéciaux http://192.168.0.15/get?key=kjgkjgkkjhhg1234567890?,.;/:%C2%A7!%C3%A9~%27{[-|
          code[i]= random(48,123); // & interdit!
      }
      code[len]='\0';  // end of string for serial printing
      Serial.print("New code value: ");
      Serial.println(code); 

             
// Response send newCode to Domoticz
    StaticJsonDocument<100> JSONData;
    // Use the object just like a javascript object or a python dictionary
    JSONData["key"] = code;
    // You can add more fields
      serializeJson(JSONData, Serial); // ex:{"key":"?Ae6c40EBHvwu"}
    char data[100];
    // Converts the JSON object to String and stores it in data variable
    serializeJson(JSONData,data);
    // Set content type as application/json and send the data
    //MARCHE PAS! AsyncWebServerResponse *response = request->beginResponse(200, "text/html",  data);
    // MARCHE PAS AsyncWebServerResponse *response = request->beginResponse(200, "text/html", "<html><head></head><body>Hello World!</body></html>");
    //response->addHeader("Domoticz","PGcode");
    //request->send(response);
    request->send(200,"application/json",code);
  
    }     
    else { message = "BAD json receive"; }
 
}

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
    digitalWrite(LED_BUILTIN, HIGH);  // eteind la LED
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.println(""); // print a new line
    Serial.print("Connecting .");
    while (WiFi.status() != WL_CONNECTED) {  //Wait for connection
      delay(500);
      Serial.print(".");
    }
    Serial.println(""); // print a new line

    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

    // Send a GET request to <IP>/PG/get?key=<message>
    server.on("/PG/get", HTTP_GET, PGrecData);
    
    server.onNotFound(notFound);

    server.begin();
    Serial.print("Server listening, Open ");
    Serial.print(WiFi.localIP());
    Serial.println(" in your browser.");
}

void loop() {
}

Code received by ESP and newcode send to Domoticz:
18:36:50.430 -> Message dans l'URL: 12/07/1950
18:36:50.430 -> lastCode value: Init
18:36:50.430 -> Les Codes ne sont pas identiques !
18:36:50.430 -> Attendre 1 seconde ...
18:36:51.416 -> New code value: 3:R;qljC_a5Q
18:36:51.416 -> {"key":"3:R;qljC_a5Q"}

Response from Domoticz:
2024-07-14 18:36:50.498 Status: User: DomoBoggiz (IP: 172.17.0.1) initiated a switch command (545/Test PG code tournant/On)
2024-07-14 18:36:50.539 Status: dzVents: Info: Handling events for: "Test PG code tournant", value: "On"
2024-07-14 18:36:51.605 Status: dzVents: Info: Handling httpResponse-events for: "OpenPG"
2024-07-14 18:36:51.606 Status: dzVents: ERROR 200:OK
2024-07-14 18:36:51.606 Status: dzVents: No available Data

I think the problem comes from the JSON processing by Domoticz because the response is OK but not the data. Certainly a format problem on the ESP side

d'où ça vient cela ?

200 ne devrait pas être une erreur ??

Bonjour JML,
Effectivement ce n'est pas une erreur mais ce n'est pas correct quand même car dans mon code j'envoyais ma réponse trop TÔT: immédiatement après la réception du GET ce qui interdit toute possibilité de réponse ultérieure!
J'ai corrigé cela et ça marche parfaitement.
Un grand merci pour votre intervention

Ok

Bonne continuation