GlobalSat LT-20L and TagoIO GPS Decoder

Hi Guys,

I am struggling with the decoder for the GlobeSAT LT20-L Tracker. I am using TagoIO but I need TTN to post the decoded data to TagoIO.

Here is a preview of a String that comes from the device.
800248F813398DDD423C00
800247F813398DDD423C00
800246F8133B8DDD423C00

Here are the parameters for the bits.

lt20 parameters

This is also in the file they gave me.

lt20 gps

If anyone could please help me with a decoder that would be fantastic.

Regards
G

1 Like

Have you looked at some of the decoders already written? How good is your JavaScript?

Hy Gerhardt
I have more or less the same problem with the GlobeSat LT-20 tracker. Have you been able to fix the problem?

1 Like

We didn’t hear anymore on this from @gerhardtsiebert. I hinted there were decoders to be searched for and we can help with tweaking any JavaScript

I’ve been working on recycling these…

https://docs.microshare.io/docs/2/technical/microshare-platform-advanced/robots-libraries/globalsat-lt-100/

Will need to be adapted…
Otherwise…

function Decoder(bytes) {
var Battery = bytes[2];
var d = (bytes[3]<<24) | (bytes[4] <<16) | (bytes[5]<<8) | (bytes[6]);
var e = (bytes[7]<<24) | (bytes[8] <<16) | (bytes[9]<<8) | (bytes[10]);
var Longitude = parseInt(e) * 0.000001;
var Latitude = parseInt(d) * 0.000001;

return {Battery:Battery,Latitude:Latitude,Longitude:Longitude};

}

Ive made the longitude decode work… but struggling for a correct latitude. also Im southern hemisphere… so the negative is likely causing issues with the decode…

i tried subtracting 180 and still not right.

 // Sydney: -33.8688, 151.2092 = MSB FAD500 17129C, LSB 00D5FA 9C1217
 // 8002 2C3252 64EFD2 42 4B 00
 // Perth: -31.95224, 115.8614 == LSB 2D3252 66EFD2 
 // Stirling -31.896675, 115.815534
/*
80022B325261EFD2424100

8002 protocol and command
2B3252 longitude
61EFD2 latitude
42 gps
41 batt
00 preserved

  "frm_payload": "gAIrMlJh79JCQQA=",
  "decoded_payload": {
    "Battery": 65,
    "LatiHex": "D2EF61",
    "Latitude": 149.2974828,   ** still not right ???
    "LongHex": "52322B",
    "Longitude": 115.8160925

 */


function Decoder(bytes) {
//protocol version
var a = bytes[0];
//command id
var b = bytes[1];
//longitude - little endian
var c = (bytes[2] | bytes[3]<<8 | bytes[4]<<16 ) ;
//latitude - little endian
var d = (bytes[5] | bytes[6]<<8 | bytes[7]<<16 ) ; 
//gps fix status and report type
var e = bytes[8];
//battery capacity
var f = bytes[9];
//preserved
var g = bytes[10];
//convert as per guide - little endian and then multiple/divide etc
var Longitude = parseInt(c) * 215 / 10 * 0.000001;
var Latitude = parseInt(d) *108 / 10 * 0.000001;
//check hex little endian is swapping correctly
var Long = c.toString(16).toUpperCase();
var Lati = d.toString(16).toUpperCase();
//display battery level - little endian
var Battery = parseInt(f)

return {LongHex:Long,LatiHex:Lati, Longitude:Longitude, Latitude:Latitude, Battery:Battery};
}

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"]
    };
  }
}

I have come across the following kinda interesting code for the LT-20. Ive not yet made it work in TTN but its got some interesting (for me as a nonproficient codehacker manipulator).
I have questioned the github owner around the validity of the calculation as it doesnt match the PDF manual (or the image at the top of this thread).

akenza-io device-type-library globalsat LT-20 uplink.js

function toLittleEndian(hex) {
var data = hex.match(/…/g);
// Create a buffer
var buf = new ArrayBuffer(4);
// Create a data view of it
var view = new DataView(buf);
// set bytes
data.forEach(function (b, i) {
view.setUint8(i, parseInt(b, 16));
});
// get an int32 with little endian
var num = view.getInt32(0, 1);
return num;
}

function consume(event) {
var payload = event.data.payload_hex;
var bits = Bits.hexToBits(payload);
var data = {};
var protocolVersion = Bits.bitsToUnsigned(bits.substr(0, 8));
var commandID = Bits.bitsToUnsigned(bits.substr(8, 8));

data.longitude = (toLittleEndian(payload.substr(4, 6)) * 215) / 10 * 0.000001;
data.latitude = (toLittleEndian(payload.substr(10, 6)) * 215) / 10 * 0.000001;

var reportType = Math.round(Bits.bitsToUnsigned(bits.substr(64, 8)) / 32);
var gpsFix = Math.round(Bits.bitsToUnsigned(bits.substr(64, 8)) / 32);

if (gpsFix == 0) {
data.gpsFix = “Not fix”;
} else if (gpsFix == 1) {
data.gpsFix = “2D fix”;
} else if (gpsFix == 2) {
data.gpsFix = “3D fix”;
}

if (reportType == 2) {
data.reportType = “Periodic mode report”;
} else if (reportType == 4) {
data.reportType = “Motion mode static report”;
} else if (reportType == 5) {
data.reportType = “Motion mode moving report”;
} else if (reportType == 6) {
data.reportType = “Motion mode static to moving report”;
} else if (reportType == 7) {
data.reportType = “Motion mode moving to static report”;
} else if (reportType == 15) {
data.reportType = “Low battery alarm report”;
}
var batteryPercent = Bits.bitsToUnsigned(bits.substr(72, 8));

emit(‘sample’, { “data”: { “batteryPercent”: batteryPercent }, “topic”: “lifecycle” });
emit(‘sample’, { “data”: data, “topic”: “default” });
}