Node-Red Sample for Sharing

I'm going to try a different approach vs the "samples" Topic.. not just a copy paste of an image and a bucket of code, but an outline of why I chose this path.

First, this uses a Function node and so I'll start by apologizing to all of the people that just went "ewwww"... sorry. I went the other direction, trying to pack it all into one.

I have a "Gloomy Day" Rule that watches MultiSensor 6 illuminance values. If the illuminance is below a threshold, I call it a gloomy day and turn on some extra lights. When the gloom dissipates, I turn the lights back off.

In my situation I've picked 4 of my dozen or so illuminance reporters and plotted them over time. I found values for my rooms, my specific MS6's that work for me. If you want to try this, you'll have to determine the values for your house, your rooms.

Now I need to determine that all the 'zones' are above the predetermined value. When they are, illuminance is considered 'true' and the lights can be turned off. Yes, true equals off. :slight_smile:

There's a old technique for comparing a value against a range... (x - min) * (x - max) <= 0 is true if it's within range, false if not.
For me, I just care that it's above a value, therefore min=0 and the entire term can be discarded: (x-max) <= 0

Functions are written in Javascript and javascript 'trickery' allows one to add booleans:
a += (x-max) <= 0
a += (y-max) <= 0

if (a >=2) then.... functions as an AND
Got 4 devices like I do then you just += them all and the compare is a >= 4

You can paste this into your favorite JavaScript tester and see it in action:

var x = 17;
var y = 16;
var z = 55;
var o = 651;


var delta = false;
delta += (x - 18) >=0;
console.warn (delta);
delta += (y - 18) >=0;
console.warn (delta);
delta += (z - 40) >=0;
console.warn (delta);
delta += (o - 650) >=0;
console.warn (delta);

I used https://playcode.io/ in my example
The Console output looks like:
0
0
1
2
for a total of 2 trues.. not enough, I need 4 trues. You can change the values in the top 4 lines and watch the results change.

I have my core answer now, I just need to make it usable. Function Nodes allow you to have as many outputs as you want, and I want 2.. equivalent to a Switch Node looking for true vs false.

if (delta >= 4 )
    {return [msg, null];}
else
    {return [null, msg];}

The msg gets sent to the first output if True, the 2nd output if False, precisely like a Switch Node

That leaves only the input side of things.. I need to get "z y z and o" from my MultiSensors.. and I use a different technique there too..

JavaScript doesn't have a Map method like Groovy, but if you squint, key: value pairs are the same anywhere...

I define a Flow specific variable, initialize it to 'empty' then as each Hubitat Event occurs, I save it. This way I can check all values on each new Event, because I want 4 True's. These 3 lines do this for me.. get the 'map' and update the latest Event, then save it back.
prState = flow.get('prState5');
prState[msg.topic.split(" ").slice(-1)] = msg.payload.value
flow.set('prState5', prState);

My MultiSensors all have names that make sense to me, and in this case I want the 2nd portion of the name. Thus if the name of my MultiSensor is "MultiSensor6K (familyroom)" I use the "(familyroom)" portion as the Key in the Key:value pair.
That's all the bit and pieces... going back to the original equation, instead of "x" I use:
delta += prState['(familyroom)'] - 18 >= 0;
to compare the Illuminance value of the 'familyroom' MultiSensor to 18 (lux) along with 3 others for the total of 4.

Here's the entire Function:

/* generic state memory. 
   Each event has a topic and payload which are stored as a Key:Value pair.
   All the pairs are retrieved, one is updated, then all are saved for next time.
*/
prState = flow.get('prState5');
prState[msg.topic.split(" ").slice(-1)] = msg.payload.value
flow.set('prState5', prState);
//node.warn("t="+msg.topic.split(" ").slice(-1)+":"+msg.payload.value);

// Use the mapped key[value] to perform the logic, boolean or arithmetic.
var delta = false;
    delta += prState['(familyroom)']   -  18 >= 0;
    delta += prState['(livingroom3)']  -  18 >= 0;
    delta += prState['(kitchen)']      -  30 >= 0;
    delta += prState['(frontWalkway)'] - 650 >= 0;

if (delta >= 4 )
    {return [msg, null];}
else
    {return [null, msg];}

Screen Shot 2020-08-07 at 10.32.42 PM

I hope this is of some value.. perhaps you're having trouble sleeping... :slight_smile:

Just to be clear.. this is about 20 seconds worth of clicking in RuleMachine. :slight_smile: It's 8x harder in Node-Red. But the FUN is in converting... naturally :slight_smile:

6 Likes

thanks for sharing I find these mini"code reviews" to be a great learning experiance

4 Likes

I missed explicitly showing the number of Function Node outputs:

Screen Shot 2020-08-08 at 7.42.34 AM

it's at the very bottom of the Node Editor for Function or Unsafe Function.

I’ll read this properly agaian when in front of the PC. I use my lights in a similar way, so this is very interesting. Thanks for sharing :+1:

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.