Not receiving variables from TTS

Hi, I am trying to get variables from my devices but seeing only metadata: f_cnt, f_port, rssi, snr.
I have multiple devices in one TTS application. For each device I am using their own payload formatter in TTS (not application payload formatter). I’ve created TTS plugin in Ubidots and have it running. In Plugin Decoder Settings I did uncomment line 37: var decoded_payload = args[‘uplink_message’][‘decoded_payload’]; but still not receiving variables (Batt, Temp, Hum etc.) How to make it work?

Do we need lines 48-59? Since this portion is related to decodeUplink of RAK1906 WisBlock.

Greetings, hope you are having a nice day.
Could you please attach here the log of the plugin execution?
Also, it would be helpful to know what device you are using.

I think the problem is that, may be, the device you are using encodes the data in a different way than the RAK1906 WisBlock Environmental Sensor. E.g. :

RAK1906 WisBlock Environmental Sensor encodes in the following way:

temperature = bytes[1], bytes[2]
humidity = bytes[3], bytes[4];
pressure = bytes[5], bytes[6], bytes[7], bytes[8]
gas = bytes[9], bytes[10], bytes[11], bytes[12]

It may happen that your device encodes data in a different way than this and so, the decodeUplink function won’t work properly.

I recommend you to double check the way in which your device encodes data.
Best.

{
“success”: true,
“message”: {
“results”: [
{
“f_cnt”: [
{
“status_code”: 201
}
],
“f_port”: [
{
“status_code”: 201
}
],
“rssi-iotsysgw”: [
{
“status_code”: 201
}
],
“snr-iotsysgw”: [
{
“status_code”: 201
}
]
}
]
}
}

I am using Dragino LHT65 and MileSight AM307.
I believe function decodeUplink(bytes) for RAK1906 is given as an example. Right?
I am not very familiar with programming languages and encoding/decoding payload. So copy/pase solution would be nice.
Do I need to create a separate plugin for each device? Or there is a way to have one plugin for multiple devices?
Thank you.

Greetings.

The problem is related to using the wrong decoder function.
Your decoder functions is intended for the RAK1906 WisBlock Environmental Sensor, not the LHT65 nor the AM307.

About having two different plugins for each device, it is advisable that each different type of device has its own plugin, since every device encodes data differently and so, a different decoder function is needed for each type of device.

You can just use one plugin if you want to, but then you would need a way to identify the type of device in order to execute the appropriate decoder.

Given the fact that you are using two different devices than the RAK1906, I would advise you to use a plugin for each device, then, modify the decoder function accordingly to how the device encodes the data.

Best

Understood. So I will create separate plugins for each type of devices.
But the problem is that I don’t have programming experience and I am not going to learn JavaScipt to just get the readings from sensor. Is there a copy/paste solution?
Lets say I have several customers with multiple different sensors. In this case for every client and every sensor I need to create a separate application and plugin with it’s own decoding function? If this is the case then it is not very convenient.

Thankfully, we have dealt with the LHT65 before, so we have the solution right at hand.

Please go to the decoder section on your TTN plugin, delete all the code and paste the following one.
Take into account that I have pointed out (upper case comment) some sections that you can comment if you wish to disable meta data.

function format_payload(args){
  var ubidots_payload = {};
  // Log received data for debugging purposes:
  // console.log(JSON.stringify(args));

  //COMMENT FROM HERE 

  // Get RSSI and SNR variables using gateways data:
  var gateways = args['uplink_message']['rx_metadata'];
  for (const i in gateways) {  
    // Get gateway EUI and name
    var gw = gateways[i];
    var gw_eui = gw['gateway_ids']['eui'];
    var gw_id = gw['gateway_ids']['gateway_id'];
    // Build RSSI and SNR variables
    ubidots_payload['rssi-' + gw_id] = {
      "value": gw['rssi'],
      "context": {
        "channel_index": gw['channel_index'],
        "channel_rssi": gw['channel_rssi'],
        "gw_eui": gw_eui,
        "gw_id": gw_id,
        "uplink_token": gw['uplink_token']
      }
    }
    ubidots_payload['snr-' + gw_id] = gw['snr'];

  }
  
  // Get Fcnt and Port variables:
  ubidots_payload['f_cnt'] = args['uplink_message']['f_cnt'];
  ubidots_payload['f_port'] = args['uplink_message']['f_port'];
  
  //TO HERE, TO REMOVE META DATA

  // Get uplink's timestamp
  ubidots_payload['timestamp'] = new Date(args['uplink_message']['received_at']).getTime(); 

  var decoded_payload = args['uplink_message']['decoded_payload'] ;
  delete decoded_payload['Ext_sensor'];
  // Merge decoded payload into Ubidots payload
  Object.assign(ubidots_payload, decoded_payload);
  return ubidots_payload
}
module.exports = { format_payload };

