Payload Decoders

LoRa devices send their readings as bytes instead of a full JSON object in order to save bandwidth. For Datacake to be able to process and store the sent measurements, you need a piece of JavaScript code called a Payload Decoder.

A Payload Decoder takes a buffer (list of bytes) as well as the port of the message and converts them to a normalized object Datacake can understand.

A simple Payload Decoder

Imagine a LoRa sensor sending a single measurement, which is a float indicating a temperature.

To encode this measurement, one could use the following code:

float temperature = 23.5;
byte payload[1];
payload[0] = round(temperature * 100);

In this example, we are first convert the float to an integer without losing precision by multiplying it with 100. To decode it back to a float, we simply divide it by 100 again. The following code is an example, how a Payload Decoder can look on the Datacake platform.

function Decoder(payload, port) {
if(port === 1) {
return [
{
field: "TEMPERATURE",
value: payload[0] / 100
}
];
}
}

As you can see, a Payload Decoder must contain a function Decoder which takes the payload and port as arguments and returns a list of measurements in the {field: str, value: any, timestamp?: number} format.

Recording multiple measurements

A Payload Decoder can return a list of an arbitrary number of measurements.

function Decoder(payload, port) {
return [
{
field: "FIELD1",
value: true
},
{
field: "FIELD2",
value: false
}
];
}

Recording historic data

Some LoRa devices send an aggregated list of measurements for e.g. the last hour. Each measurement can take an optional timestamp parameter which is a UNIX timestamp (seconds since Jan 01 1970 (UTC)).

function Decoder(payload, port) {
return [
{
field: "FIELD1",
value: true,
timestamp: 1589815300
},
{
field: "FIELD1",
value: false,
timestamp: 1589811700
}
];
}

​

Accessing metadata

You can access the global variable normalizedPayload which contains the following metadata:

{
"deveui": string, // The device's DevEUI
"port": number, // The message's port
"counter": number,
"frequency": number, // GHz
"data_rate": string, // Data rate according to https://blog.dbrgn.ch/2017/6/23/lorawan-data-rates/
"coding_rate": string,
"gateways": [
"id": string,
"datetime": date,
"channel": number,
"rssi": number,
"snr": number
]
}

This data is normalized from the LNS' payload. If you rather want to access the raw payload received from the LNS, you can do so via the global rawPayload variable.

Please note that when you access the rawPayload, the payload decoder will most likely not work with other LoRa network servers.

Tips and tricks

Execution time

A Payload Decoder must not take longer than 100ms (milliseconds) to return, otherwise its execution will be aborted and you will find a note on the Debug tab of the device.

Access to base64-encoded payload

The base64-encoded payload is available via the global b64payload-variable.

Converting the buffer to a string

You should avoid sending strings over LoRa, since text uses a lot of bytes. You can still decode the buffer to string using:

String.fromCharCode.apply(null, payload);