Arduino -Sending and Receiving JSON Data over MQTT

To send an receive JSON data with Arduino you can use the ArduinoJson library.

The online documentation contains several usage examples, and there is even a book that supports the project.

In this example we are going to send a JSON object using MQTT, receive that object and decode it.



The first step is to create a doc object of sufficient size. You can either create a static one or a dynamic one in the example we use static.

The difference between StaticJsonDocument and DynamicJsonDocument is covered here.

In version 5 of ArduinoJson we had StaticJsonBuffer and DynamicJsonBuffer the difference is here

You will see code on the Internet for both v5 and v6. The code in this example uses v6. The difference between v5 and v6 is explained here.

 There is a detailed tutorial on calculating the size here.

Values of 128,256 are usually used. If you find that not all objects are serialised then you need to choose a larger value.

The next thing to note is how we add the elements using standard object notation doc[“sensor”] = “gps”;

For the array element we create a nested array object and then add in the array values.

This is what the output looks like using the mosquitto_sub tool.

arduino-json-2

Once we are finished we use the serializeJson(doc, out) function using the doc object and an output buffer which I declared using char out[128].

We then publish using the standard mqtt.publish command. The code is shown below:

StaticJsonDocument<256> doc;
doc["sensor"] = "gps";
doc["time"] = 1351824120;

// Add an array.
//
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
//doc["data"]=data;
// Generate the minified JSON and send it to the Serial port.
//
char out[128];
int b =serializeJson(doc, out);
Serial.print("bytes = ");
Serial.println(b,DEC);
boolean rc = mqttClient.publish("arduino-test", out);
// The above line prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}

Receiving JSON Data

The received data is handled by the callback function. This returns the data in a byte array.

Again we need to create a JSON doc of sufficient size.

Then we can either convert the payload into a string as it is a byte array of we can use it directly as the deserialize function will accept a byte array.

We then convert the received jSON string into a doc object and access the values using the same syntax we used for create them and print out a few just to confirm that it all works. The code is shown below:

void callback(char* topic, byte* payload, unsigned int length) {

char str[length+1];
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
int i=0;
for (i=0;i<length;i++) {
Serial.print((char)payload[i]);
str[i]=(char)payload[i];

}
str[i] = 0; // Null termination
Serial.println();
//practise string
//char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";

StaticJsonDocument <256> doc;
deserializeJson(doc,payload);

// deserializeJson(doc,str); can use string instead of payload
const char* sensor = doc["sensor"];
long time = doc["time"];
float latitude = doc["data"][0];
float longitude = doc["data"][1];

Serial.println("latitude =");
Serial.println(latitude,2);
Serial.println(sensor);

Notes:

The latest version of the MQTT client (2.8) allows you to change the size of the MQTT output buffer using setBufferSize(). However When I tried this it gave compile errors for my Ethernet board and I need to go back to v2.7.

Download Sketch

download

Related Tutorials and Resources

Please rate? And use Comments to let me know more

Leave a Reply

Your email address will not be published. Required fields are marked *