Best.

Thank you for your assistance. But what if I need to retrieve data from other sensors. Where should I look? Or how to compile a decoder function?

Greetings.

I’d dare to say that 99% of the manufacturers provide a decoder along with the device documentation, so, at first instance, I would advise you to attend the device’s documentation in order to understand how is the data encoded.

From my experience I can tell that there are some devices supported on TTN which are already provided with a decoder function (payload formatter) and all you have to do after routing that data to Ubidots is to extract the appropriate keys from the JSON object. I.E. as in the line var decoded_payload = args['uplink_message']['decoded_payload'] ;

You can reach to us if any other question arises.
Cheers.

I did use manufacturers decoder for all devices in TTS side (payload formatter) but variables weren’t sent (decoded) to Ubidots. I wasn’t able to extract variables from frm_payload.

Most of the time, TTS would provide you with the device’s decoder, which they call payload formatter. After the data has been decoded and transformed in a JSON object, it is sent to Ubidots in a format according to TTS JSON schema, which differs a little from Ubidots JSON schema.

Actually, data was being sent to Ubidots, however, it was being accessed in the wrong way on the plugin’s decoder and so, no data was displayed on the device/widget.

When data is sent from TTS to Ubidots, 90% of the time it would come already decoded (no need to decode from Base 64) in the following format:

var decoded_payload = args['uplink_message']['decoded_payload'] ;

I.E: if the decoder on TTS sends temperature data in a key “temperature”, then, from the Ubidots decoder side, you would access that data by doing something like:

var decoded_payload = args['uplink_message']['decoded_payload'] ;
var tempData = decoded_payload["temperature"]

In summary: TTN will provide you with the decoder most of the times, so, on Ubidots’ side, all you have to do is access the key which contains the data.

Best.

Greetings, hope you are doing great.

I just wanted to know if you were able to receive data successfully, and also, mention a few things:

  • Since TTN provides you with decoder functions for a wide variety of devices, all you have to do on Ubidots side is to access the correct JSON object key.
  • Every time that TTN sends a payload to the Ubidots TTN plugin, It will send a JSON which contains the data inside the following keys: ['uplink_message']['decoded_payload']

Imagine that you have a sensor capable of measuring temperature, humidity and pressure. This sensor is sending data to Ubidots from TTN, then in order to access each variable, you’d only have to do this (assuming that TTN decoder names variables in this way)

var payload = args["uplink_message"]["decoded_payload"] ;
var temperature = payload["temperature"] ;
var humidity = payload["humidity"] ;
var pressure = payload["pressure"] ;
  • Given the fact that, on Ubidots side, you don’t actually decode but only access the required JSON object keys, it is advisable to use only one plugin for all your TTN projects. This way you will surely have things more organized by being in one place.

In your particular case, I think this decoder function will work great, so please go to your TTS-Ubidots plugin and edit the decoder like this:

function format_payload(args){
  var ubidots_payload = {};

  // Get uplink's timestamp
  ubidots_payload['timestamp'] = new Date(args['uplink_message']['received_at']).getTime(); 

  var payload = args['uplink_message']['decoded_payload'] ;
  delete decoded_payload['Ext_sensor'];
  // Merge decoded payload into Ubidots payload
  Object.assign(ubidots_payload, decoded_payload);
  return ubidots_payload
}
module.exports = { format_payload };

Best.
-Juan David-

Hello Juan & Andy (IOTsys),

Andy - I’m wondering - are you using official TTN - like on their network - or perhaps using their 10 unit eval system? Or did you use the TTS and put it on your own server.

I’m doing similar things - in fact I provisioned 3x LHT65N from Dragino (love them and the nice battery) and 1x LHT52 (I’m lukewarm on them). All of these should have decoders defined in the TTS/N repository and I have been able to have them work “stock” - without mods.

I’ve had more trouble with Milesight decoders which I’ve ended up writing my own. I have only ONE PLUGIN going to ONE Ubidots DEVICE TYPE. I need to actually figure out how to do more Device Types - one per device going to my plugin.

I like having one plugin for TTS since that simplifies things. I’m hoping the Ubidots team is listening in (pls make a duplicate-device-type UX function).

One neat thing about Ubidots is that if the JSON package gets sent correctly - it looks like you are 90% there - that Ubidots “just does the right thing”.

Anyway welcome to Ubidots community.

Cheers,
Marlan