Problems with const char* and String types

Hello;

I'm having a problem related to const char* and String types.

When deserializing with the String type in the "Unit" class, everything goes fine. However, if I override the type to const char*, things get lost and become unstable, assigning other values ​​to the variables.

Here's the result as an example.

With string:

4:32:01.859 -> Mensagem chegou no topico: fikerplunk/Test/LockerCriando classe lockers...
14:32:01.904 -> Mensagem chegou no topico: fikerplunk/Test/UnitCriando classe units...
14:32:01.997 -> Quantidade de units
14:32:02.044 -> 13
14:32:02.044 -> Valor Unit:101A
14:32:02.044 -> Valor Unit:102A
14:32:02.044 -> Valor Unit:103A
14:32:02.089 -> Valor Unit:104A
14:32:02.089 -> Valor Unit:105A
14:32:02.135 -> Valor Unit:11A
14:32:02.135 -> Valor Unit:12A
14:32:02.135 -> Valor Unit:201A
14:32:02.182 -> Valor Unit:202A
14:32:02.182 -> Valor Unit:203A
14:32:02.182 -> Valor Unit:204A
14:32:02.227 -> Valor Unit:205A
14:32:02.227 -> Valor Unit:Portaria
14:32:02.272 -> Valor Unit:101A
14:32:02.272 -> Valor Unit:102A
14:32:02.272 -> Valor Unit:103A
14:32:02.319 -> Valor Unit:104A
14:32:02.319 -> Valor Unit:105A
14:32:02.365 -> Valor Unit:11A
14:32:02.365 -> Valor Unit:12A
14:32:02.365 -> Valor Unit:201A
14:32:02.410 -> Valor Unit:202A
14:32:02.410 -> Valor Unit:203A
14:32:02.410 -> Valor Unit:204A
14:32:02.457 -> Valor Unit:205A
14:32:02.457 -> Valor Unit:Portaria
14:32:02.503 -> Valor Unit:101A
14:32:02.503 -> Valor Unit:102A
14:32:02.503 -> Valor Unit:103A
14:32:02.549 -> Valor Unit:104A
14:32:02.549 -> Valor Unit:105A
14:32:02.595 -> Valor Unit:11A
14:32:02.595 -> Valor Unit:12A
14:32:02.595 -> Valor Unit:201A
14:32:02.641 -> Valor Unit:202A
14:32:02.641 -> Valor Unit:203A
14:32:02.687 -> Valor Unit:204A
14:32:02.687 -> Valor Unit:205A
14:32:02.687 -> Valor Unit:Portaria

With const char*:

14:33:29.687 -> Mensagem chegou no topico: fikerplunk/Test/LockerCriando classe lockers...
14:33:29.780 -> Mensagem chegou no topico: fikerplunk/Test/UnitCriando classe units...
14:33:29.827 -> Quantidade de units
14:33:29.874 -> 13
14:33:29.874 -> Valor Unit:101A
14:33:29.874 -> Valor Unit:102A
14:33:29.921 -> Valor Unit:P⸮L⸮
14:33:29.921 -> Valor Unit:⸮
14:33:29.921 -> Valor Unit:⸮⸮xV⸮⸮1A⸮⸮⸮?⸮⸮⸮?t
14:33:29.966 -> Valor Unit:⸮1A⸮⸮⸮?⸮⸮⸮?t
14:33:30.013 -> Valor Unit:⸮⸮?⸮⸮⸮

Here is the code:

#include <PubSubClient.h>
#include "ArduinoJson.h"
#include <WiFi.h>
#include <WiFiClient.h>

class Locker
{
  public:
    String id;
    boolean active;
    String document;
    String status;
    int sensorPin;
    int relayPin;
    int number;
    String keycode;
    String bookingNumber;
    String nrOfDays;
    String packetNumber;
    const char* typeLocker;
};

class Unit
{
  public:
    const char* name;
    //String name;
};

Locker lockers[99];
Unit units[99];

WiFiClient wifiClient;
PubSubClient client(wifiClient);
int totalUnit;

void setup() {
  Serial.begin(9600);
  WiFi.begin("userWifi", "passW1f1");

  client.setServer("159.782.456.632", 1883);
  client.setBufferSize(20000);
  client.setCallback(callback);
  client.setKeepAlive(90);
}

