It seems no leading zeroes are sent. Instead, 7 bytes are sent for two numbers, which is 3.5 bytes per number. That makes life harder than needed (and it might be easier to change the Arduino code instead), but it’s a good example so here goes
0x873fe946b44d1e
is actually 0x0873fe94
and 0x06b44d1e
hexadecimal without the leading zeroes. That is 141819540
and 112479518
decimal, being 41.819540
and 12.479518
for the coordinates.
So, we need bitwise operators to shift the bytes into their right positions, and use bitwise ORs to combine them into two numbers:
byte ----- shifted -----
0 87 8700000
1 3f 3f000
2 e9 e90
3 46 4 6000000
4 b4 b40000
5 4d 4d00
6 1e 1e
-------- -------- OR
0873fe94 06b44d1e
To split 0x46
we can right-shift byte[3] >> 4
to get 0x04
, and do a bitwise AND on byte[3] & 0x0F
to get 0x06
.
Around Rome, the following TTN payload function works:
function Decoder(bytes, port) {
// 7 bytes total, 3.5 bytes per number: 0x873fe9 46 b44d1e is actually
// 0x0873fe94 and 0x06b44d1e, without leading zeroes
var lat = ((bytes[0]<<20 | bytes[1]<<12 | bytes[2]<<4 | bytes[3]>>4)
- 100000000) / 1000000;
var lng = (( (bytes[3]&0x0F)<<24 | bytes[4]<<16 | bytes[5]<<8 | bytes[6])
- 100000000) / 1000000;
return {
location: {
lat: lat,
lng: lng
}
};
}
However, this won’t work for negative values.
The minimum longitude of -180.00
would be sent as -180,000,000 + 100,000,000 = -80,000,000
, being 0xFB3B4C00
in 4 bytes. For that String(lng,HEX)
will also return 4 bytes (instead of 3.5 bytes), simply as it would be a different value without the leading F
.
To support negative values, it might seem you could add/subtract (at least) 180,000,000 instead of 100,000,000 in all formulas, in both the Arduino code and the payload function, to always send positive numbers. But then large positive values would become 4 bytes long, like +360,000,000
is 0x15752A00
. Actually, even with the original code, for +180.00
you would send 280,000,000
, which already needs 4 bytes as 0x10B07600
. Also, .billionths
is probably always positive, even if gps.location.rawLat().deg
is negative…?
In short: it’s a nasty encoding, unsuitable for negative values, and even unusable for large positive values.