Decode float sent by Lopy as Node

Unfortunately Otto, the JavaScript ES5 parser that TTN uses, does not support Typed Arrays, which would have made life easy.

Two options:

  • Don’t send a float, but multiply by, say, 100 and send an integer. Then after decoding, divide by 100 to get the original value. You’ll find many examples here on the forum.

  • Use the following, based on a Stack Overflow post by Ilya Bursov, but for this example with the byte order reversed:

function Decoder(bytes, port) {

  // Based on https://stackoverflow.com/a/37471538 by Ilya Bursov
  function bytesToFloat(bytes) {
    // JavaScript bitwise operators yield a 32 bits integer, not a float.
    // Assume LSB (least significant byte first).
    var bits = bytes[3]<<24 | bytes[2]<<16 | bytes[1]<<8 | bytes[0];
    var sign = (bits>>>31 === 0) ? 1.0 : -1.0;
    var e = bits>>>23 & 0xff;
    var m = (e === 0) ? (bits & 0x7fffff)<<1 : (bits & 0x7fffff) | 0x800000;
    var f = sign * m * Math.pow(2, e - 150);
    return f;
  }  

  // Test with 0082d241 for 26.3134765625
  return {
    // Take bytes 0 to 4 (not including), and convert to float:
    temp: bytesToFloat(bytes.slice(0, 4))
  };
}

The above function will get you 26.3134765625. To limit the number of decimals, use, e.g.:

// Unary plus-operator to cast string result of toFixed to a number:
temp: +bytesToFloat(bytes.slice(0, 4)).toFixed(3)

Of course, the toFixed could also be added to bytesToFloat instead:

// Convert to a string with 3 decimals, and then apply the unary plus-operator
// to cast the string result of toFixed to a proper number:
return +f.toFixed(3);

When handling multiple values, one can use the x+= addition assignment operator and the x++ postfixed increment operator to keep track of the bytes that have been handled:

var b = 0;
var float1 = bytesToFloat(bytes.slice(b, b+=4));
var float2 = bytesToFloat(bytes.slice(b, b+=4));
var byte1 = bytes[b++];
// Assume LSB (MSB seems more common?)
var unsigned16bits = bytes[b++] | bytes[b++]<<8;
// 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 signed16bits = bytes[b++] | bytes[b++]<<24>>16;
var signed32bits = bytes[b++] | bytes[b++]<<8 | bytes[b++]<<16 | bytes[b++]<<24;
var float3 = bytesToFloat(bytes.slice(b, b+=4));

Finally, beware:

6 Likes