# How to build an MQTT Payload Parser

**URL:** <https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032>\
**Category:** Tutorials\
**Tags:** tutorials\
**Created:** [January 22, 2022, 7:46pm UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032 "2022-01-22T19:46:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://yyz2.discourse-cdn.com/flex034/user_avatar/community.tago.io/system/32/24_2.png) [@system](https://community.tago.io/u/system)\
**Post date:** [January 22, 2022, 7:46pm UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032/1 "2022-01-22T19:46:09Z")

</div>

@Vitor Lima

As MQTT has the freedom of sending data in the format you want, you will need to normalize the data to the TagoIO format by using the Payload Parser.

> 📝 This tutorial expects you to have read the [In-depth guide to Payload Parser - How to - TagoIO Community](https://community.tago.io/t/in-depth-guide-to-payload-parser).

Of course, you can skip all this tutorial by making sure you’ve already sent in the correct format, which is a json array with **at least** the parameters **variable** and **value**. Check out more about it here: [Sending Data - TagoIO](https://help.tago.io/portal/en/kb/articles/34-sending-data).

But if this is not your case, I’ll try to provide some guidance on the most common use cases.

* * *

# Publishing hexadecimal payload only.

If you came to just publish a hexadecimal, such as **“001100”** , make sure that you’re sending it with the quotation marks so it doesn’t get interpreted as a number, the content of your **payload** parameter will be like:

```auto
[{ "variable": "payload", "value": "001100", "metadata": { "mqtt_topic": "data" } }]

```

I recommend you start with this code, it will transform it to a Buffer and you can use all the knowledge you got from this tutorial to parse it.

```javascript
/* This is a generic payload parser that can be used as a starting point for MQTT devices
** The code expects to receive a string hexadecimal data, and not JSON formatted data.
**
** Testing:
** You can do manual tests to the parse by using the Device Emulator. Copy and Paste the following JSON:
** [{ "variable": "payload", "value": "0109611395", "metadata": { "mqtt_topic": "data" } }]
*/

// Prevents the code from running for other types data insertions.
// We search for a variable name payload or a variable with metadata.mqtt_topic
const mqtt_payload = payload.find((data) => data.variable === "payload" || (data.metadata && data.metadata.mqtt_topic));
if (mqtt_payload) {
  // Cast the hexadecimal to a buffer.
  const buffer = Buffer.from(mqtt_payload.value, 'hex')

 // Normalize the data to TagoIO format.
 // We use Number function to cast number values, so we can use it on chart widgets, etc.
  const data = [
    { variable: 'protocol_version', value: buffer.readInt8(0) },
    { variable: 'temperature', value: buffer.readInt16BE(1) / 100, unit: '°C' },
    { variable: 'humidity', value: buffer.readUInt16BE(3) / 100, unit: '%' },
  ];

  // This will concat the content sent by your device with the content generated in this payload parser.
  // It also adds the field "serie" to be able to group in tables and other widgets.
  const serie = String(new Date().getTime());
  payload = payload.concat(data).map(x => ({ ...x, serie }));
}

```

* * *

# Publishing a comma separated payload.

Comma separated values will require you to first split your string in an array, and then start to pick your values from the new generated array. Is it good to remember that an Array in Javascript starts from index 0.  
If your data does have change on it’s length, you will need to resolve this problem by using IF’s or a For function.

```javascript
/* This is a generic payload parser that can be used as a starting point MQTT devices
** The code expects to receive comma separated data, and not JSON formatted data.
**
** Testing:
** Testing:
** You can do manual tests to the parse by using the Device Emulator. Copy and Paste the following JSON:
** [{ "variable": "payload", "value": "temp,12,hum,50", "metadata": { "mqtt_topic": "data" } }]
*/

// Prevents the code from running for other types data insertions.
// We search for a variable name payload or a variable with metadata.mqtt_topic
const mqtt_payload = payload.find((data) => data.variable === "payload" || (data.metadata && data.metadata.mqtt_topic));
if (mqtt_payload) {
  // Split the content by the separator , 
  const splitted_value = mqtt_payload.value.split(',');
  // splitted_value content will be ['temp', '12', 'hum', '50']
  // index starts from 0

 // Normalize the data to TagoIO format.
 // We use Number function to cast number values, so we can use it on chart widgets, etc.
  const data = [
    { variable: 'temperature', value: Number(splitted_value[1]), unit: '°C' },
    { variable: 'humidity', value: Number(splitted_value[3]), unit: '%' },
  ];

  // This will concat the content sent by your device with the content generated in this payload parser.
  // It also adds the field "serie" to be able to group in tables and other widgets.
  const serie = String(new Date().getTime());
  payload = payload.concat(data).map(x => ({ ...x, serie }));
}

```

* * *

# Publishing a JSON payload, not TagoIO data format.

In this case we recommend you start with the snippet “Convert Raw JSON to TagoIO JSON”. It has all the comments you need and a quick function to transform the JSON for you.

 ![image](https://canada1.discourse-cdn.com/flex034/uploads/tagoio1/original/2X/1/1acfa72e756ed416dd07a0e0e1e49039b6b19268.png)

* * *

# Common mistakes

- **Payload Parser is not running**

If you’re sending data through your MQTT device, but it’s not being stored and neither running your payload parser, it can be that you didn’t setup an Action for your device.

It looks like that:

 ![image](https://canada1.discourse-cdn.com/flex034/uploads/tagoio1/original/2X/a/a0224979213508d965f368e59da69cb688ab8c76.png)

You can either go to your Actions page and create an Action of type **MQTT** for your device, and set the action to **Stored data to bucket** , or change your topic to **tago/data/post** , as it will have the same effect. You can read the tutorial in the following link [MQTT - TagoIO](https://help.tago.io/portal/en/kb/articles/32-mqtt).

At the end, your Live Inspector will look like this:

 ![image](https://canada1.discourse-cdn.com/flex034/uploads/tagoio1/original/2X/0/0d4d2cda2f84cba395a2806a131dba5d80a1662e.png)

- **Can’t display my variable in charts and some widgets**

This is a very common mistake where you send a variable as a string and not a number. Data type does matter when using widgets on TagoIO.  
A value of a variable can be a boolean, a number or a string. Inside the Payload Parser, it’s very common for data to be received as a string by default when using MQTT. You can easily fix that problem by casting your value to a number, as follows:

```auto
const data = [
    { variable: 'temperature', value: Number(splitted_value[1]), unit: '°C' },
    { variable: 'humidity', value: Number(splitted_value[3]), unit: '%' },
  ];

```

Instead of

```auto
const data = [
    { variable: 'temperature', value: splitted_value[1], unit: '°C' },
    { variable: 'humidity', value: splitted_value[3], unit: '%' },
  ];

```

---

<div class="post-metadata">

**Author:** ![bill.bianeck](https://avatars.discourse-cdn.com/v4/letter/b/2bfe46/32.png) [@bill.bianeck](https://community.tago.io/u/bill.bianeck)\
**Post date:** [April 4, 2022, 5:02pm UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032/2 "2022-04-04T17:02:55Z")

</div>

very useful content, building a MQTT Payload Parser is one of the first steps I had to learn to start my own project!

---

<div class="post-metadata">

**Author:** ![desenvolvimento](https://avatars.discourse-cdn.com/v4/letter/d/94ad74/32.png) [@desenvolvimento](https://community.tago.io/u/desenvolvimento)\
**Post date:** [June 26, 2023, 6:51pm UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032/3 "2023-06-26T18:51:48Z")

</div>

Dear Team,

How can I access the MQTT topic name in the analysis, please?

My analysis is correctly triggered by an action, nevertheless, my variable context doesn’t has the name of the topic:

 ![](https://canada1.discourse-cdn.com/flex034/uploads/tagoio1/original/2X/b/b6b1c9726f8a5e05cb813179b167d908873436e9.png)

Thank you.

---

<div class="post-metadata">

**Author:** ![freddy.minuzzi](https://yyz2.discourse-cdn.com/flex034/user_avatar/community.tago.io/freddy.minuzzi/32/415_2.png) [@freddy.minuzzi](https://community.tago.io/u/freddy.minuzzi)\
**Post date:** [June 27, 2023, 2:11pm UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032/4 "2023-06-27T14:11:51Z")

</div>

Hi Desenvolvimento,

In order to see what topic it’s related to you should print out the scope. Since the data is what contains the topic

const { Analysis } = require(“@tago-io/sdk”);

async function mqttPushExample(context, scope) {

console.log(context);

console.log(scope);

}

module.exports = new Analysis(mqttPushExample);

This code here is being activated by a action which is monitoring the topic: “testing” on a device. It will result it displaying the following information including the **topic** :

[2023-06-27 11:08:39] Analysis finished.

[2023-06-27 11:08:39] [{ variable: ‘payload’, value: ‘7b0a2020226d7367223a202268656c6c6f220a7d’, metadata: **{ mqtt\_topic: ‘testing’ }** }]

[2023-06-27 11:08:39] { log: [Function: log], token: ‘a-5a2da5ac-582c-471f-bdfd-4d2ed7cf184e’, environment: [{ key: ‘’, value: ‘’ }, { key: ‘\_action\_id’, value: ‘648a1f057f5dc300080af8ef’ }, { key: ‘\_action\_type’, value: ‘mqtt\_topic’ }], analysis\_id: ‘645aa43d67866700096a50d6’ }

[2023-06-27 11:08:38] Starting Analysis…

Hope this helps!

---

<div class="post-metadata">

**Author:** ![desenvolvimento](https://avatars.discourse-cdn.com/v4/letter/d/94ad74/32.png) [@desenvolvimento](https://community.tago.io/u/desenvolvimento)\
**Post date:** [June 28, 2023, 9:27am UTC](https://community.tago.io/t/how-to-build-an-mqtt-payload-parser/1032/5 "2023-06-28T09:27:35Z")

</div>

Hi, Freddy!

You’re right, I’m so used to typing _scope[0]_ that I didn’t remember about the other info in scope haha

Thank you again 🙂
