i am converting float data to bytes using python struct library while sending data to TTN.
what decoder function do I need to use to get the data back ?
i am converting float data to bytes using python struct library while sending data to TTN.
what decoder function do I need to use to get the data back ?
Hi, could you possibly elaborate on the question? Tell us which library exactly you are using (i know you say ‘python struct’, but there can be multiple variations…could you give a link to it on github?
The chances are - you will need to write a decoder yourself…
Show me how the data is converted (with an example of input in decimal <-python->output hex)…
Might have luck converting it…
Anyhow, if you are using lib i think you are, and it is converting a float into 2 bytes…try using this (assuming your data is only 2 bytes long):
function Decoder(bytes, port) {
var obj = new Object();
var float=(bytes[0] << 8 | bytes[1])/100;
return obj;
}
This will convert data like 011D to 285, and dividing by 100 will give 2.85…Thats how many manufacturers encode data for battery…
But anyhow, provide some details on encryption…
I am using lopy4 from pycom and below is the code I am using to pack the float values
buffersitemp = struct.pack(“f”,si.temperature())
buffersihum = struct.pack(“f”,si.humidity())
I am sending using
s.send(buffersitemp)
s.send(buffersihum)
for which I get the payload as below in TTN console
5A5A0642
D8202D42
As the value is actually transmitted as a float, you cannot use the above to decode it: the decoder is JavaScript and JavaScript’s bitwise operators work on 32 bits integers, not on floats.
the link you gave worked. but I wanted to understand how this bytes to float works under the hood.
are there any links you can recommend for further reading.
I have temperature, humidity and pressure values coming into TTN (decoded using above code) how can I filter those to be published to separate mqtt topics ?
This is nicely documented: https://www.thethingsnetwork.org/docs/applications/mqtt/api.html#uplink-fields
Thanks for all the help.
I am able to subscribe to the uplink messages but the timestamp I see is for the eu region whereas my gateway is located in asia. How can I make sure I get the correct time ?
I doubt that. I’m quite sure you’ll get a value that ends with “Z”, indicating Zulu-time, a.k.a. UTC. So, any library that can handle ISO 8601 dates should understand that.
two of the convert functions I use in the convert section of the ttn payloads
function Bytes2Float32(bytes) {
var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand === 0) return sign * 0.0 ;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
}
function bytes2short(bytes){
var sign = (bytes[1] & 0x80) ? -1 : 1 ;
var short = (bytes[1] << 8) + bytes[0];
if (sign < 0) {
short = (short & ~(0xffff))
}
short *= sign;
return short;
}
When using TTN’s standard naming convention for the Decoder function, being:
function Decoder(bytes, port) {
...
…then bytes
is an array of numbers, with each number being 0 to 255. So it seems the above needs to be invoked with something like:
// LSB 32 bits float
var float = Bytes2Float32(bytes[3]<<24 | bytes[2]<<16 | bytes[1]<<8 | bytes[0]);
Alternatively, change the function to read:
function Bytes2Float32(bytes) {
// better rename this to a new local variable, e.g., bits:
bytes = bytes[3]<<24 | bytes[2]<<16 | bytes[1]<<8 | bytes[0];
var sign = (bytes & 0x80000000) ? -1 : 1;
....
…and invoke with:
// Take bytes 0 to 4 (not including)
var float = Bytes2Float32(bytes.slice(0, 4));
(When handling a lot of values, use the x+=
addition assignment operator and the x++
postfixed increment operator to keep track of the bytes that have been handled.)
As an aside, bytes2short
can be written as:
// LSB 16 bits signed number.
// Sign-extend to 32 bits to support negative values, by shifting 24 bits
// (too far) to the left, followed by a sign-propagating right shift:
var signedInteger = bytes[1]<<24>>16 | bytes[0];
Both functions are part of the Converter function and called like you described. In the decoder function I take a 4 byte slice of the bytes, and in the Converter I make a 4 byte float out of it.
your version of the bytes2short is a lot short. I wil try that one out.