Map widget cannot locate variable 'location' in the bucket

Hi

I have successfully added a device and on update it has loaded all the variable to the bucket on TagoIO.

The devices uses the following payload formatter on the TTI

function Decoder(bytes, port)
{
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var decoded = {};

if (port === 1)
{
decoded.type = “position”;

decoded.latitude = bytes[0] + bytes[1] * 256 + bytes[2] * 65536 + bytes[3] * 16777216;
if (decoded.latitude >= 0x80000000)
  decoded.latitude -= 0x100000000;
decoded.latitude /= 1e7;
  
decoded.longitude = bytes[4] + bytes[5] * 256 + bytes[6] * 65536 + bytes[7] * 16777216;
if (decoded.longitude >= 0x80000000)
  decoded.longitude -= 0x100000000;
decoded.longitude /= 1e7;
  
//decoded.inTrip = ((bytes[8] & 0x1) !== 0) ? true : false;
//decoded.fixFailed = ((bytes[8] & 0x2) !== 0) ? true : false;
//decoded.headingDeg = (bytes[8] >> 2) * 5.625;
decoded.manDown=((bytes[8]&0x4)!==0)?true:false;
decoded.speedKmph = bytes[9];
decoded.batV = bytes[10] * 0.025;

//decoded.location = decoded.latitude + ',' + decoded.longitude;

}
else if (port === 2)
{
decoded.type = “downlink ack”;

decoded.sequence = (bytes[0] & 0x7F);
decoded.accepted = ((bytes[0] & 0x80) !== 0) ? true : false;
decoded.fwMaj = bytes[1];
decoded.fwMin = bytes[2];

}
else if (port === 3)
{
decoded.type = “stats”;

decoded.initialBatV    = (((bytes[0] & 0xF) !== 0) ? (4.0 + (bytes[0] & 0xF) * 0.100) : null);
decoded.txCount        =  32 * ((bytes[0] >> 4) + (bytes[1]  & 0x7F) *  16);
decoded.tripCount      =  32 * ((bytes[1] >> 7) + (bytes[2]  & 0xFF) *   2
                                                + (bytes[3]  & 0x0F) * 512);
decoded.gpsSuccesses   =  32 * ((bytes[3] >> 4) + (bytes[4]  & 0x3F) *  16);
decoded.gpsFails       =  32 * ((bytes[4] >> 6) + (bytes[5]  & 0x3F) *   4);
decoded.aveGpsFixS     =   1 * ((bytes[5] >> 6) + (bytes[6]  & 0x7F) *   4);
decoded.aveGpsFailS    =   1 * ((bytes[6] >> 7) + (bytes[7]  & 0xFF) *   2);
decoded.aveGpsFreshenS =   1 * ((bytes[7] >> 8) + (bytes[8]  & 0xFF) *   1);
decoded.wakeupsPerTrip =   1 * ((bytes[8] >> 8) + (bytes[9]  & 0x7F) *   1);
decoded.uptimeWeeks    =   1 * ((bytes[9] >> 7) + (bytes[10] & 0xFF) *   2);

}

return decoded;
}

// add other functions (Converter, Validator) here if you used them. If you didn’t you can just skip them.

function decodeUplink(input) {
var data = input.bytes;
var valid = true;

if (typeof Decoder === “function”) {
data = Decoder(data, input.fPort);
}

if (typeof Converter === “function”) {
data = Converter(data, input.fPort);
}

if (typeof Validator === “function”) {
valid = Validator(data, input.fPort);
}

if (valid) {
return {
data: data
};
} else {
return {
data: {},
errors: [“Invalid data received”]
};
}
}

After device update the variable Latitude and Longitude appear in the bucket. As seen below

My problem is that the variable ‘location’ is not created by TagoIO internal process as the following documentation from TagoIO indicates.

TagoIO converts the latitude and longitude fields to the specific format so you don’t have to worry about any conversions. In order to accomplish that, you only need to have the variables latitude and longitude or lat and lng , and TagoIO will automatically get these values variables and create a new variable called location .

After you get your device to send the latitude and longitude information to TagoIO, create a dashboard and add a Map widget. Look for the device, and add the variable ’ location ’ inside the map.

I created my Map widget and added the devices with variable location,

But the devices are not displayed

MapDisplay

Am i doing something wrong. I have done this many time before with no problems. Is it because i am ussing TTI rather than TTN.

Any help appriciated.
Thanks
Flaxies.

Hi @flaxies
I saw a similar doubt as yours in the community a few times ago in the following link.
If you scroll down @vitor has the following answer about that documentation sentence

Could you see if this past post attends you?
Thanks Filipe.

My basic question wasn´t answered: if the TagoIO support is saying that I don´t need to do any conversions (highlighted text in the screenshot below), why the proposed solution is toc reate a conversion in the conector?

Hi @claudio.rosa,
If you send latitude and longitude directly from TTN, it should automatically parse to location. But it seems the same was not true for TTI, so I just updated the network integration to apply this.

This is not valid if you’re parsing this directly at TagoIO using your own connector or payload parser, as this function is ignored on Tago side to give you full control over your parser.

Can you check if it’s working for you now ?

Vitor,

This is the JS Decoder that I am using for tracking and environment informations. Now I need to take a drive to test, because the accelerometer, to save battery, make the device sleep, if I don´t have movements. Make it sense.

