Requirements
Any device sending data to either a Plugin or an UbiFunction on Ubidots from any LoRaWAN network server.
The URL of the repository in which the device's decoder is hosted
1. Preliminary comments
If you haven't checked on the previous technical guide regarding Ubidots DaaS yet, we highly advise you to do so.
This technical guide uses a SenseCAP S2102 - LoRaWAN Wireless Light Intensity Sensor which is registered on TTS LNS, configured so that no decoding is performed on TTS's side. In other words, the raw binary data will arrive into Ubidots to use our DaaS.
2. Identify the decoder's entry point as well as the arguments it expects
As mentioned previously, this example uses a SenseCAP S2102 - LoRaWAN Wireless Light Intensity Sensor, so the URL of the repository hosting the device's decoder is needed.
Once you are on the repository's page, you should be able to see the decoder:
There may be several different functions defined, so you need to identify the decoder's entry point. Thankfully, most decoders are well commented and tell you exactly which one is the entry point.
Also, note in the following image, that this decoder declares and initializes a bytes variable with data contained inside the bytes key in the incoming arguments object, so if the incoming object doesn't have such key, the decoder will fail to execute from the very beginning.
With the above in mind, the decoder expects an object like the following on its arguments:
{
'bytes' : '01ABEDF5CD'
}
3. Build the request to use Ubidots' DaaS
As stated in the previous guide, the body of the request to use Ubidots' DaaS is a JSON as follows:
{
"url": "DECODER-URL-RAW-FORMAT",
"payload": {
DECODER-EXPECTED-OBJECT
},
"function": "DECODERS-ENTRY-POINT"
}
Where:
Key | Value |
url | The URL of the repository hosting the decoder. |
payload | An object matching the one expected by the decoder. |
function | The name of the decoder's main function or entry point. |
With that in mind, the body of a request for using Ubidots' DaaS on the SenseCAP S2102 - LoRaWAN Wireless Light Intensity should look like this:
{
"url": "https://raw.githubusercontent.com/Seeed-Solution/TTN-Payload-Decoder/master/decoder_new-v3.js",
"payload": {
'bytes' : '01ABEDF5CD' (A hex string)
},
"function": "decodeUplink"
}
Head to the plugin receiving the data and go to its decoder section. Then, in the code editor, do the following:
Import the library required for issuing the HTTP request:
const axios = require('axios');
Define and initialize the decoder's URL and entry point:
const decoderURL = 'https://raw.githubusercontent.com/Seeed-Solution/TTN-Payload-Decoder/master/decoder_new-v3.js';
const decoderEntryPoint = 'decodeUplink';
Declare the function to issue the request to the endpoint of Ubidots' DaaS:
async function DaaS(decoderURL, entryPoint, payloadToDecode, ubidotsToken)
{
var headers = {"X-Auth-Token": ubidotsToken, "Content-Type": "application/json"};
var payload =
{
"url" : decoderURL,
"payload" : payloadToDecode,
"function" : entryPoint
}
var options =
{
"method" : 'post',
"url" : 'http://functions.ubidots.com/pub/decode/custom',
"data" : payload,
"json" : true,
"headers" : headers,
};
const req = await axios.request(options);
return req.data.decoded;
}
Declare the function to build an Ubidots compatible payload from the one returned by the device's decoder. For this particular example, you can find such function in other of our technical guides. If you are using another device, you need to know what object the device's decoder returns in order to format it to an Ubidots-compatible JSON.
function buildUbidotsPayload(args)
{
var ubidotsPayload = {};
var messages = args.data.messages;
var varLabelMap =
{
4097:"air-temperature",
4098:"air-humidity",
4099:"light-intensity",
4100:"CO2-concentration",
4102:"soil-temperature",
4103:"soil-humidity",
4108:"soil-electrical-conductivity",
};
messages.forEach(msg =>
{
if (msg.hasOwnProperty("measurementId"))
{
ubidotsPayload[varLabelMap[msg.measurementId]] = msg["measurementValue"];
}
});
return ubidotsPayload;
}
Declare the main function:
async function formatPayload(args)
{
var ubidotsToken = args._parameters.token;
var incomingBinaryData = args.uplink_message.decoded_payload.payload;
var decodedData = await DaaS(decoderURL,decoderEntryPoint, {"bytes" : Buffer.from(incomingBinaryData,'hex')},ubidotsToken);
var ubidotsaPyload = buildUbidotsPayload(decodedData);
return ubidotsaPyload;
}
Lastly, the whole plugin's decoder should look like this:
const axios = require('axios');
const decoderURL = 'https://raw.githubusercontent.com/Seeed-Solution/TTN-Payload-Decoder/master/decoder_new-v3.js';
const decoderEntryPoint = 'decodeUplink';
async function formatPayload(args)
{
var ubidotsToken = args._parameters.token;
var incomingBinaryData = args.uplink_message.decoded_payload.payload;
var decodedData = await DaaS(decoderURL,decoderEntryPoint, {"bytes" : Buffer.from(incomingBinaryData,'hex')},ubidotsToken);
var ubidotsaPyload = buildUbidotsPayload(decodedData);
return ubidotsaPyload;
}
function buildUbidotsPayload(args)
{
var ubidotsPayload = {};
var messages = args.data.messages;
var varLabelMap =
{
4097:"air-temperature",
4098:"air-humidity",
4099:"light-intensity",
4100:"CO2-concentration",
4102:"soil-temperature",
4103:"soil-humidity",
4108:"soil-electrical-conductivity",
};
messages.forEach(msg =>
{
if (msg.hasOwnProperty("measurementId"))
{
ubidotsPayload[varLabelMap[msg.measurementId]] = msg["measurementValue"];
}
});
return ubidotsPayload;
}
async function DaaS(decoderURL, entryPoint, payloadToDecode, ubidotsToken)
{
var headers = {"X-Auth-Token": ubidotsToken, "Content-Type": "application/json"};
var payload =
{
"url" : decoderURL,
"payload" : payloadToDecode,
"function" : entryPoint
}
var options =
{
"method" : 'post',
"url" : 'http://functions.ubidots.com/pub/decode/custom',
"data" : payload,
"json" : true,
"headers" : headers,
};
const req = await axios.request(options);
return req.data.decoded;
}
module.exports = { formatPayload };
4. Visualizing the data
After successfully completing the steps above, your device should be displayed on Ubidots with its data: