Extract GPS data from payload

I'm stuck getting the right data from the payload of a gps tracker.

  • Is the payload (see red arrow) a Hex string? How can I get GPS data from it?
  • Why do I see the battery value (99% charged) but no Latitude Longitude etc?

This is the payload format info of the tracker

Any help is appreciated

Hi @maru

With the link you posted, what event are we actually looking at?
I can't identify it in the provided list of possible types

if you can show us the exact layout description on the website of the payload, we can hopefully decipher it - but currently, it doesn't look like a single event

You might also look at node-red-contrib-buffer-parser (node) - Node-RED

Hi @marcus-j-davies,
Thank you for reading.

This GPS is connected to The Things Network where I use a payload formatter.
Bellow is a part of that formatter(it exceeds the number of characters that can be used in this forum, therefore not posted in its entirety)

            measurementArray = [
                {measurementId: '3940', type: 'Work Mode', measurementValue: workMode},
                {measurementId: '3942', type: 'Heartbeat Interval', measurementValue: heartbeatInterval},
                {measurementId: '3943', type: 'Periodic Interval', measurementValue: periodicInterval},
                {measurementId: '3944', type: 'Event Interval', measurementValue: eventInterval},
                {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(16, 18))},
                {measurementId: '3900', type: 'Uplink Interval', measurementValue: interval}
            ]
            break;
        case '05':
            measurementArray = [
                {measurementId: '3000', type: 'Battery', measurementValue: getBattery(dataValue.substring(0, 2))},
                {measurementId: '3940', type: 'Work Mode', measurementValue: getWorkingMode(dataValue.substring(2, 4))},
                {measurementId: '3965', type: 'Positioning Strategy', measurementValue: getPositioningStrategy(dataValue.substring(4, 6))},
                {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(6, 8))}
            ]
            break
        case '06':
            collectTime = getUTCTimestamp(dataValue.substring(8, 16))
            measurementArray = [
                {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
                {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
                {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
                {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
                {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
                {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}

So I think the keyi part for me is measurementId '41971 and '4198'

               {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
                {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},

Is this useful?

Mmm when I try to decode it - I end up at the Atlantic?
can you pass the whole data buffer that you get?

If you search for packet type 0x11 (the first byte in the payload you show as an example) - in that document you shared - you can see that it is a Positioning Status and Sensor Packet-0x11
ID 0x11 is used to upload the positioning status, sensor data and battery.
So there is no GPS info in that packet... you need to share one of the types that does contain location info - packet type 0x06 or 0x09 I think - which then corresponds to the later code snippet you show (case 06) .

(Finally the packet you show starts 1101 so type 0x11 - second byte 01 means The GNSS scan timed out and failed to obtain the location. - so you may not see any packets of type 0x06 until you get a valid location detected. (ie 0x1100... ))

1 Like

I’m glad there is people like you around @dceejay.
I’m just happy I wasn’t going mad.

Thanks you for this explanation, it's getting clearer to me now.
I already suspected that there was no GPS data in the data obtained.
Perhaps the tracker can't see a satellite because it's in the house?
I'll take it outside and try to get more data.

@ dceejay and @ marcus-j-davies thank you both for your input!

I think I got it:

According to this payload format info:

Byte:
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
09 00 00 00 00 67 88 ca 37 00 54 00 5c 03 10 b8 84 61

Byte 1 		0x09 GNSS Location Only Packet
Byte 2~4		0x000000 event status: : no event
Byte 5		0X00 motion segmentnumber: ) no motion 
Byte 6~9	0X6788ca37 = 1737017911 (DEC) seconds??  
Byte 10~13	0X0054005c = 5505116 Longitude 
Byte 14~17	0X0310b884 = 51427460 Latitude
Byte 18		0X61 = 97 (DEC)  Battery level 97%

Next step is try to plot this on Worldmap

you can parse this into friendly data using buffer parser:

demo flow

[{"id":"7a69fe6e9bc79cc2","type":"inject","z":"dc4d66c20e03fcbd","name":"09000000006788ca370054005c0310b88461","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"09000000006788ca370054005c0310b88461","payloadType":"str","x":590,"y":100,"wires":[["7d28dc01345eeda2"]]},{"id":"7d28dc01345eeda2","type":"buffer-parser","z":"dc4d66c20e03fcbd","name":"","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint8","name":"FrameId","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"bool","name":"EventStatus=>start","offset":1,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"bool","name":"EventStatus=>end","offset":1,"length":1,"offsetbit":1,"scale":"1","mask":""},{"type":"bool","name":"EventStatus=>motionless","offset":1,"length":1,"offsetbit":2,"scale":"1","mask":""},{"type":"uint8","name":"MotionSegmentNumber","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint32be","name":"UTCTime","offset":5,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint32be","name":"Longitude","offset":9,"length":1,"offsetbit":0,"scale":"/ 1000000","mask":""},{"type":"uint32be","name":"Latitude","offset":13,"length":1,"offsetbit":0,"scale":"/ 1000000","mask":""},{"type":"uint8","name":"BatteryLevel","offset":17,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":510,"y":160,"wires":[["76ec65852effe6dd"]]},{"id":"76ec65852effe6dd","type":"debug","z":"dc4d66c20e03fcbd","name":"debug 20","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":160,"wires":[]}]

Just move Latitude to lat and Longitude to lon, and add a name property and should just appear

It's trial and error but below I post my flow and node screenshots


I used a Change node and moved Longitude to lon and another node for Latiude to lat


also added a Change node for the name.


The Worldmap node


...and this is the output

I use Ctrl-Shft-m to switch to the Worldmap but I don't see a point/marker.
What am I doing wrong?

If you look at the examples on the information page for web-workmap you will see the properties need to be in the same payload.
node-red-contrib-web-worldmap (node) - Node-RED

The minimum msg.payload must contain name, lat and lon properties, for example

    msg.payload = { "name":"Jason", "lat":51.05, "lon":-1.35 }

In the flow you posted, the properties are in separte payloads - so you need to combine them.

Tha's it! :grinning:

This is a working flow, with a combined Cnage node for lon and lat


with a combined Change node for lon and lat

Thank you all for reading and advice :+1:

1 Like