OH4 JS Transformation to convert raw modus to HEX

Hi All

I have data coming from a modBUS device which I need to convert from two’s complement to HEX for the value to be meaningful.

The raw value is -7130 which when the two complement is reversed (Invert Bits and add 1) should result in a HEX vale of E426.

Using a calculator I get the expected result:

image

However using the following script:

(function(data) {
  console.info('******************Entered map transformation with "' + data + '"!');
  var returnValue;
    returnValue = (Math.abs(data));
  console.info('******************Absolute Value "' + returnValue + '"!');
    returnValue = ~(Math.abs(data));
  console.info('******************Not (~) Value "' + returnValue + '"!');
    returnValue = (~(Math.abs(data)) + 1);
  console.info('******************Not (~) Value plus 1 "' + returnValue + '"!');  
    returnValue = (~(Math.abs(data)) + 1).toString(16);
  console.info('******************Hex Result of Not (~) Value plus 1 "' + returnValue + '"!');  
  return returnValue
})(input)

I end up with:

17:33:26.963 [INFO ] [org.openhab.automation.script        ] - ******************Entered map transformation with "-7130"!
17:33:26.963 [INFO ] [org.openhab.automation.script        ] - ******************Absolute Value "7130"!
17:33:26.963 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value "-7131"!
17:33:26.964 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value plus 1 "-7130"!
17:33:26.964 [INFO ] [org.openhab.automation.script        ] - ******************Hex Result of Not (~) Value plus 1 "-1bda"!

The Hex result seems to be the HEX of 7130 and not the required -7130, so I am sure I have got something basic wrong again.

image

Any suggestions would be appreciated.
Mark

I hate mucking around with bitwise operations. It’s particularly annoying in JavaScript.

First of all, I’m surprised the Math.abs(data) works without error. input and therefore data is always going to be a String. I’m not sure if that could be causing problems here or not. What happens if you parseInt(data) first?

Secondly, use .toString(2) on your intermediate steps. Maybe seeing the actual bits will reveal something.

Thanks Rich

This suggestion was really helpful…

(function(data) {
  console.info('******************Entered map transformation with "' + data + '"!');
    returnValue = (parseInt(data)).toString(2);
  console.info('******************ParseInt "' + returnValue + '"!');  
    returnValue = (Math.abs(parseInt(data))).toString(2);
  console.info('******************Absolute Value "' + returnValue + '"!');
    returnValue = (~(Math.abs(parseInt(data)))).toString(2);
  console.info('******************Not (~) Value "' + returnValue + '"!');
    returnValue = (~(Math.abs(parseInt(data))) + 1).toString(2);
  console.info('******************Not (~) Value plus 1 "' + returnValue + '"!');  
    returnValue = (~(Math.abs(parseInt(data))) + 1).toString(16);
  console.info('******************Hex Result of Not (~) Value plus 1 "' + returnValue + '"!');  
  return returnValue
})(input)

Produces:

20:03:54.809 [INFO ] [org.openhab.automation.script        ] - ******************Entered map transformation with "-7130"!
20:03:54.810 [INFO ] [org.openhab.automation.script        ] - ******************ParseInt "-1101111011010"!
20:03:54.810 [INFO ] [org.openhab.automation.script        ] - ******************Absolute Value "1101111011010"!
20:03:54.811 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value "-1101111011011"!
20:03:54.811 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value plus 1 "-1101111011010"!
20:03:54.811 [INFO ] [org.openhab.automation.script        ] - ******************Hex Result of Not (~) Value plus 1 "-1bda"!

So it looks like the NOT ~ is not doing what I expected?

From what I have researched it should do a bitwise NOT to invert all the bits?

image

It only seems to have inverted the last BIT? The inverted BITs should be 1110 0100 0010 0101

I’m out of ideas here. I’ve never done bitwise stuff in JS. Based on the usual JS sources it does say it’s supposed to apply the operator to each bit.

Note the sign: ~ 1101111011010 = 1…10010000100101 = - 1101111011011 (Two's complement - Wikipedia)

Thanks for that.
I had noticed the sign change (which is expected I gather for NOT (~).

The issue seems to be that not each bit is being flipped:

So -1101111011010 becomes 1101111011001 and not the expected 0010000100101 (Only last two bits are flipped)?

I also see if I use a calculator and do ```0-(1BDA) I get the required result of E426:

image

However in the script returnValue = (0-(~(parseInt(data)) + 1)).toString(16); doe snot echo that at all.

My latest code version is:

(function(data) {
  console.info('******************Entered map transformation with "' + data + '"!');
  
    returnValue = (parseInt(data)).toString(2);
  console.info('******************ParseInt "' + returnValue + '"!');   
  
    returnValue = (~(parseInt(data))).toString(2);
  console.info('******************Not (~) Value "' + returnValue + '"!');
  
    returnValue = (~(parseInt(data)) + 1).toString(2);
  console.info('******************Not (~) Value plus 1 "' + returnValue + '"!');  
  
    returnValue = (0-(~(parseInt(data)) + 1)).toString(16);
  console.info('******************Zero -  Not (~) Value plus 1 "' + returnValue + '"!');  
  
    returnValue = (~(parseInt(data)) + 1).toString(16);
  console.info('******************Hex Result of Not (~) Value plus 1 "' + returnValue + '"!');    
  
  return returnValue
})(input)

which produces:

09:13:31.575 [INFO ] [org.openhab.automation.script        ] - ******************Entered map transformation with "-7130"!
09:13:31.576 [INFO ] [org.openhab.automation.script        ] - ******************ParseInt "-1101111011010"!
09:13:31.576 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value "1101111011001"!
09:13:31.576 [INFO ] [org.openhab.automation.script        ] - ******************Not (~) Value plus 1 "1101111011010"!
09:13:31.577 [INFO ] [org.openhab.automation.script        ] - ******************Zero -  Not (~) Value plus 1 "-1bda"!
09:13:31.577 [INFO ] [org.openhab.automation.script        ] - ******************Hex Result of Not (~) Value plus 1 "1bda"!

Wondering is the issue could be using 16bit signed vs 32 bit signed? Have read some article which imply 32bit is assumed?

Maybe only solution is to try manually flip the bits or to find a way to get the negative value as per calculator result?

I know it’s less fun but have you searched for existing code that can be resused like e.g.
https://gist.github.com/bsara/519df5f91833d01c20ec

1 Like

Thank you. I have been searching and have tried a good few options. My lastest is as follows:

    var b = (((parseInt(data))).toString(2)).split('')
    returnValueTest = (((parseInt(data))).toString(2)).split('').map(c => 1 - c).join('');
  console.info('******************SPLIT and JOIN Value "' + returnValueTest + '"!');  

However that produces:

10:25:06.044 [INFO ] [org.openhab.automation.script        ] - ******************SPLIT and JOIN Value "NaN0010000100101"!

Which is correct except for the leading NaN.

Will take a look at yoru suggested code and give it a try too.

Your ‘issue’ is caused by using a signed variable instead of using an unsigned one. AFAIK, Javascript doesn’t support unsigned integer types - see JavaScript C Style Type Cast From Signed To Unsigned - Stack Overflow for some workarounds.

Thank you so much. That was it exactly. Changed to unsigned and now I get the expected result -e426 which I can now work on to convert to E.4.2.6

Really appreciate the insight and help

1 Like