Search code examples
arduinomqttpublish-subscribeesp32

ESP32 Arduino PubSub publish error for variable char array?


I'm programming an ESP32 with Arduino and am publishing MQTT messages using the standard pubsubclient library.

In my loop below, I have noticed my "Inside loop" gets published, however, the second message of variable jsonObjChar never seems to get published to the topic? There aren't any errors in the serial monitor.

void loop(){
  String temperature = String(readDHTTemperature());
  String humidity = String(readDHTHumidity());
  String light = String(readLDRLight());


  String jsonObj = "{";    
  jsonObj.concat("\"deviceId\":\"123456\"");
  jsonObj.concat(",");
  jsonObj.concat("\"messageType\":\"ambientSensorReading\"");
  jsonObj.concat(",");
  jsonObj.concat("\"temperature\":\"");
  jsonObj.concat(temperature);
  jsonObj.concat("\"");
  jsonObj.concat(",");
  jsonObj.concat("\"humidity\":\"");
  jsonObj.concat(humidity);
  jsonObj.concat("\"");
  jsonObj.concat(",");
  jsonObj.concat("\"light\":\"");
  jsonObj.concat(light);
  jsonObj.concat("\"}");

  delay(1000);

  int jsonObjCharLength = jsonObj.length() + 1;
  char jsonObjChar[jsonObjCharLength];
  jsonObj.toCharArray(jsonObjChar, jsonObjCharLength);

  Serial.println("PREPARED");  
  Serial.println(jsonObjChar);  

  const char topic[13] = "prototype001";

  client.publish(topic, "inside loop");
  client.publish(topic, jsonObjChar);

  // ... and resubscribe
  client.subscribe("prototype001");

  delay(5000);

}

The variable jsobObjChar seems to be fine, when I print it out to the serial monitor, it looks like an ordinary string (I've structured in JSON format to be handled on the server side)

20:13:41.494 -> PREPARED

20:13:41.494 -> {"deviceId":"123456","messageType":"ambientSensorReading","temperature":"25.10","humidity":"49.90","light":"2592"}

20:13:46.521 ->

If it helps, I'm using cloudmqtt.

Any help would be greatly appreciated!!!


Solution

  • Try to get rid of strings, they will fracture your heap and cause crashes. Define global fixed charBuffers (big enough to take the largest message) and helper (tmp chars) for conversion and other things) Do not define const chars in the loop do it before setup so the compiler places them in the stack and is not using heap during runtime. I changed your code to this principle and added an extra delay between messages:

    const char topic[13] = "prototype001"; // goes to the stack
    char jsonObjChar [256] = '\0'; // set it large enough goes to the stack not heap!
    char numBuffer [16] = '\0'; //tmpBuffer for conversion of ints to char
    
    void loop(){
     if (!client.connected()) {
      reconnect();
      }
    
    
      strcpy (jsonObj, "{");    // Initialize/clear char by using strcpy
      strcat(jsonObj, "\"deviceId\":\"123456\"");   // strcat append
      strcat(jsonObj,",");
      strcat(jsonObj,"\"messageType\":\"ambientSensorReading\"");
      strcat(jsonObj,",");
      strcat(jsonObj,"\"temperature\":\"");
      // conversion only needed if temperature is an int, if its char use strcat(jsonObj,readDHTTemperature());
      itoa (readDHTTemperature(), numBuffer, 10); // Converts an int to a char array 
      strcat(jsonObj,numbuffer);
      strcat(jsonObj,"\"");
      strcat(jsonObj,",");
      strcat(jsonObj,"\"humidity\":\"");
      // if already char use strcat(jsonObj,readDHTHumidity());
      itoa (readDHTHumidity(), numBuffer, 10);
      strcat(jsonObj,numbuffer);
      strcat(jsonObj,"\"");
      strcat(jsonObj,",");
      strcat(jsonObj,"\"light\":\"");
      // if char strcat(jsonObj,readLDRLight());
      itoa (readLDRLight(),numBuffer. 10);
      strcat(jsonObj,numbuffer);
      strcat(jsonObj,"\"}");
    
      delay(1000);
    
    
      Serial.println("PREPARED");  
      Serial.println(jsonObjChar);  
    
      client.publish(topic, "inside loop");
      delay(1000); // for test onl<
      client.publish(topic, jsonObjChar);
    
      // ... and resubscribe
      client.subscribe("prototype001");
    
      delay(5000);
     client.loop();
    
    }
    

    If it works - fine. If not the next debug step would be to look whats received at the server.