How to convert MQTT stream into a string?

Hello,

Still trying to learn C++, but I am using the "WiFiSimpleReceive" example and there is this part in the code:

    while (mqttClient.available()) {
      Serial.print((char)mqttClient.read());
    }

I need to pass this information from that loop into a JSON parser where it needs to be in the format const char*
ie: const char* input = ..........

I've been banging my head against this for hours, would appreciate any help.

Thanks!

Are you using ArduinoJson? You can have the JSON deserialized right from the stream. Try the Assistant to generate code:

You will end up with something like:

StaticJsonDocument<1024> doc;

DeserializationError error = deserializeJson(doc, mqttClient);

if (error) {
  Serial.print(F("deserializeJson() failed: "));
  Serial.println(error.f_str());
  return;
}

Here is one way of doing what your topic title asks

void callback(char* topic, byte* payload, unsigned int length)
{
  char messageBuffer[30];  //a buffer to hold the string
  memcpy(messageBuffer, payload, length); //copy the payload to the buffer
  messageBuffer[length] = '\0';  //add the termination to turn the buffer into a string
  Serial.println(messageBuffer);  //print the string to prove that the conversion worked
}

Hello both, thank you for the responses.

Exactly, I am trying to use the ArduinoJson.h library with the ArduinoMqttClient.h (official) library.

Here is the exact stream of characters I get from the while loop in the OP:

{"doseCount":[{"date":"15 Aug 21","dosesTotal":"5,050,672","dosesToday":"65,634"},{"date":"14 Aug 21","dosesTotal":"4,985,038","dosesToday":"105,595"},{"date":"13 Aug 21","dosesTotal":"4,879,443","dosesToday":"106,331"},{"date":"12 Aug 21","dosesTotal":"4,773,112","dosesToday":"105,064"},{"date":"11 Aug 21","dosesTotal":"4,668,048","dosesToday":"106,592"},{"date":"10 Aug 21","dosesTotal":"4,561,456","dosesToday":"98,244"},{"date":"09 Aug 21","dosesTotal":"4,463,212","dosesToday":"25,483"}],"caseCount":[{"date":"15 Aug 21","casesTotal":"13,503","casesNew":"411"},{"date":"14 Aug 21","casesTotal":"13,092","casesNew":"463"},{"date":"13 Aug 21","casesTotal":"12,629","casesNew":"384"},{"date":"12 Aug 21","casesTotal":"12,245","casesNew":"343"},{"date":"11 Aug 21","casesTotal":"11,902","casesNew":"345"},{"date":"10 Aug 21","casesTotal":"11,557","casesNew":"356"},{"date":"09 Aug 21","casesTotal":"11,201","casesNew":"284"}],"calcs":{"percentageNSWVaccinated":"30.93%","averageDoses":"83923","daysUntil70percent":"76"}}

Unfortunately, the while loop is providing it as a stream of characters and I still can't figure out how to transcribe it so that I can pass it to deserializeJson();

Here's an example which returns nothing. I get the error "DeserializationError -> EmptyInput" right after the while loop which prints the correct JSON string.

  if (messageSize) {
    // use the Stream interface to print the contents
    while (mqttClient.available()) {
      Serial.print((char)mqttClient.read());
      }    

    DynamicJsonDocument doc(2048);
    deserializeJson(doc, mqttClient);
    JsonObject calcs = doc["calcs"];
    const char* calcs_percentageNSWVaccinated = calcs["percentageNSWVaccinated"]; // "30.93%"
    const char* calcs_averageDoses = calcs["averageDoses"]; // "83923"
    const char* calcs_daysUntil70percent = calcs["daysUntil70percent"]; // "76"

    Serial.println();
    Serial.print("NSW Percentage Vaccinated: ");
    Serial.println(calcs_percentageNSWVaccinated);
    }

Much appreciated!

To put it another way this works:

