Check if at least two out of five booleans are true

Good morning just a quick question. How would I go about the following?
Check if at least two out of five booleans are true. I am sure there must be a node for this.

thanx

I guess a lot depends on how the states arrive: in one message or as 5 separate messages.

Could you elaborate on that part and what the messages (if multiple) are.

Thanks for your reply. I have a number of seperate outputs, if two of the payloads is true, the result must be true, otherwise false.

relay_2 : msg : Object
object
topic: "relay_2"
payload: false
bool: false

The first thing you will need to do is to combine all the payloads into one message. See this article in the cookbook for an example of how to join messages into one object.

Ok, thats not a problem, but then?

@Colin,

This is the result. So what I want now is to check that we have 2 X true and then the result should be true?

11-8-2021 09:15:36node: 82b10c89.3acdfrelay_4 : msg : Object
object
topic: "relay_4"
payload: array[4]
0: false
1: false
2: true
3: true
bool: true
_msgid: "ee1e011e.a532e"

Change false to 0 and true to 1 and add all data to check whether the result is > 1.

1 Like

Just to add to the ideas:

The JOIN node may be of use.

But it has its own set of problems.

Unless you can guarantee that the 5 devices all send their messages at/around the same time, it can cause problems.

EG:
device 1, 2, 3, 4 send their message and 5 doesn't. A bit later 1 sends its next message.
That will then activate the joining of 5 messages.

Anyway: good luck.

Oh, @Duncan

To follow up on what was suggested about making the message 0 and 1 rather than false and true.

You just stick a function node that looks at the incoming message and if it is true sends a 1 else it sends a 0.

So that is 5 x function nodes at the input (or output of the device) to change the signals.

You have not followed the example carefully enough. You should be using key/value pair mode in the Join node

Actually, since you are just interested in the count of how many true values there are then an array is may be the best way. How do you know when all the values are available? Do they all come at the same time with a gap between or is there some other way you can know when they are all there?

Hi Colin,

The values are sent every second. I have used the join node with a key, so no timing. Here is the result.
Now i need the function to pick out the 2 X "1"
payload: object
relay_1: 0
relay_2: 0
relay_3: 1
relay_4: 1

So, you write some code in a function node something like this

total = payload.relay_1 + payload_relay_2 + payload.relay_3 + payload.relay_4
if total > 1
{
    send message
}

BUT

Sorry, you said five messages. This is only showing FOUR.

It will be easier to go back to the array version of the join. Set it to output a value on a timeout of 0.5 seconds (so it well send the array when there has been a gap of 0.5 seconds, so you know they are all there), then you can add up the number of true values using, in a function node
const total = msg.payload.reduce((accumulator, currentValue) => accumulator + currentValue)

Then you can test total for >=2 and take whatever action is required.

That code will work with true/false or 1/0 values.

Or if you want to keep it as key/values in an object then

let total = 0
for (const [key, value] of Object.entries(msg.payload)) {
    total += value
}

Which adds up the values of all keys in msg.payload

1 Like

That seems a better way.

Or use JSONata and count the true values. Join the relays manually, using key value, and set the count to 5 and ever subsequent message.

[{"id":"e8b2339b.a97c6","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay1","payload":"true","payloadType":"bool","x":170,"y":2840,"wires":[["a6dcf54.cb62488"]]},{"id":"a6dcf54.cb62488","type":"join","z":"c74669a0.6a34f8","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"5","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":420,"y":2960,"wires":[["b95420ef.cc09e8"]]},{"id":"dfc39466.b8114","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay2","payload":"false","payloadType":"bool","x":180,"y":2880,"wires":[["a6dcf54.cb62488"]]},{"id":"ac03c7de.383bc8","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay3","payload":"true","payloadType":"bool","x":170,"y":2920,"wires":[["a6dcf54.cb62488"]]},{"id":"8045dd02.c4ae9","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay4","payload":"false","payloadType":"bool","x":180,"y":2960,"wires":[["a6dcf54.cb62488"]]},{"id":"b95420ef.cc09e8","type":"change","z":"c74669a0.6a34f8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$count($$.payload.*[$=true]) >= 2","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":2960,"wires":[["38ffe006.30b6e8"]]},{"id":"e4fbe3c3.48595","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay5","payload":"false","payloadType":"bool","x":180,"y":3000,"wires":[["a6dcf54.cb62488"]]},{"id":"fc513290.4edac","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"relay1","payload":"false","payloadType":"bool","x":360,"y":2840,"wires":[["a6dcf54.cb62488"]]},{"id":"38ffe006.30b6e8","type":"debug","z":"c74669a0.6a34f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":710,"y":2880,"wires":[]}]
$count($$.payload.*[$=true]) >= 2

I think it would be better to set the count in the Join node to 2 (and every subsequent message). Otherwise, if one or more channels is not working, then it will never output anything.

Wow, 3 different approaches and I get them all to work. Thanks for the great support, I am learning every day.
Thanks!!!

1 Like

As long as the 5 initial count has happen then the subsequent will work, 2 would work to. The first count of 5 has to happen then everything will be ok. But you could possibly do it all in the join node to with a reduce sequence.