Bytearray() and structures for floating point values
-
I am getting to grips with my FiPy and PySense. Just started sending LoRa packages and used the following code to send the battery voltage.
vt = py.read_battery_voltage() print("Battery voltage: " + str(py.read_battery_voltage())) data = bytearray(2) data = bytearray(struct.pack("f", vt)) s.send(data) # send buffer to TTN
The voltage was 4.420753 and the byte array I received was 61 d2 8c 40
I used javascript to decode this at the other end using a standard library function but it says the value is 8.1085 e -315If I use https://gregstoll.dyndns.org/~gregstoll/floattohex/ as a resource to convert from float to hex is comes out as 40 8d 76 cf so the reverse of my number. If i swap endianness it converts 40 8d 76 cf as 4.42075 so that seems to be the problem.
What is the JavaScript I should use to unpack my payload to read the correct value?
thanks
-
I found an answer. The function in Python by default packs the four bytes in little endian format. JavaScript expects big endian. By merely changing
data = bytearray(struct.pack("f", vt))
to
data = bytearray(struct.pack(">f", vt))
the unpack at the other end was simple.
Java Script
function decodeFloat(data1) { var binary = parseInt(data1, 16).toString(2); if (binary.length < 32) binary = ('00000000000000000000000000000000'+binary).substr(binary.length); var sign = (binary.charAt(0) == '1')?-1:1; var exponent = parseInt(binary.substr(1, 8), 2) - 127; var significandBase = binary.substr(9); var significandBin = '1'+significandBase; var i = 0; var val = 1; var significand = 0; if (exponent == -127) { if (significandBase.indexOf('1') == -1) return 0; else { exponent = -126; significandBin = '0'+significandBase; } } while (i < significandBin.length) { significand += val * parseInt(significandBin.charAt(i)); val = val / 2; i++; } return sign * significand * Math.pow(2, exponent); } // example use data = '408df220' // is floating point value 4.43580627441406255 value = decodeFloat(data); log.console('Value=', value);
The code above is from https://stackoverflow.com/questions/4414077/read-write-bytes-of-float-in-js
From a great website application at https://gregstoll.dyndns.org/~gregstoll/floattohex/ I produced the image below
-
@smbunn
look then maybe here
https://github.com/ronniebasak/JStruct
possibly here if above not work
http://www.jython.org/javadoc/org/python/modules/struct.html
-
False path. The hyperlinked example is in Java. Almost none of the structures used exist in JavaScript which does not support ByteBuffer as a type. So after an hour I have realized I am wasting my time trying to patch something together.
Anyone else got any ideas? It seems like it should be easy :-)
-
@robert-hh
True but this is a general question and some of my values will be over vastly different ranges. So it is really a question on float to 4 byte array back to float. I am working on the unpacking now guided by https://stackoverflow.com/questions/29879009/how-to-convert-python-struct-unpack-to-java and will let everyone know how I get on.
From my limited understanding it seems that Python has a great pack and unpack function but JavaScript doesn't so you have to write your own.
-
@smbunn given that you transmitted 4 bytes, you could as well send a 4 byte ascii string, tellung the value in millivolt and still being precise enough for the purpose.
-
@smbunn
maybe this one
https://stackoverflow.com/questions/29879009/how-to-convert-python-struct-unpack-to-java