I will send News soon:

// ttn application function to decode uplink data.

// Decode decodes an array of bytes into an object.

// - port contains the LoRaWAN fPort number

// - bytes is an array of bytes, e.g. [225, 230, 255, 0]

// The function must return an object, e.g. {“temperature”: 22.5}

function Decoder(bytes, port) {

var decoded = {};

var hexString=bin2HexStr(bytes);

return rakSensorDataDecode(hexString);

}

// convert array of bytes to hex string.

// e.g: 0188053797109D5900DC140802017A0768580673256D0267011D040214AF0371FFFFFFDDFC2E

function bin2HexStr(bytesArr) {

var str = “”;

for(var i=0; i<bytesArr.length; i++) {

var tmp = (bytesArr[i] & 0xff).toString(16);

if(tmp.length == 1) {

tmp = “0” + tmp;

}

str += tmp;

}

return str;

}

// convert string to short integer

function parseShort(str, base) {

var n = parseInt(str, base);

return (n << 16) >> 16;

}

// convert string to triple bytes integer

function parseTriple(str, base) {

var n = parseInt(str, base);

return (n << 8) >> 8;

}

// decode Hex sensor string data to object

function rakSensorDataDecode(hexStr) {

var str = hexStr;

var myObj = {};

while (str.length > 4) {

var flag = parseInt(str.substring(0, 4), 16);

switch (flag) {

case 0x0768:// Humidity

myObj.humidity = parseFloat(((parseShort(str.substring(4, 6), 16) * 0.01 / 2) * 100).toFixed(1));//unit:%RH

str = str.substring(6);

break;

case 0x0673:// Atmospheric pressure

myObj.barometer = parseFloat((parseShort(str.substring(4, 8), 16) * 0.1).toFixed(2));//unit:hPa

str = str.substring(8);

break;

case 0x0267:// Temperature

myObj.temperature = parseFloat((parseShort(str.substring(4, 8), 16) * 0.1).toFixed(2));//unit: °C

str = str.substring(8);

break;

case 0x0188:// GPS

myObj.latitude = parseFloat((parseTriple(str.substring(4, 10), 16) * 0.0001).toFixed(4));//unit:°

myObj.longitude = parseFloat((parseTriple(str.substring(10, 16), 16) * 0.0001).toFixed(4));//unit:°

myObj.altitude = parseFloat((parseTriple(str.substring(16, 22), 16) * 0.01).toFixed(1));//unit:m

str = str.substring(22);

break;

case 0x0371:// Triaxial acceleration

myObj.acceleration_x = parseFloat((parseShort(str.substring(4, 8), 16) * 0.001).toFixed(3)) ;//unit:g

myObj.acceleration_y = parseFloat((parseShort(str.substring(8, 12), 16) * 0.001).toFixed(3)) ;//unit:g

myObj.acceleration_z = parseFloat((parseShort(str.substring(12, 16), 16) * 0.001).toFixed(3)) ;//unit:g

str = str.substring(16);

break;

case 0x0402:// air resistance

myObj.gasResistance = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2)) ;//unit:KΩ

str = str.substring(8);

break;

case 0x0802:// Battery Voltage

myObj.battery = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2));//unit:V

str = str.substring(8);

break;

case 0x0586:// gyroscope

myObj.gyroscope_x = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2)) ;//unit:°/s

myObj.gyroscope_y = parseFloat((parseShort(str.substring(8, 12), 16) * 0.01).toFixed(2));//unit:°/s

myObj.gyroscope_z = parseFloat((parseShort(str.substring(12, 16), 16) * 0.01).toFixed(2));//unit:°/s

str = str.substring(16);

break;

case 0x0902:// magnetometer x

myObj.magnetometer_x = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2));//unit:μT

str = str.substring(8);

break;

case 0x0a02:// magnetometer y

myObj.magnetometer_y = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2));//unit:μT

str = str.substring(8);

break;

case 0x0b02:// magnetometer z

myObj.magnetometer_z = parseFloat((parseShort(str.substring(4, 8), 16) * 0.01).toFixed(2));//unit:μT

str = str.substring(8);

break;

default:

str = str.substring(7);

break;

}

}

return myObj;

}

Vitor,

If the JS Decoder that I metioned in the previous e-mail is applied in the The Things Stack uplink, the TTI network and the connector that I created to my device, a RAKWireless Wistrio 5205, they can recognize the payload fields. But If I remove the JS Decoder from TTS, the connector and network in TagoIO, the don´t recognize anymore.

The attached files are showing the Inspector data files with and without JS Decoder applied in the The Thing Stack. You will see that now, we can see the correct Decoder processs when the JS Decoder is applied in the TTS uplink.

The problem is that in the TTS/TTI/TTN, we have this option, I mean to apply the JS Decoder in the uplink to TagoIO, but in the LoRaWAN Kerlink WMC, we don´t have the same option. Today I am working with two LNS, TTS and Kerlink, then I need to make the decoders works for both.

Is it clear for you?

Take a look the Inspector capture file without the JS Decoder in the TTS, but applied in the

(Attachment Inspector data 20210325 RAKWireless Wistrio tracker with JS Decoder TTS.txt is missing)

(Attachment Inspector data 20210325 RAKWireless Wistrio tracker without JS Decoder TTS.txt is missing)