int main() {
  const char* json = R"({"doseCount":[{"date":"15 Aug 21","dosesTotal":"5,050,672","dosesToday":"65,634"},{"date":"14 Aug 21","dosesTotal":"4,985,038","dosesToday":"105,595"},{"date":"13 Aug 21","dosesTotal":"4,879,443","dosesToday":"106,331"},{"date":"12 Aug 21","dosesTotal":"4,773,112","dosesToday":"105,064"},{"date":"11 Aug 21","dosesTotal":"4,668,048","dosesToday":"106,592"},{"date":"10 Aug 21","dosesTotal":"4,561,456","dosesToday":"98,244"},{"date":"09 Aug 21","dosesTotal":"4,463,212","dosesToday":"25,483"}],"caseCount":[{"date":"15 Aug 21","casesTotal":"13,503","casesNew":"411"},{"date":"14 Aug 21","casesTotal":"13,092","casesNew":"463"},{"date":"13 Aug 21","casesTotal":"12,629","casesNew":"384"},{"date":"12 Aug 21","casesTotal":"12,245","casesNew":"343"},{"date":"11 Aug 21","casesTotal":"11,902","casesNew":"345"},{"date":"10 Aug 21","casesTotal":"11,557","casesNew":"356"},{"date":"09 Aug 21","casesTotal":"11,201","casesNew":"284"}],"calcs":{"percentageNSWVaccinated":"30.93%","averageDoses":"83923","daysUntil70percent":"76"}})";
  DynamicJsonDocument doc(2048);

  DeserializationError error = deserializeJson(doc, json);
    
  std::cout << "DeserializationError -> " << error.c_str() << std::endl;

  serializeJsonPretty(doc, std::cout);

  return 0;
}

and returns:

Start
DeserializationError -> Ok
{
  "doseCount": [
    {
      "date": "15 Aug 21",
      "dosesTotal": "5,050,672",
      "dosesToday": "65,634"
    },
    {
      "date": "14 Aug 21",
      "dosesTotal": "4,985,038",
      "dosesToday": "105,595"
    },
    {
      "date": "13 Aug 21",
      "dosesTotal": "4,879,443",
      "dosesToday": "106,331"
    },
    {
      "date": "12 Aug 21",
      "dosesTotal": "4,773,112",
      "dosesToday": "105,064"
    },
    {
      "date": "11 Aug 21",
      "dosesTotal": "4,668,048",
      "dosesToday": "106,592"
    },
    {
      "date": "10 Aug 21",
      "dosesTotal": "4,561,456",
      "dosesToday": "98,244"
    },
    {
      "date": "09 Aug 21",
      "dosesTotal": "4,463,212",
      "dosesToday": "25,483"
    }
  ],
  "caseCount": [
    {
      "date": "15 Aug 21",
      "casesTotal": "13,503",
      "casesNew": "411"
    },
    {
      "date": "14 Aug 21",
      "casesTotal": "13,092",
      "casesNew": "463"
    },
    {
      "date": "13 Aug 21",
      "casesTotal": "12,629",
      "casesNew": "384"
    },
    {
      "date": "12 Aug 21",
      "casesTotal": "12,245",
      "casesNew": "343"
    },
    {
      "date": "11 Aug 21",
      "casesTotal": "11,902",
      "casesNew": "345"
    },
    {
      "date": "10 Aug 21",
      "casesTotal": "11,557",
      "casesNew": "356"
    },
    {
      "date": "09 Aug 21",
      "casesTotal": "11,201",
      "casesNew": "284"
    }
  ],
  "calcs": {
    "percentageNSWVaccinated": "30.93%",
    "averageDoses": "83923",
    "daysUntil70percent": "76"
  }
}
0
Finish

I just don't know how to apply it to a MQTT request as per above, and then extract a value that I want (such as calcs_percentageNSWVaccinated) rather than a fixed JSON which I've manually fed in.

Oh man, I feel like an idiot. I wasted half a day because I didn't realise that this while loop is streaming and clearing the data at the same time :man_facepalming:

Commenting it out, it all works perfectly now. Hope this helps someone else. Thank you all.

    while (mqttClient.available()) {
      Serial.print((char)mqttClient.read());
      }   

Does anyone know how to clear mqttClient without iterating through a while loop?