Dragino LGT92 and TTN

I cannot seem to get the required position variable from my Dragino LGT92 fw1.64 on the TTN network.

I have tried various payload suggestions but they return erroneous lat/long coordinates. Can this be done by using a synthetic variable?

Here is my TTN payload that I am using. It does not contain the position variable. It is the version that works best but lacks the position.
function Decoder(bytes, port) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.

var latitude;//gps latitude,units: °
latitude=(bytes[0]<<24 | bytes[1]<<16 | bytes[2]<<8 | bytes[3])/1000000;//gps latitude,units: °

var longitude;
longitude=(bytes[4]<<24 | bytes[5]<<16 | bytes[6]<<8 | bytes[7])/1000000;//gps longitude,units: °

var alarm=(bytes[8] & 0x40)?“TRUE”:“FALSE”;//Alarm status

var batV=(((bytes[8] & 0x3f) <<8) | bytes[9])/1000;//Battery,units:V

if(bytes[10] & 0xC0==0x40)
{
var motion_mode=“Move”;
}
else if(bytes[10] & 0xC0 ==0x80)
{
motion_mode=“Collide”;
}
else if(bytes[10] & 0xC0 ==0xC0)
{
motion_mode=“User”;
}
else
{
motion_mode=“Disable”;
} //mode of motion

var led_updown=(bytes[10] & 0x20)?“ON”:“OFF”;//LED status for position,uplink and downlink

var Firmware = 160+(bytes[10] & 0x1f); // Firmware version; 5 bits

var roll=(bytes[11]<<8 | bytes[12])/100;//roll,units: °

var pitch=(bytes[13]<<8 | bytes[14])/100; //pitch,units: °

var hdop = 0;
if(bytes[15] > 0)
{
hdop =bytes[15]/100; //hdop,units: °
}
else
{
hdop =bytes[15];
}

var altitude =(bytes[16]<<8 | bytes[17]) / 100; //Altitude,units: °

return {
Latitude: latitude,
Longitude: longitude,
Roll: roll,
Pitch:pitch,
BatV:batV,
ALARM_status:alarm,
MD:motion_mode,
LON:led_updown,
FW:Firmware,
HDOP:hdop,
Altitude:altitude,
};
}

Hi @RockiesIOT

I just made a minor change to the returned object in your decoder:

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

    var latitude;//gps latitude,units: °
    latitude = (bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]) / 1000000;//gps latitude,units: °

    var longitude;
    longitude = (bytes[4] << 24 | bytes[5] << 16 | bytes[6] << 8 | bytes[7]) / 1000000;//gps longitude,units: °

    var alarm = (bytes[8] & 0x40) ?“TRUE”: “FALSE”;//Alarm status
    var batV = (((bytes[8] & 0x3f) << 8) | bytes[9]) / 1000;//Battery,units:V
    if (bytes[10] & 0xC0 == 0x40) {
        var motion_mode =“Move”;
    }
    else if (bytes[10] & 0xC0 == 0x80) {
        motion_mode =“Collide”;
    }
    else if (bytes[10] & 0xC0 == 0xC0) {
        motion_mode =“User”;
    }
    else {
        motion_mode =“Disable”;
    } //mode of motion

    var led_updown = (bytes[10] & 0x20) ?“ON”: “OFF”;//LED status for position,uplink and downlink
    var Firmware = 160 + (bytes[10] & 0x1f); // Firmware version; 5 bits
    var roll = (bytes[11] << 8 | bytes[12]) / 100;//roll,units: °
    var pitch = (bytes[13] << 8 | bytes[14]) / 100; //pitch,units: °
    var hdop = 0;
    
    if (bytes[15] > 0) {
        hdop = bytes[15] / 100; //hdop,units: °
    }
    else {
        hdop = bytes[15];
    }

    var altitude = (bytes[16] << 8 | bytes[17]) / 100; //Altitude,units: °

    return {
        position: {"value": 1, "context": {"lat": latitude, "lng": longitude}},
        Roll: roll,
        Pitch: pitch,
        BatV: batV,
        ALARM_status: alarm,
        MD: motion_mode,
        LON: led_updown,
        FW: Firmware,
        HDOP: hdop,
        Altitude: altitude,
    };
}

Let me know if this indeed works.

Thanks for your help, it did not seem to work. Below did work -

var position;
position = {“value”: 1, “context”: {“lat”: latitude, “lng”: longitude}};
return {
Position: position,

This returned -

“Position”: {
“context”: {
“lat”: 51.176088,
“lng”: -115.563889
},
“value”: 1

Update - I moved the app and device to v3 of TTS and it stopped working. The payload looks good in TTS and everything arrives in UBIDOTS except the position. Any advice?

Payload is -
“decoded_payload”: {
“ALARM_status”: “FALSE”,
“Altitude”: 0,
“BatV”: 4.03,
“FW”: 162,
“HDOP”: null,
“LON”: “ON”,
“Latitude”: 51.176012,
“Longitude”: -115.564433,
“MD”: “Disable”,
“Pitch”: 0,
“Roll”: 0,
“position”: {
“context”: {
“lat”: 51.176012,
“lng”: -115.564433
},
“value”: 1
}
},

Hello @RockiesIOT

I know you’ve already created your The Things Stack plugin to integrate your data coming from the new TTS v3 community version. That’s great by the way.
Now, I’ve inspected the logs of your plugin, that you can found here and then going to respective section

This plugin not only sends the variables in the “decoded_payload” key but also adds others from the metadata sent by TTS. However this conflicts with the STEM accounts limitations, particularly the 10 variables per Device hard stop.
With this in mind, you’ll see that our API response says “You have exceeded the maximum number of variables that can be created” for some of the variables.

I recommend the following:

  1. Change your decoder within The Things Stack to match the below format. Pay attention to the comments I’m leaving in the JSON
    Doing this will reduce you number of variables to 9 and guarantee the correct format.
{
 “ALARM_status”: "FALSE", // Ubidots doesn't accept string values. Change "FALSE" to 0 and "TRUE" to 1
 “BatV”: 4.036,
 “FW”: 162,
 “HDOP”: null, // Same here. Null isn't valid. If null don't send this variable
 “LON”: “ON”, // Change "ON" to 1 and "OFF" to 0
 “MD”: “Disable”, // This one needs changing as well
 “Pitch”: 0,
 “Roll”: 0,
 “position”: {
  “value”: {altitude}, // Instead of sending the Altitude as a separate variable, send it as a the value for the "position" variable
  “context”: {
   “lat”: 51.176432,
   “lng”: -115.563465
  }
}
  1. Update the decoder code (found above the Logs) to the following:
    I’ve removed all of the extra metadata added to the payload. With this, only the variables coming in decoded_payload will be sent to Ubidots.
function format_payload(args) {
    console.log(`args from TTS: ${JSON.stringify(args)}`);
    var ubidots_payload = {};
    
    // Get uplink's timestamp
    ubidots_payload['timestamp'] = new Date(args['uplink_message']['received_at']).getTime(); 
    
    // See if there's a decoded payload already 
    var decoded_payload = {};
    if("decoded_payload" in args['uplink_message']){
      // If "uplink_message.decoded_payload" is found, then it will be used, and "uplink_message.frm_payload" will be ignored
      decoded_payload = args['uplink_message']['decoded_payload'];
      console.log(`Decoded payload found! --> ${JSON.stringify(decoded_payload)}`);
    }
    else{
      // If no decoded_payload was found, then decode "uplink_message.frm_payload" here:
      let bytes = new Buffer(args['uplink_message']['frm_payload'], 'base64');
      decoded_payload = decodeUplink(bytes)['data'];
    }

    // Merge decoded payload into Ubidots payload
    Object.assign(ubidots_payload, decoded_payload);

    return ubidots_payload
}

function decodeUplink(bytes) {
  // Decoder for the RAK1906 WisBlock Environmental Sensor (https://store.rakwireless.com/products/rak1906-bme680-environment-sensor)
    var decoded = {};
  
    if (bytes[0] == 1) {
        // If received data is of Environment Monitoring type
        decoded.temperature = (bytes[1] << 8 | (bytes[2])) / 100;
        decoded.humidity = (bytes[3] << 8 | (bytes[4])) / 100;
        decoded.pressure = (bytes[8] | (bytes[7] << 8) | (bytes[6] << 16) | (bytes[5] << 24)) / 100;
        decoded.gas = bytes[12] | (bytes[11] << 8) | (bytes[10] << 16) | (bytes[9] << 24);
    } 
    return {"data": decoded};
}

module.exports = { format_payload };
  1. Delete the variables “altitude”, “F port”, “Frame counter”, “latitude” and “longitude” to make room for the others.

UPDATE: By the way, I already modified the TTS decoder to reflect the changes proposed in point 1 except for the condition for the “HDOP” variable.

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

    var latitude;//gps latitude,units: °
    latitude = (bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]) / 1000000; // gps latitude,units: °

    var longitude;
    longitude = (bytes[4] << 24 | bytes[5] << 16 | bytes[6] << 8 | bytes[7]) / 1000000; // gps longitude,units: °

    var alarm = (bytes[8] & 0x40) ? 1 : 0; // Alarm status
    var batV = (((bytes[8] & 0x3f) << 8) | bytes[9]) / 1000; // Battery,units:V
    if (bytes[10] & 0xC0 == 0x40) {
        var motion_mode = "Move";
    }
    else if (bytes[10] & 0xC0 == 0x80) {
        motion_mode = "Collide";
    }
    else if (bytes[10] & 0xC0 == 0xC0) {
        motion_mode = "User";
    }
    else {
        motion_mode = "Disable";
    } //mode of motion

    var led_updown = (bytes[10] & 0x20) ? 1 : 0; // LED status for position,uplink and downlink
    var Firmware = 160 + (bytes[10] & 0x1f); // Firmware version; 5 bits
    var roll = (bytes[11] << 8 | bytes[12]) / 100; // roll,units: °
    var pitch = (bytes[13] << 8 | bytes[14]) / 100; // pitch,units: °
    var hdop = 0;

    if (bytes[15] > 0) {
        hdop = bytes[15] / 100; // hdop,units: °
    }
    else {
        hdop = bytes[15];
    }

    var altitude = (bytes[16] << 8 | bytes[17]) / 100; // Altitude,units: °

    return {
        position: { "value": altitude, "context": { "lat": latitude, "lng": longitude } },
        Roll: roll,
        Pitch: pitch,
        BatV: batV,
        ALARM_status: alarm,
        MD: { "value": 1, "context": { "md": motion_mode } },
        LON: led_updown,
        FW: Firmware,
        HDOP: hdop,
    };
}

Best,

–David

1 Like

Thank you for your assistance.

FYI In other news - Using a RAK7249 on V3 of TTS in basic station mode does not seem to work. RAK is troubleshooting the issue, might be a certificate issue. In the meantime use packet forwarder instead.