Pass pointer to function

Hello,

I don't understand why this codes doesn't work as instead :frowning:

This code is working well :

static const char *url = "https://xxxxx/file_v2_1_0_199.bin";
HttpsOTA.onHttpEvent(HttpEvent);
HttpsOTA.begin( url, server_certificate );

This code, no :frowning:

...
#include <ArduinoJson.h>
...
StaticJsonDocument srvActions;
...
DeserializationError error = deserializeJson(srvActions, msg);
if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; }
const char* action = srvActions["action"];
const char* datas = srvActions["value"];
...
appUpdate( String( datas ) );
...

void appUpdate( String fwFileName ) {
Serial.println( fwFileName );
Serial.println( fwFileName.length());
int str_len = fwFileName.length() + 1;
char char_array[ str_len ];
fwFileName.toCharArray(char_array, str_len);

static const char *url = char_array;
HttpsOTA.onHttpEvent(HttpEvent);
Serial.print("url : ");Serial.println( url);
HttpsOTA.begin( url, server_certificate );

See bellow the console result :

08:34:15.852 -> 44
08:34:15.852 -> url : https://xxxxxxxx/file_v2_1_0_199.bin
08:34:15.852 -> E (5217) HTTP_CLIENT: Error parse url e⸮?⸮

Thanks in advance for your help

Memory issue ?

Try

void appUpdate( String& fwFileName ) {
  HttpsOTA.onHttpEvent(HttpEvent);
  HttpsOTA.begin( fwFileName.c_str(), server_certificate );
  …

There is no reason to allocate all the memory you have…

This supposed you are passing a String to the function.

If you pass something within double quotes then just do

void appUpdate( const char * fwFileName ) {
  HttpsOTA.onHttpEvent(HttpEvent);
  HttpsOTA.begin( fwFileName, server_certificate );
  …

Édit: just seen you call appUpdate( String( datas ) );

Why don’t you just call with the const char* you got ➜ appUpdate( datas ); and use the second version of the function given above ….

So much memory used for nothing:

  • you have a const char *
  • you allocate a String with its content
  • you duplicate that String to call the function
  • in the function you duplicate it again to have a char array buffer
  • then you allocate a const char * pointer to point at the start of the buffer (the buffer name would have been good enough)

That’s absurd given you had the const char* to start with…

Thanks for you reply.

It was my original code and console result :


void wsPrepare(char * msg){//Coming from WebSocket
  DeserializationError error = deserializeJson(srvActions, msg);
  if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; }
  const char* action = srvActions["action"];
  const char* datas  = srvActions["value"];
...
appUpdate( datas );
...
void appUpdate( const char * fwFileName ) {
  HttpsOTA.onHttpEvent(HttpEvent);
  Serial.printf("url : %s\n", fwFileName);
  HttpsOTA.begin( fwFileName, server_certificate ); 

09:03:25.993 -> url : https://xxxxxx/file_v2_1_0_199.bin
09:03:25.993 -> E (5299) HTTP_CLIENT: Error while setting default configurations
09:03:25.993 -> E (5304) esp_https_ota: Failed to initialise HTTP connection

I don't understand/know how to debug this issue. It's working only if the url variable has been declared in the "appUpdate" function like :

static const char *url = "https://xxxxxx/file_v2_1_0_199.bin";

Did you try what I proposed?

Don’t print or do anything else in the function

Possibly verify your internet connection is still active

Post full code

Need a moment to write a short sample code, my actual project is over 1000 lines.

appUpdate( datas );

09:03:25.993 -> E (5299) HTTP_CLIENT: Error while setting default configurations
09:03:25.993 -> E (5304) esp_https_ota: Failed to initialise HTTP connection

But the code see below is working

  static const char *url = "https://xxxxxx/file_v2_1_0_199.bin";
  appUpdate( url );

I don't understand because "datas" variable is a pointer of char array :
const char* datas = srvActions["value"];

That’s an issue you need to dig into

May be the problem is linked with the JSON, because

This code doesn't work :

void wsPrepare(char * msg){
if (msg == "") return;
Serial.print("WS >> wsPrepare ");
//Serial.println(msg);

DeserializationError error = deserializeJson(srvActions, msg);
if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; }
const char* action = srvActions["action"];
const char* datas = srvActions["value"];
...
Serial.printf("datas : %s\n", datas);
appUpdate( datas);

09:46:20.005 -> url : https://xxxxxx/file_v2_1_0_199.bin
09:46:20.005 -> E (5299) HTTP_CLIENT: Error while setting default configurations
09:46:20.005 -> E (5304) esp_https_ota: Failed to initialise HTTP connection

And this code is working :

void wsPrepare(char * msg){
if (msg == "") return;
Serial.print("WS >> wsPrepare ");
//Serial.println(msg);

DeserializationError error = deserializeJson(srvActions, msg);
if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; }
const char* action = srvActions["action"];
const char* datas = srvActions["value"];
...
static const char *url = "https://xxxxxx/file_v2_1_0_199.bin";
Serial.printf("url: %s\n", datas);
appUpdate( url);

09:47:41:214 -> url : https://xxxxxx/file_v2_1_0_199.bin
09:47:41:214 -> App >> Mise à jour : Http Event On Connected

may be there are invisible characters
try to print

Serial.printf("datas : [%s]\n", datas);

I become crazy ....

  Serial.printf("datas length : %s - %i\n", datas, strlen (datas));
  Serial.printf("datas : [%s]\n", datas);
  appUpdate( datas );

10:07:10.266 -> datas length : https://xxxxxx/file_v2_1_0_199.bin - 44
10:07:10.266 -> datas : [https://xxxxxx/file_v2_1_0_199.bin]
10:07:10.266 -> E (5216) HTTP_CLIENT: Error while setting default configurations

  static const char *url = "https://xxxxxx/filek_v2_1_0_199.bin";
  Serial.printf("url length: %s - %i\n", url, strlen (url));
  Serial.printf("url : [%s]\n", url);
  appUpdate( url );

10:09:29.809 -> url length: https://xxxxxx/filek_v2_1_0_199.bin - 44
10:09:29.809 -> url : [https://xxxxxx/file_v2_1_0_199.bin]
10:09:29.809 -> WS >> Pong
10:09:33.514 -> App >> Mise à jour : Http Event On Connected

you might have a buffer overflow somewhere than corrupts the http connection

Arf... Is there a way/method to trace this issue ?

look at the whole code for array allocation

I tried to remove all unnecessary code.

#include <Arduino.h>
#include <ArduinoUniqueID.h>
#include <Preferences.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#include "HttpsOTAUpdate.h"

#include <jled.h>
...
WebSocketsClient webSocket;
...
const size_t CAPACITY       = JSON_OBJECT_SIZE(4) + JSON_ARRAY_SIZE(3);
StaticJsonDocument<CAPACITY> doc;      
JsonArray jsonCmd           = doc.to<JsonArray>();
StaticJsonDocument<CAPACITY> srvActions;
...
void setup() {
  ...
  wsInit();
  ...
  ledSetup.Stop();
  ledCur.Update();
}
...
void loop() {
   ...
   ledCur.Update();
   webSocket.loop();
   wsSend();
   ...
}
...
void wsInit(){
  Serial.printf("WS >> Initialisation sur %s:%i\n", wsIP, wsPort);
  webSocket.begin( wsIP, wsPort, "/");
  webSocket.onEvent(wsEvent);
  webSocket.setAuthorization(............);
  webSocket.setReconnectInterval(5000);
  webSocket.enableHeartbeat(15000, 5000, 2);
}
...
void wsSend(){
  if (!wsIsConnected || jsonCmd.size() == 0) return;
  String output;
  serializeJson(doc, output);
  output = "{\"" + (isConfigured ? String("publicKey") : String("uniqueId")) + "\":\"" + (isConfigured ? publicKey : uniqueId) + "\", \"version\": \"" + SKETCH_VERSION + "\", \"actions\": " + output + "}";
  Serial.printf("WS >> wsSend : %s\n", output.c_str());
  webSocket.sendTXT(output);
  jsonCmd.clear();
}
...
void wsEvent(WStype_t type, uint8_t * payload, size_t length) {
  Serial.print("WS >> ");

  switch(type) {
	...
    case WStype_TEXT:
      Serial.printf("wsReceived : %s\n", payload);
      if ( String((char *) payload).startsWith("{") ) wsPrepare((char *) payload);
      break;
	...
  }
}
...
void wsPrepare(char * msg){
  if (msg == "") return;
  Serial.print("WS >> wsPrepare ");
  //Serial.println(msg);

  DeserializationError error = deserializeJson(srvActions, msg);
  if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; }
  const char* action = srvActions["action"];
  const char* datas  = srvActions["value"];

  actions act = actionSwitch( srvActions["action"] );
  
  switch (act){
   ...
   case 4: //UPDATE
      Serial.printf(">> Action : %s\n", action); 
      ledCur.Stop();
      ledCur = JLed(PIN_RED).Blink(500, 500).Forever();

      Serial.printf("datas length : %s - %i\n", datas, strlen (datas));
      Serial.printf("datas : [%s]\n", datas);
      appUpdate( datas );
      break;
	...   
  }
}
...
static HttpsOTAStatus_t otastatus;
static const char *server_certificate = ..............
void HttpEvent(HttpEvent_t *event) {
  Serial.print("App >> Mise à jour : ");
  .....
}

void appUpdate( const char * fwFileName ) {
  HttpsOTA.onHttpEvent(HttpEvent);
  HttpsOTA.begin( fwFileName, server_certificate ); 
}

so many missing parts, so hard to say. usually the bug is where you don't expect it...

you can't test a cString like this

  if (msg == "") return;

do

  if (*msg == '\0') return; // message is empty

also in this function

void wsEvent(WStype_t type, uint8_t * payload, size_t length) {

you are not guaranteed that the payload ends up with a null char, so you can't take for granted you have a cString when you do

      if ( String((char *) payload).startsWith("{") ) wsPrepare((char *) payload);

➜ there might be a few non printable bytes at the end that you don't see when you print things out.

do something like

    case WStype_TEXT:
      Serial.write("wsReceived :");
      Serial.write(payload, length);
      Serial.println();
      if (*payload == '{' ) wsPrepare((char* ) payload, length);
      break;

and change the function

void wsPrepare(char * msg, size_t length) {
  if (length == 0) return;

  DeserializationError error = deserializeJson(srvActions,  msg, length);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
  const char* action = srvActions["action"];
  const char* datas  = srvActions["value"];

  actions act = actionSwitch( srvActions["action"] );

  switch (act) {
      ...
    case 4: //UPDATE
      Serial.printf(">> Action : %s\n", action);
      ledCur.Stop();
      ledCur = JLed(PIN_RED).Blink(500, 500).Forever();

      Serial.printf("datas length : %s - %i\n", datas, strlen (datas));
      Serial.printf("datas : [%s]\n", datas);
      appUpdate( datas );
      break;
      ...
  }
}

Thanks for your comment :slight_smile:

Unfortunally, it's not better.
By any chance, is it possible that «srvActions["value"]» doesn't contain a null terminating ?

I don't succeed to add it manually with strcopy

no it will have one set by the ArduinoJSON library. what might happen though is that the library will read the data until it finds a null char, which might not be there at the end of the payload

One way to find out possibly is by looking at the char count
when you do

static const char *url = "https://xxxxxx/file_v2_1_0_199.bin";

➜ how many characters do you have in url ?

then when you go for the JSON, how many characters do you see in
const char* datas = srvActions["value"];

they would need to match

I already checked this part, it's correct :

const char* datas = srvActions["value"];
const char *urlTest = "https://xxxxxx/file_v2_1_0_199.bin"

Serial.printf("datas length : %s - %i\n", datas, strlen (datas));
Serial.printf("urlTest length : %s - %i\n", urlTest, strlen (urlTest));

14:11:09.874 -> datas length : https://xxxxxx/file_v2_1_0_199.bin - 44
14:11:09.874 -> urlTest length : https://xxxxxx/file_v2_1_0_199.bin - 44

really weird. Hard to debug without the full system on hand...

I would try to write a small code using the JSON and making the request

I'll write a short project to share with only the feature used for this action.

As I can see both variable have the same length and type. Is there a way to do a loop to display all ASCII codes of all caracters ?

sure a simple while loop until you find the null char would do

but that's what print does. if you can count 44 characters on screen for https://xxxxxx/file_v2_1_0_199.bin then you've seen them all

the issue is likely somewhere else. could you print the string and its length as well within the function and not when calling it.