Working with state changes

#1

Hey there I have MODBUS Input module


which is working in modbus.
for some reason it is not working according to data sheet and instead of having one register per Input i get a decimal number two's complimentary i would like to do automation to detect the input status.

number is 16 bits
i found something which should do the work
node-red-contrib-binary
not sure if it will support the signed number however ,
is there any solution to manipulate the msg value ( i currently don't know how to get it in function node).

0 Likes

#2

Feed the message into a debug node and copy/paste here what you see, then explain again what you want to convert it to.

0 Likes

#3

10/20/2018, 4:19:09 PMnode: 513283da.a8848csensor.dio : msg.payload : string[1]

"9"

this is an example the number 9 indicate for two active inputs

the LSB and bit number 3
so 2^0+2^3= 9...

for the automation i would like to get state for each input.
basically i also could not find the reason why i cannot read the register directly and i only get one cumulative results.

0 Likes

#4

What node type is that string coming from?

0 Likes

#5

Event status

0 Likes

#6

I don't understand. I assumed it was coming from a comms node of some sort. How can a Status node read modbus? If that is what you meant by Event status.

0 Likes

#7

Hey it is very simple ..
i get a string which is represent by decimal number which if i convert it into 16 bit array
each bit will indicate for the input status..

i would like to do an automation which will read each bit separately.... and will send MQTT message...

  1. how can i convert the payload into number ?
  2. how to put the bits data into an array? 16 bits...
0 Likes

#8

OK, if you don't want to tell us which node you are using in the hope we might make your life easier then that is up to you.

To convert a string to a number you can do, in a function node

var number = Number(msg.payload);

Then to access, for example, bit 2 (0 being the least significant bit) you can use

var bit2 = (number >> 2)&1;

so you could load up an array using something like that in a loop.

0 Likes

#9

When I want to get an array of bits from a number, I build a string of 16 1's and 0's, split it into single characters, map those to numbers, and reverse the array, like so:

var bits = ('0000000000000000' + Number("9").toString(2)).slice(-16).split('').map(d => +d).reverse()

which returns this array:
[ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]

Now you have a 16 element array, with the index # equal to each bit's position -- so to check bit 2, you would use the JS syntax bits[2]. There is probably a cleaner way than fiddling with all the 0 padding and slicing, but filling buffer arrays is not as intuitive for me...

0 Likes

#10

Hey Thanks!

I am using function node

var bit2 = (number >> 2)&1; means rotate right ? 2 times and does And operand with 1?


second option
var bits = ('0000000000000000' + Number("9").toString(2)).slice(-16).split('').map(d => +d).reverse()

means add array of 16 bits of zero ,

what does slice -16 will do ? i assume map and reverse will convert the array to be in the right direction ?

0 Likes

#11

I am using simple flow..
dio is the sensor ,
i could not see any output to this....
this is the new function i have created..
var number = Number(msg.payload);
var bit2 = (number >> 2)&1;
msg=bit2;
return msg;

when i tired to change return variable to number
return number;

i get the following:
Function tried to send a message of type number
on debug window

0 Likes

#12

Which means your Function node is returning a number, not a message object.

Change your function to do:

msg.payload = bit2;
0 Likes

#13

Thanks so can you elaborate the command
var bit2 = (number >> 2)&1;

does it means rotate right ? 2 bits?

0 Likes

#14

No, shift right not rotate right.
The w3schools site is excellent for information on javascript (and lots of other stuff too). The operators can be seen at
https://www.w3schools.com/jsref/jsref_operators.asp

0 Likes

#15

The slice(-n) function returns the last n characters of a string -- and Array.reverse(), well it reverses an array ;*)

BUT, I have since found a more "natural" way to create an array of bit flags from any numeric value (either of datatype integer or string):

// create an empty array (of `N` bit flags)
var bits = new Array(16).fill(0);
// "AND" each element and "shift" to get its bit value
msg.payload =  bits.map((d,i) => (msg.payload & 2**i) >> i);
// return the original msg with the new payload array
return msg;
0 Likes