ESP32: Deserializing MessagePack

In this tutorial we will learn how to deserialize a MessagePack payload, using ArduinoJson and the ESP32. The tests were performed using an ESP32 board from DFRobot.

Introduction

In this tutorial we will learn how to deserialize a MessagePack payload, using ArduinoJson and the ESP32.

For an introductory tutorial on how to serialize content to the MessagePack format, please check the previous tutorial.

In order to have a valid payload to test, we will serialize the following JSON to the MessagePack format:

{
    "sensorType": "temperature",
    "value": 10
}

We will be using this online tool, which allows to specify a JSON object and obtain the corresponding MessagePack payload, and vice-versa. If you have troubles using the tool, below is the expected output:

[130, 170, 115, 101, 110, 115, 111, 114, 84, 121, 112, 101, 171, 116, 101, 109, 112, 101, 114, 97, 116, 117, 114, 101, 165, 118, 97, 108, 117, 101, 10]

The tests shown here were performed using an ESP32 board from DFRobot and with version 6 of the ArduinoJson library.

The code

We will start the code by the ArduinoJson library include.

#include <ArduinoJson.h>

Then we will move to the Arduino setup function, where we will write the rest of the code. As usual, the first thing we do is opening a serial connection, to be able to output the result of our program.

Serial.begin(115200);

Then we will declare an array with the bytes of the MessagePack serialized content. This will be the payload we will try to deserialize.

uint8_t payload[] = {
    130, 170, 115, 101, 110, 115, 111, 114, 84, 121, 112,
    101, 171, 116, 101, 109, 112, 101, 114, 97, 116, 117,
    114, 101, 165, 118, 97, 108, 117, 101, 10
};

In order to be able to deserialize the content, we will need to declare an object of class StaticJsonDocument, to hold the memory representation of the parsed object.

Recall from the previous tutorials that we need to specify the capacity of the StaticJsonDocument when creating an object of this class. This capacity is specified in bytes, as a template parameter.

We will use the value 100, which is enough for the content we are deserializing. Nonetheless, for a more accurate estimation, please use this assistant.

StaticJsonDocument<100> testDocument;

To do the actual deserialization, we simply need to call the deserializeMsgPack function. As first input we need to pass the document that will hold the memory representation of the deserialized object and as second input the payload to deserialize [1].

As output, the function returns an object of class DeserializationError. You can check the implementation file for this class here. We will store this return value in a variable.

DeserializationError error = deserializeMsgPack(testDocument, payload);

To make sure the deserialization did not fail, we will check the returned DeserializationError object. Since the class overloads the C++ Boolean operator, we can enclose the object in an IF condition to check if some error has occurred.

If an error occurred, we can call c_str method to obtain the string representation of the error and print it to the serial port, to help debugging.

if (error) {
    Serial.print("Deserialization failed with error: ");
    Serial.println(error.c_str());
    return;
}

If no error occurs in the deserialization, we can then access the values from our object. To do it, we simply need to use the subscript operator [] on our StaticJsonDocument object, passing as input the key of the object to which we want to obtain the value.

Note that below we are going to be using implicit casts to obtain the values from the StaticJsonDocument. Nonetheless, ArduinoJson also supports explicit casting, as covered here in more detail.

const char* sensorType = testDocument["sensorType"];
int value = testDocument["value"];

To finalize, we will print to the serial port the values obtained.

Serial.println(sensorType);
Serial.println(value);

The final source code can be seen below.

#include <ArduinoJson.h>

void setup() {

  Serial.begin(115200);

  uint8_t payload[] = {
    130, 170, 115, 101, 110, 115, 111, 114, 84, 121, 112,
    101, 171, 116, 101, 109, 112, 101, 114, 97, 116, 117,
    114, 101, 165, 118, 97, 108, 117, 101, 10
  };

  StaticJsonDocument<100> testDocument;

  DeserializationError error = deserializeMsgPack(testDocument, payload);

  if (error) {
    Serial.print("Deserialization failed with error: ");
    Serial.println(error.c_str());
    return;
  }

  const char* sensorType = testDocument["sensorType"];
  int value = testDocument["value"];

  Serial.println(sensorType);
  Serial.println(value);
}

void loop() {}

Testing the code

To test the code, first compile it and upload it to your device, using the Arduino IDE. Once the procedure finishes, open the IDE serial monitor.

You should get an output similar to figure 1. As can be seen, we were able to obtain and print the values of the fields in the original JSON that we converted to the MessagePack representation.

 Output of the program on the Arduino IDE serial monitor
Figure 1 – Output of the program on the Arduino IDE serial monitor.

References

[1] https://arduinojson.org/v6/api/msgpack/deserializemsgpack/

Leave a Reply