Json Parsing Issue

Hopefully this will be a quick one, I am using a ESP32 to read values from a MQTT server over Wi-Fi.

The topic is in this format:

{"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent",}

My code successfully connects and can publish to the MQTT server; however, I can’t figure out how to extract the values for say, "temp":42.2,"

I think I am close but could use some help to get this working!

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



const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_ARRAY_SIZE(2) + 60; // Example capacity
    StaticJsonDocument<capacity> doc;

// WiFi
const char *ssid = ""; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);
    while (!client.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (client.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    client.subscribe("CumulusMX/DataUpdate");
}

void callback(char *topic, byte *payload, unsigned int length) {
  
  
   char jsonString[length + 1];
   memcpy(jsonString, payload, length);
        jsonString[length] = '\0';
        DeserializationError error = deserializeJson(doc, jsonString);
        if (error) {
            Serial.print(F("deserializeJson() failed: "));
            Serial.println(error.f_str());
            return;
   }
  
    int windspeed = doc["windspeed"];
    int winddir = doc["winddir"];
    float press = doc["press"];
       
    Serial.println(windspeed);       
    Serial.println(winddir);
        
       
    }


void loop() {
    client.loop();
}

Here is formatted result:

{
  "time": "15:19:49",
  "windspeed": 3,
  "windgust": 10,
  "wgustTM": 16,
  "YearGustH": 39,
  "winddir": 133,
  "press": 29.95,
  "presstrend": "Rising slowly",
  "temp": 42.2,
  "temptrendtext": "Rising",
  "tempTH": 42.5,
  "tempTL": 37.0,
  "dew": 39.2,
  "heatindex": 42.2,
  "wchill": 40.1,
  "feelslike": 40.1,
  "tempH": 96.7,
  "tempL": -10.6,
  "outhum": 89,
  "raintoday": 0.26,
  "rainrate": 0.00,
  "rmonth": 1.00,
  "ryear": 30.38,
  "IsRaining": 0,
  "moonphase": "Waning Crescent"
}

So you can extract the value for "temp" like this:

float temp = doc["temp"]; // 42.2

I added this to the end of the code

float temp = doc["temp"];
Serial.println(temp);

But I am not seeing any values in the serial monitor

Just this:"

Connecting to WiFi..
Connected to the Wi-Fi network
Connected to the MQTT Broker

So you could not get the topic message?

Why this line is comment out?

This has a trailing comma, which should cause the JSON parse to fail with InvalidInput. But if that's just a typo, the JSON parsing part works for me after removing that comma

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200);
}

const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };

void loop() {
  JsonDocument doc;
  auto length = strlen(payload);

  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    for (;;);
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);

  delay(2500);
}

That prints the expected numbers. Note that all the static JSON stuff is deprecated; just use JsonDocument.

I am trying to incorporate your suggestion, this won’t compile for me..

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



const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_ARRAY_SIZE(2) + 60; // Example capacity
    StaticJsonDocument<capacity> doc;

// WiFi
const char *ssid = "FRANKWIFI-2.4"; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
   
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    //client.setCallback(callback);
    while (!client.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (client.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    client.subscribe("CumulusMX/DataUpdate");
}
 const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };
void loop() {
  JsonDocument doc;
  auto length = strlen(payload);

  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    for (;;);
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);

  delay(2500);
}
        
       
  
 

void loop() {
    client.loop();
}

Hi @kenb4 ,

If OP were able to receive the topic message and the JSON data had a trailing ,, OP should see deserializeJson() failed: InvalidInput.

Therefore, I assume that callback() wasn't executed.

That's a good point. When I add Serial.printf("size: %d\n", measureJson(doc)); to your code and I found the size of doc is 392 bytes.

However, capacity is 108, so there's insufficient space.

It helps to include the error. Posting the message verbatim, as <CODE/>, will preserve spacing to indicate the exact position.

But I'm guessing it's because you have two functions named loop

Here is what I am seeing now, I did have two “Void Loop” I commented the one at the end out, but it just created another error.

Arduino: 1.8.19 (Windows 10), Board: "ESP32 Dev Module, Disabled, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, Core 1, Core 1, None, Disabled, Disabled"




Mqtt-Example-2:80:5: error: 'client' does not name a type; did you mean 'Client'?

   80 |     client.loop();

      |     ^~~~~~

      |     Client