void loop() {
  client.loop();
  verificaMqtt();
  for (int i = 0; i < totalUnit; i++) {
    Serial.print("Valor Unit:");
    Serial.println(units[i].name);
  }
}

void connectMqtt() {
  if (client.connect("userFikerplunk", "userMqttx", "p4ssw0rd")) {
    String sub1 = "fikerplunk/Test/Locker";
    String sub2 = "fikerplunk/Test/Unit";
    if (client.subscribe(sub1.c_str())) {
      Serial.println("Se inscreveu no tópico");
      Serial.println(sub1);
    }
    if (client.subscribe(sub2.c_str())) {
      Serial.println("Se inscreveu no tópico UNIT");
      Serial.println(sub2);
    }
  } else {
    Serial.print("falha, erro =");
    Serial.print(client.state());
  }
}

void verificaMqtt() {
  if (!client.connected() && WiFi.status() == WL_CONNECTED)
  {
    Serial.println(F("DESCONECTOU MQTT, CONECTANDO NOVAMENTE"));
    connectMqtt();
  }
}

void callback(char* topic, unsigned char* message, unsigned int length) {
  Serial.print("Mensagem chegou no topico: ");
  Serial.print(topic);
  String messageTemp;
  //json = "";
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  String sub1 = "fikerplunk/Test/Locker";
  String sub2 = "fikerplunk/Test/Unit";
  if ((String)topic == sub1) {
    Serial.println("Criando classe lockers...");
    criarClasse(messageTemp);
    messageTemp = "";
  }
  else if ((String)topic == sub2) {
    Serial.println("Criando classe units...");
    criarClasseUnit(messageTemp);
    messageTemp = "";
  }
}

void criarClasse(String json)
{
  DynamicJsonDocument doc(30000);
  deserializeJson(doc, json);
  JsonObject root = doc.as<JsonObject>();
  int count = -1;
  for (JsonPair kv : root)
  {
    count++;
    lockers[count].id = kv.key().c_str();
    lockers[count].document = (const char*)doc[lockers[count].id]["document"];
    lockers[count].keycode = (const char*)doc[lockers[count].id]["keycode"];
    lockers[count].number = doc[lockers[count].id]["number"];
    lockers[count].status = (const char*)doc[lockers[count].id]["status"];
    lockers[count].sensorPin = doc[lockers[count].id]["sensorPin"];
    lockers[count].relayPin =  doc[lockers[count].id]["relayPin"];
    lockers[count].nrOfDays = (const char*)doc[lockers[count].id]["nrOfDays"];
    lockers[count].bookingNumber = (const char*)doc[lockers[count].id]["bookingNumber"];
    lockers[count].active = doc[lockers[count].id]["active"];
    lockers[count].packetNumber = (const char*)doc[lockers[count].id]["packetNumber"];
    lockers[count].typeLocker = (const char*)doc[lockers[count].id]["typeLocker"];
  }
}

void criarClasseUnit(String json)
{
  DynamicJsonDocument doc(30000);
  deserializeJson(doc, json);
  JsonObject root = doc.as<JsonObject>();
  int count = -1;
  for (JsonPair kv : root)
  {
    count++;
    units[count].name = kv.key().c_str();
  }
  totalUnit = count + 1;
  Serial.println("Quantidade de units");
  Serial.println(totalUnit);
}

This is the json I get by mqtt:

{"101A":{},"102A":{},"103A":{},"104A":{},"105A":{},"11A":{},"12A":{},"201A":{},"202A":{},"203A":{},"204A":{},"205A":{},"Portaria":{}}

Could someone tell me why this occurs and how can I fix it to work with const char*?

Thanks!

you understand that if you have a String instance, you have dynamic storage that goes with it for the content of the String. if you go with const char* there is no storage whatsoever attached to name...

so when you do

    units[count].name = kv.key().c_str();

you assign the pointer to the back end data of kv.key()., not a copy of the content

you need storage, if you want it static, then define a max length for your units

class Unit
{
  public:
    char name[31]; // max 30 characters and trailing null char
};

and use strncpy() or strlcpy() to get the bytes from kv.key().c_str(); into units[count].name

but how could I handle this situation using const char*?

I ask because this JSON I get always tries to increase and if I leave it as String it will consume a lot of ram.

if you want to keep a copy, you'll need storage.

if you want to save whole JSON, it will consume a lot of ram regardless is this String or char

Thank you for the explanation.

I managed to deal here, thank you very much!

glad if that helped

enjoy

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.