Mark_VG
(Mark)
September 14, 2023, 3:44pm
1
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:
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.
Any suggestions would be appreciated.
Mark
rlkoshak
(Rich Koshak)
September 14, 2023, 5:18pm
2
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.
Mark_VG
(Mark)
September 14, 2023, 6:12pm
3
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?
It only seems to have inverted the last BIT? The inverted BITs should be 1110 0100 0010 0101
rlkoshak
(Rich Koshak)
September 14, 2023, 6:23pm
4
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 )
Mark_VG
(Mark)
September 15, 2023, 7:15am
6
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:
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?
Wolfgang_S
(Wolfgang_S)
September 15, 2023, 7:42am
7
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
Mark_VG
(Mark)
September 15, 2023, 8:31am
8
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.
Mark_VG
(Mark)
September 15, 2023, 9:20am
10
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