Mqtt-Example-2:81:1: error: expected declaration before '}' token

   81 | }

      | ^



exit status 1

'client' does not name a type; did you mean 'Client'?



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

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

// WiFi
const char *ssid = "FRANKWIFI-2.4"; 
const char *password = "Kiya1020";

// MQTT Broker
const char *mqtt_broker = "192.168.4.53";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
   
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    //client.setCallback(callback);
    while (!client.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (client.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    client.subscribe("CumulusMX/DataUpdate");
}
 const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };

void loop() {
  JsonDocument doc;
  auto length = strlen(payload);

  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    for (;;);
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);

  delay(2500);
}
     
       
  
 

//void loop() {
    client.loop();
}

Ok, I just renamed that function at the end and the code compiles and runs but it seems to just be returning the values from this line:

const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };
void loop() {

I am not seeing the live data from the MQTT server.

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

// WiFi
const char *ssid = ""; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
   
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    //client.setCallback(callback);
    while (!client.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (client.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    client.subscribe("CumulusMX/DataUpdate");
}
 const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };
void loop() {
  JsonDocument doc;
  auto length = strlen(payload);

  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    for (;;);
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);

  delay(2500);
}
     
       
  
 

void loops() {
    client.loop();
}

As expected. Did you intend something different?

Not a fan of calling the various clients just client. Try this (I redacted the WiFi credentials)

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

// WiFi
const char *ssid = "yyyy"; 
const char *password = "zzzz";

// MQTT Broker
const char *mqtt_broker = "192.168.4.53";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient wifi;
PubSubClient mqtt(wifi);

void printPayload(const void *payload, unsigned int length) {
  JsonDocument doc;
  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);
}

void callback(char *topic, byte *payload, unsigned int length) {
  Serial.print("mqtt callback\t");
  Serial.println(topic);
  printPayload(payload, length);
}

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);

    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    mqtt.setServer(mqtt_broker, mqtt_port);
    mqtt.setCallback(callback);
    while (!mqtt.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (mqtt.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(mqtt.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    mqtt.subscribe("CumulusMX/DataUpdate");
}

const char *testPayload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };

void loop() {
  mqtt.loop();

  static auto testLen = strlen(testPayload);
  static auto last = millis();
  auto now = millis();
  if (now - last > 2500) {
    last = now;
    printPayload(testPayload, testLen);
  }
}

Yes, I am sure my code is working as it should, but what I am trying to do is subscribe to the MQTT topic ”CumulusMX/DataUpdate” and read the data from there. That topic is updated every 1.5 seconds from my Weather Station.

Thanks Ken, this also runs fine but is not returning the live data from the MQTT connection.

My apologies for the confusion.

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

// WiFi
const char *ssid = ""; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const char *topic = "TEST";
const int mqtt_port = 1883;

WiFiClient wifi;
PubSubClient mqtt(wifi);

void printPayload(const void *payload, unsigned int length) {
  JsonDocument doc;
  char jsonString[length + 1];
  memcpy(jsonString, payload, length);
  jsonString[length] = '\0';
  Serial.print("payload\t");
  //Serial.println(jsonString);

  DeserializationError error = deserializeJson(doc, jsonString);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  int windspeed = doc["windspeed"];
  int winddir = doc["winddir"];
  float temp = doc["temp"];

  Serial.println(windspeed);
  Serial.println(winddir);
  Serial.println(temp);
}

void callback(char *topic, byte *payload, unsigned int length) {
  Serial.print("mqtt callback\t");
  Serial.println(topic);
  printPayload(payload, length);
}

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);

    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(5000);
        Serial.println("Connecting to WiFi..");
    }
    Serial.println("Connected to the Wi-Fi network");
    //connecting to a mqtt broker
    mqtt.setServer(mqtt_broker, mqtt_port);
    mqtt.setCallback(callback);
    while (!mqtt.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());       
        if (mqtt.connect(client_id.c_str())) {
            Serial.println("Connected to the MQTT Broker");
        } else {
            Serial.print("failed with state ");
            Serial.print(mqtt.state());
            delay(2000);
        }
    }
    // Publish and subscribe
   //Client.publish(topic, "Hi, I'm ESP32 ^^");
    mqtt.subscribe("CumulusMX/DataUpdate");
}

const char *testPayload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };

void loop() {
  mqtt.loop();

  static auto testLen = strlen(testPayload);
  static auto last = millis();
  auto now = millis();
  if (millis() - last > 2500) {
    last = now;
    printPayload(testPayload, testLen);
  }
}

