Node-RED Combined State Check

I was reviewing some of my flows as I had noticed that a few things could be better, or there were two flows doing the same thing. I got into a discussion with Markus about a good way to perform checks that didn’t require a coding major to accomplish. We found these two ways to make things easy. Now, the thought process will be opposite, but it condenses the flow without having to code anything.

The First:

This one is my favorite: Combined State Check.

image

This change node checks the status of your globals. All need to test true for the flow to continue to the next step. It eliminates a series of switch nodes checking on globals every step of the way.

Open a new change node and choose J: expression.

image

Click the … on the right and expand it.

$globalContext from the function reference and click “insert”

As in the photo, I have a global that keeps the state of my lower motion sensor for the stairs. I want that in parenthesis and quotes - space - equals - space value and
Adding a line for each global. Boolean (true/false) do not need to be in quotes. Strings do. As shown below with the power state of my monitor. The state false or true. “ON” or “OFF” represents the true value state. If you want the light to be on to move forward or true.

$globalContext("stairslowermotion") = false and
$globalContext("officemonitorpower") = "OFF" and

Click Done and go back to the properties.

Set a boolean “is true”
Then to the bottom and choose checking all rules.

Click done again.
This will check each line in the J expression and stop if one does not match. If it runs through all lines, then the result is true and will move on to the next step in your sequence. Just like a series of switch nodes.

[{"id":"9676af98d06a1d11","type":"switch","z":"269b966381fd84be","name":"Combined State Check","property":"$globalContext(\"stairslowermotion\") = false and\t$globalContext(\"tvbasement\") = false and\t$globalContext(\"bsparebathmotion\") = false and\t$globalContext(\"bsparebathmotion2\") = false and\t$globalContext(\"officemonitorpower\") = \"OFF\"","propertyType":"jsonata","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":2570,"y":640,"wires":[[]]}]

The Second

Combined Global Check

This one takes up a bit more space and uses reverse logic. There are uses for this one because of the additional outputs, but I haven’t thought of anything in my own setup that I would need this for. But, that doesn’t say that there aren’t any.

image

This one uses a J expression as well, but opposite just “true” in the context. Next you set up your globals and be sure to add a bool is true at the end.
At the bottom, you want to choose “stopping at first match”. This will send a false out of the corresponding output. If it gets all the way to true, which will be connected to the next step in the flow. In this case, you could trigger something different from one of the preceding outputs if the flow hits a false. This could be a push notification or a light or an error. It’s flexible.

Hovering over the outputs will also let you see what you’re testing for.

If you want to check for “ON” or “OFF” like in the other node, you would just use a J expression on each line defining one device like above.

Just don’t forget that you check for the opposite in this node test for true so that everything in the list needs to result in false so it skips that line and moves to the next until it hits true at the bottom

The first rows act as a trap. If any of them result in true then it won’t reach the bottom connection to move to the next node. The devices need to result in not true in order for the flow to continue.

[{"id":"8abc54f69d9745a6","type":"switch","z":"269b966381fd84be","name":"Combined Global Check","property":"true","propertyType":"jsonata","rules":[{"t":"eq","v":"bsparebathdoor","vt":"global"},{"t":"eq","v":"bsparebathmotion","vt":"global"},{"t":"eq","v":"bsparebathmotion2","vt":"global"},{"t":"true"}],"checkall":"false","repair":false,"outputs":4,"x":2570,"y":500,"wires":[[],[],[],[]]}]

In the end, it’ll allow you to keep your flows neat and tidy. Sometimes that can prove troubleshooting to be a chore. When setting the first one up, I would recommend using change nodes to make sure that the you have the intended results and you won’t really have a good way to see the failures in logic with these methods.

The second set up, you can put debug nodes on the outputs to see if they come through.

4 Likes

You can also use $not($globalContext("stairslowermotion")) instead of $globalContext("stairslowermotion") = false

Math can also be added to JSONata expressions:

I wanted to keep my temperature close to a desired value but not turn heating on too often. So when deciding whether to turn heating on, instead of comparing the current temperature with the setpoint, I added an offset:

$flowContext('bedroom_temperature') < $flowContext('bedroom_target_temperature') - 0.5

This runs on a 60 min trigger.

For turning off I simply compare the room temperature and setpoint without any offset and it runs on a 15 min trigger so the flow is biased on delaying heating as much as possible.

1 Like

Lots of cool ways to do these things. All without having to code it. Thanks for sharing. Trying to get some new ideas out there for others. I find that there aren’t a lot of good explanations out there for this stuff. It’s what every Node-RED usre needs sometimes.

2 Likes

It’s a steep learning curve, especially for people that don’t know how to code. NR seems easy because it’s visual but for anything more complex it will likely require some degree of programming knowledge (whether it’s function blocks or JSONata expressions).