Dragino LGT92 in v3 how to start?

Hi everybody,

I’m new to TTN and got stuck. I started this new topic, because I could get any further with the old post, they are about v2 TTN and in v3 TTN everyhing seems to be different.

I have added an application, and then added the Dragino LGT92. The systems seem to talk to each other, but i don’t recieve the battery, postition etc. I always see in the examples. Also it says: " Last seen info unavailable", while there just been activity in the messages.

For example if I look in the messages I see this:
Successfully processed join-request

Raw payload

I think this payload needs to be decoded and then I can see the values maybe???

So I tried this v2 script in the Payload Formatters > Downlink. There the config says “This option will affect both uplink and downlink formatter” and the example shows an encoder an decoder. But I don’t have that encoder script, only this decoder script. Is this oke to put in? I tried and no effect. And is this script Java? Do I need to use the “Java Script playload decoder? or is this another kind of script?” Sorry i’m really new to this. The script I found in the forums is this:

function Decoder(bytes, port) {
    // Decode an uplink message from a buffer
    // (array) of bytes to an object of fields.
    var alarm = bytes[6] & 0x40 ? true : false; //Alarm status
    value = ((bytes[6] & 0x3f) << 8) | bytes[7];
    var batV = value / 1000; //Battery,units:Volts
    value = (bytes[8] << 8) | bytes[9];
    if (bytes[8] & 0x80) {
        value |= 0xffff0000;
    var roll = value / 100; //roll,units: °
    value = (bytes[10] << 8) | bytes[11];
    if (bytes[10] & 0x80) {
        value |= 0xffff0000;
    var pitch = value / 100; //pitch,units: °
    var json = {
        roll: roll,
        pitch: pitch,
        batV: batV,
        alarm: alarm,
    var value = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2];
    if (bytes[0] & 0x80) {
    value |= 0xffffff000000;
    var value2 = (bytes[3] << 16) | (bytes[4] << 8) | bytes[5];
    if (bytes[3] & 0x80) {
    value2 |= 0xffffff000000;

    if (value == 0x0fffff && value2 == 0x0fffff) {
        //gps disabled (low battery)
    } else if (value === 0 && value2 === 0) {
        //gps no position yet
    } else {
    json.latitude = value / 10000; //gps latitude,units: °
    json.longitude = value2 / 10000; //gps longitude,units: °
    return json;

Last but not least when I added the Dragino LGT92 with this pre-filled-in config of the V3…it asked which “Hardware version” and " Firmware version" I have, so I have selected “unknown_hw_version” and “1.6.4” Firmware…hoping I have the last version because I bought it last week… does this really, matter? Should I delete everyhing, start over and try and older firmware version? Or can you add device multiple times to TTN an try which one works??
Anyone has a clue how I can know for shure which firmware I have? It’s not on the box. Also emailed this question to Dragino…I hope they know what firmware version they shipped.

If I get this working. My goal is to transfer the tracking data to Home Assistant.The Things Network - Home Assistant
But first I have to get these basic things right in TTN.

This packet is the join request. That is where the node connects to TTN, there is no application data in that packet. The next uplink should have data if the node receives and processes the reply correctly.
What is the next packet?

Thanks for your reply. It seems like it’s repeating the same message. I made a screendump:


My networklayer settings.


Repeated join requests means the node is not receiving the replies. Until the node successfully receives and processes the reply you will not see real data.
Can you connect to node to your computer as described in the manual to check the messages and firmware version?

I’m still digging that manual now…Seems that I need to order a “USB toTTL adapter to connect to LGT-92for using AT command” first before I can answer your question.

I saw in the corner of my eye the messages are changing:

16:06:34 Link ADR request enqueued
16:06:34 Link ADR request enqueued
16:06:34 Device status request enqueued
16:06:34 Successfully scheduled data downlink for transmission on Gateway Server
16:06:34 Schedule data downlink for transmission on Gateway Server Rx1 Delay 5 * info
16:06:34 Store upstream data message
16:06:34 Forward data message to Application Server MAC payload AF9B67016AB6621EB8CFB8
FPort 2 SNR -12.8 RSSI -119 Bandwidth 125000

That means the node has successfully joined and you should see received data in the application.

Turns out you really need to also buy the USB-to TTL converter, and Firmware Flashprogrammer for this device. In meanwhile I found out i have v1.6.0 firmware and then this should be the code, and should be uploaded under the “Upload” section of the Payload formatters:

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

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

    var longitude = 0;
    if (bytes[4] !== 0) {
        longitude = (bytes[4] << 24 | bytes[5] << 16 | bytes[6] << 8 | bytes[7]) / 1000000; //gps longitude,units: °
    } else {
        longitude = 0; //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,

These examples I found here: Dragino Download Server ./downloads/LGT_92/
The example code on their support site seems to be somewhat screwed up. I needed to “fix” it.

A bit off topic. I received my lgt92 this week. It already had the latest firmware 1.6.5. I was able to join it to V3 without any problem.

But the GPS is terrible. My unit is a LGT92-LI-EU868, firmware v1.6.5 EU868, hardware v1.6.5, GPS ublox-MAX7. I have to set FTIME to 5 minutes to get location fixes when I have it in my car or around my neck outdoors. Indoors I never get a location fix. How is your GPS working, and what hardware version do you have?

I really just got it working v.1.6.4, don’t know hw version. But it seems to take a long time to get a location fix indeed, maybe that’s why the thing was so cheap :wink: I’m waiting for my TTL > USB so I can program the thing to transmit more the 1 times an hour and also enable or disable other sattelite services beside GPS :wink: then I know for shure.
Then my next challenge is to get the GPS values to Home Assistant, which does not work yet. If everything works, i’ll take a look for a unit with faster-GPS. The Things Network - Home Assistant

This only works with a certain hw version. The version I have with the ublox max7 does not support this. I was advised by dragino to set the pdop to 7, meaning it will fix faster but with a very large inaccuracy. I will try this later today.

By the way: some settings can be done using lorawan downlink, so you could alraedy try some of the settings without the need for the serial adapter.

Do you have an example script for changing a value via TTN downlink? Where to input it? If i’d know how to start I’d maybe can figure it out myself how do the rest with the manual.

GPS are like your lover, you can’t just turn them on & off on demand.

It takes 12.5 minutes minimum to download the almanac which is valid for a number of months - this gives rough positions of the entire satellite constellation and enables a warm fix which is typically 20 seconds.

So the almanac allows the GPS to have a good idea of what to ‘look’ for. Once it has a connection to a satellite, it can then start picking up the ephemeris for that satellite which holds data for the coming 30 minutes. This takes 30 seconds for each satellite once the GPS is receiving the satellite’s signal.

So the ephemeris allows the GPS to know precisely what to expect if it’s powered down and then re-queried in the next 29 minutes, giving a hot fix which could be a second but at worst could be 20s. Turn on 31 minutes later, it reverts back the almanac.

If the time between GPS queries is longer than 30 minutes, it will need a warm fix (20 seconds) and then 30s to download the ephemeris if you want that to hand (which you don’t if you are not going to ask for a fix again in the next 30 minutes).

GPS queries more frequently than 30 minutes will need to be on for 30+ seconds towards the end of your 30 minute sliding window so it can pick up the ephemeris. You can do what you like in the first 29 minutes, but if you want to be sure of a hot fix on minute 31, it will need time to download. Obviously this data is coming down all the time so it may have accumulated enough, but it’s very hard to tell without all sorts of arcane AT commands. Or just testing, try running the GPS for five seconds after you’ve got your hot fix and see how that fairs. The different chipsets as well as the antenna’s will all have different levels of success.

TL;DR: You can’t just turn on a GPS and get a good fix without letting it collect the data it needs.


In the user manual you can find the supported downlink commands. You need to convert it to Bas64 (online tool: Hex to Base64: Encode and decode bytes online — Cryptii).

E.g.: the command to disable motion mode (so always do GPS fix at every interval) is A5 00. Converted to base64 this is pQA=. You can enter it through the Things webinterface:


This will be downloaded to the unit on the next time it reports itself to the network. I have found that you can only send one command at a time. (hence the replace downlink queue). Use Fport 2 and enable the confirmed downlink

Some other commands:
set 60s interval AQAAPA==
set 5 min interval (=default): AQABLA==

set motion mode off: pQA=
set motion mode 1 on (default): pQE=


And to make things easier for me I used Node-red and the MQTT interface to do all this in a more user friendly way. Also I use Node red to give me some nice graphs and tracking map.

2021-07-08 (1)

2021-07-08 (2)

1 Like

Where is this downloaded from? Is it coming with the GPS signal? Because I am very sure it is not downloaded over LoRaWAN.

In my tests I am doing a fix every 5 minutes. So this should result in a hot fix after the first time. But it doesn’t. It takes 3 to 5 minutes every time…

Yes - it would only come over LoRaWAN if you’d programmed the downlinks for that …

As it happens, most smartphones use A-GPS, A for Assisted, where they download the almanac & ephemeris data over the internet.

Have you previously left the device on for about 20 minutes with clear view of the sky. It’s not how often you fix or ask for a position, it’s how much the unit has time to do it’s job before it’s shut down.

The acid test for any GPS unit is outside where you can put your arm up at 55° and not point at anything substantial in the sky and leave it alone for about 30 minutes. That should get you 5 or 6 satellites minimum with about ±5m accuracy.

I have left it alone hanging outdoors for hours…

I now start to suspect it never fully downloads the almanac. To preserve power it goes into sleep mode right after it gets a fix and reports that over the LoRaWAN.

Yup, that’s what people do, seems very reasonable thing to do, but ends up with just fragments. The almanac is good for 180 days, so at least once every couple of months the GPS needs to run for 20 minutes with good view of the sky - so once you get a good fix, leave it be for 15 minutes.

Sometimes it’s worth powering up the GPS for 30 seconds every 25 minutes to get the ephemeris data so you always get a hot fix - although that needs refining if a satellite you have ephemeris data is out of view, which means the almanac is used to find the missing satellite - you need 4 for a goodish fix.

This may be a better power strategy than turning on less frequently but then needing more time to get the fix in the first place. Hmmm, something to try that I hadn’t thought of (mostly as I now have decent set of power monitors) to see if this is the case.


First run for at least 15 minutes with good view of sky - this can be done pre-deployment on desktop power as long as the deployment zone is within 100km or so

Subsequent runs, hot fix as required but at least once every 25 minutes wait for a minimum of 4 satellites and let it run for 30 seconds from when you’ve got the 4th satellite.

If occasional fix requirements, ensure the GPS is on for 15 minutes once every couple of months to ensure it has a good clean copy of the almanac.

If the GPS has been dormant for a while (you will know this either via RTC or the reported time from the first satellite), then run it for 15 minutes so it has a good clean copy of the almanac.

Bear in mind that the ephemeris and almanac are moving data, so it can’t piece together yesterday pieces with todays.

That is something you can change to the GPS being on all the time IIRC. That will of course drain the battery fast(er).