Node-red convert from hexa to decimal

I have a raspberry pi and KNX sensors. I am using Node-RED and I wish to extract measurement (For example: Temperature). But I don’t know how to convert from hexa (Data Type “2-Octet Float Value”10) to decimal (Format: 2 octet (MEEEMMM MMMMMMMM – Encoding:(0.01*M) *2(E)).Thanks for help

Looks like you missed an "E" in your conversion string... from the docs, the encoding should be:
SEEEEMMM MMMMMMMM (I think)

If so, here is one way you can extract the bits you need from the payload and do the math:

var buf = Buffer.from(msg.payload);
var s = buf.readUInt8() >> 7;
var m = buf.readUInt16BE() & 0b0000011111111111;
var e = (buf.readUInt8() & 0b01111000) >> 3;
msg.payload = (0.01*m) * (2**e);
return msg;

Do you have any idea what your input buffer [46, 23] should be when converted to a float? Using this method, I get 498.88 but I have no idea whether that is correct.

I also saw some docs that mentioned the first Mantissa bit was a "sign" bit, and would determine whether the value was positive or negative (maybe due to 2's complement logic?). Obviously I did not code for that possibility, but in your sample data that value is 0, so it should not affect the answer...

1 Like

Yes i missed an "E", sorry.
498,88 is the right vlaue. I insert the image of encoding document.
For the sign I Think when it's 1 is negatif and when it is 0 is positif.
Thank you for your help

Can you please explain to me :

  1. Why you have created (var s) and you didn’t use it.
  2. What the meaning of “& 0b00...”

And i don’t know how can I inject function for deteminate the sign. Can you help me please

Thank you

I mentioned that I extracted the sign bit from the first byte, but was not sure what to do with it. With your sample data, that bit is 0 -- and if you never expect negative numbers, I guess you could safely ignore it. What do you think should be done with that bit? If it just switches the sign of the result, then you could add this to the equation for setting the payload value:

var s = (buf.readUInt8() >> 7) == 0 ? 1 : -1;
...
msg.payload = s * (0.01*m) * (2**e);

But if it's actually part of the Mantissa, it would need to be combined with the m variable somehow -- I'm just not that well versed in 2's-complement number conversion to javascript numbers.

In Javascript, a single ampersand & is the "logical AND" function. The Javascript number 120 can be also be represented as hexadecimal (0x78), octal (0o170), or binary (0b01111000). I just like to use the binary format because it gives me a visual "bitmask" showing which bits are "on" and which are "off", so I know which will be ignored when combined using the logcal "AND" operator. And the >> operator is used to bit-shift a number to the right, while << shifts left.

All of these things and much more are well documented on the W3Schools sites -- I reference them probably every day...

1 Like

Thank you...

I launched the code but I got an error messagelike in the picture. Can you help me please!
sdf

add a debug node before your function so you can see the message that is causing that error

1 Like

According to the description box earlier mantissa is 12 bits, including the bit on the front, making a 12 bit twos complement number, so 0111 1111 1111 is 2047, 0000 0000 0000 is zero, 1111 1111 1111 is -1 and 1000 0000 0000 is -2048.
If you want to allow for -ve numbers then the easiest way may be to get the 11 bits as you have already, then if the sign bit is set then subtract 2048. Then apply the exponent.

1 Like

I got the same message. Befor function I have a change function ( change msg.payload to msg.payload.value)

I looked at the encoding example, -2048=<M=<2047 two's complement notation. This mean with this function I not allow to get the right negatif values? @shrickus @Colin
var buf = Buffer.from(msg.payload);
var s = buf.readUInt8() >> 7 === 0 ? 1 : -1;
var m = buf.readUInt16BE() & 0b0000011111111111;
var e = (buf.readUInt8() & 0b01111000) >> 3;
msg.payload = s*(0.01*m) * Math.pow(2, e);

return msg

This might do it (untested). If the sign bit is set it subtracts 2048 from the mantissa

var buf = Buffer.from(msg.payload);
var s = buf.readUInt8() >> 7 === 0 ? 0 : 2048;
var m = (buf.readUInt16BE() & 0b0000011111111111) - s;
var e = (buf.readUInt8() & 0b01111000) >> 3;
msg.payload = 0.01 * m * Math.pow(2, e);
return msg