Then you should not be defining a global pointer named payload as "const"
and treating is as a variable that your program can modify internally.

 const char *payload{ R"({"time":"15:19:49","windspeed":3,"windgust":10,"wgustTM":16,"YearGustH":39,"winddir":133,"press":29.95,"presstrend":"Rising slowly","temp":42.2,"temptrendtext":"Rising","tempTH":42.5,"tempTL":37.0,"dew":39.2,"heatindex":42.2,"wchill":40.1,"feelslike":40.1,"tempH":96.7,"tempL":-10.6,"outhum":89,"raintoday":0.26,"rainrate":0.00,"rmonth":1.00,"ryear":30.38,"IsRaining":0,"moonphase":"Waning Crescent"})" };

See @kenb4 post above.

I apricate everyone’s help!! Thank you! I am sure my problem is in reading and parsing that topic data.

I will keep at it and let you know when I get it working!

I am still stuck, below is my latest sketch which is bit different than previous attempts.

Again,

I can connect to my MQTT server and publish successfully using the following line (verified using MQTT explorer).

client.publish(topic, "ESP32 Connected! ^^"); // for testing
 

I added this line to the callback section, but nothing prints to the serial monitor

Serial.print("Message Arrived!");

So I think I am not seeing the incoming messages on the topic “CumulusMX/DataUpdate” for some reason? The json pay load is 630 byts.

I tried expanding the message buffer size as well as subscribing to a smaller topic.

Sorry if this code is a bit of a Frankenstein, I am just getting started at all of this.

FULL SKETCH:

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

// WiFi
const char *ssid = ""; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const char *topic = "CumulusMX/DataUpdate";  
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi..");    }
        Serial.println("Connected to the Wi-Fi network"); 
           
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);
    while (!client.connected()) {
        String client_id = "esp32-client";
        client_id += String(WiFi.macAddress());       
        if (client.connect(client_id.c_str())) {
            Serial.print("Connected to the MQTT Broker:"); 
            Serial.print ( topic) ;                         
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());                  
            delay(2000);                      
        }
}
//client.publish(topic, "ESP32 Connected! ^^"); // for testing
//client.subscribe("CumulusMX/DataUpdate"); // for testing

}
void callback(char* topic, byte* payload, unsigned int length)
{   
    Serial.print("Message Arrived!");
    char messageBuffer[1000];                 //an array to hold the payload
    memcpy(messageBuffer, payload, length);  //copy the payload into the array
    messageBuffer[length] = '\0';            //turn the char array into a C string
    Serial.printf("%s\n", messageBuffer);     
    parseMessage(messageBuffer);    
}

void parseMessage(char* json)
{
    StaticJsonDocument<1000> doc;
    DeserializationError error = deserializeJson(doc, json);
    if (error)
    {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return;
    }
    const char* time = doc["time"];
    int temp = doc["temp"];
    int winddir = doc["winddir"];
    float press = doc["press"];

    Serial.printf("Time : %s\n", time);
    Serial.printf("Out Door Temp : %d\n", temp);
    Serial.printf("Wind Direction : %d\n", winddir);
    Serial.printf("Pressure : %f\n", press);
}
void loop() { 
    client.loop();
}

This prints the topic name when connecting, but that has nothing to do with anything. Might give a false sense of progress; remove it.

The actual call to subscribe uses a hard-coded string instead of the topic variable. And of course, at the moment, it is commented-out.

If that's not the obvious blunder, then

you might try shortening the client ID. If this is your MQTT server, how many others are there? Maybe include a random-ish value. Some library examples use millis(); its variance might depend on your WL_CONNECTED loop. Just in case the server gets confused with you retrying as the same client.

You're not being that consistent with print vs println. Include a line break at the front of the string -- "\nMessage Arrived" -- to be sure you don't miss it.

Check if (length < sizeof(messageBuffer) -1). Probably unrelated to your current problem, but it could become one later.

Thanks again for all your patience.

I dumbed down the clientId:

if (client.connect("ESP32")) {

Added the line break:"

Serial.print("\nMessage Arrived!");

Using these lines to pub/sub:

client.publish("test-Pub", "ESP32 Connected2! ^^"); // for testing
client.subscribe("CumulusMX/DataUpdate"); // for testing

I also added a reconnect: Not seeing any errors at this time.

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP32")) {
      Serial.println("connected");
      // Subscribe
      client.subscribe("CumulusMX/DataUpdate");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

I added a test line to publish some simple text and my code does publish every 2 seconds so I know my connection to the MQTT server is good.

void loop() { 
  if (!client.connected()) {
    reconnect();
  }
  client.publish("test-Pub", "ESP32 Connected2! ^^");
  delay(2000);
    client.loop();    
}

I was also able to publish to “CumulusMX/DataUpdate” as another test.

I still can’t seem get that callback function to fire to even test reading and parsing the messages being sent on “CumulusMX/DataUpdate” I temporarily added a serial print line in that callback function to kinda watch it.

The broker runs locally and is wide open using “allow_anonymous true”

I have 3 other clients attached that can sub/pub just fine without credentials

I am still trying!

Current Sketch:

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

// WiFi
const char *ssid = ""; 
const char *password = "";

// MQTT Broker
const char *mqtt_broker = "";
const int mqtt_port = 1883;


WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // Set software serial baud to 115200;
    Serial.begin(115200);
    // Connecting to a WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi..");    }       
        Serial.println("Connected to the Wi-Fi network");       
           
    //connecting to a mqtt broker
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);
    while (!client.connected()) {            
        if (client.connect("ESP32")) {                     
        } else {
            Serial.print("failed with state ");
            Serial.print(client.state());                  
            delay(2000);                      
        }
}
client.publish("test-Pub", "ESP32 Connected2! ^^"); // for testing
client.subscribe("CumulusMX/DataUpdate"); // for testing

}
void callback(char* topic, byte* payload, unsigned int length)
{   
    Serial.print("\nMessage Arrived!");
    char messageBuffer[1000];                 //an array to hold the payload
    memcpy(messageBuffer, payload, length);  //copy the payload into the array
    messageBuffer[length] = '\0';            //turn the char array into a C string
    Serial.printf("%s\n", messageBuffer);     
    parseMessage(messageBuffer);    
}


void parseMessage(char* json)
{
    Serial.print("ParseMessage Called!");
    StaticJsonDocument<1000> doc;
    DeserializationError error = deserializeJson(doc, json);
    if (error)
    {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return;
    }
    const char* time = doc["time"];
    int temp = doc["temp"];
    int winddir = doc["winddir"];
    float press = doc["press"];

    Serial.print(time);
    Serial.print(temp);
    Serial.print(winddir);
    Serial.print( press);
}
    void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP32")) {
      Serial.println("connected");
      // Subscribe
      client.subscribe("CumulusMX/DataUpdate");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void loop() { 
  if (!client.connected()) {
    reconnect();
  }
  //client.publish("test-Pub", "ESP32 Connected2! ^^");
  //delay(2000);
    client.loop();    
}

Are any of them ESP32? Here is a test program that grabs whatever is being published through test.mosquitto.org by using the ro:readonly creds to access the top-level # wildcard topic, as required by that server. (Maybe you can try the same wildcard locally.)

#include <WiFi.h>
#include <PubSubClient.h>
#include "arduino_secrets.h"

WiFiClient wifi;
PubSubClient mqtt(wifi);
auto broker = "test.mosquitto.org";
auto port = 1884;
auto user = "ro";
auto pass = "readonly";
String id = "rand";

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void reconnect() {
  // Loop until we're reconnected
  while (!mqtt.connected()) {
    Serial.print("Attempting MQTT connection as ");
    Serial.print(id);
    Serial.print("...");
    // Attempt to connect
    if (mqtt.connect(id.c_str(), user, pass)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      // mqtt.publish("outTopic","hello world");
      // ... and resubscribe
      mqtt.subscribe("#");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqtt.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(SECRET_SSID, SECRET_PASS);
  for (int i = 0; WiFi.status() != WL_CONNECTED; i++) {
    Serial.print(i % 50 ? "." : "\n.");
    delay(20);
  }
  id += micros();
  Serial.println();
  Serial.println(WiFi.macAddress());
  id += WiFi.macAddress().substring(10);

  mqtt.setServer(broker, port);
  mqtt.setCallback(callback);
  reconnect();
}

void loop() {
  // Commented-out so that it doesn't run forever
  // if (!mqtt.connected()) {
  //   reconnect();
  // }
  mqtt.loop();
}

Just to prove that the PubSubClient works.