Node-RED as a rule/script engine for OpenHAB

rules
node-red
Tags: #<Tag:0x00007fd3138e3c38> #<Tag:0x00007fd3138e3af8>

(dalibor) #161

I tried googling but didn’t find much specifics, can you elaborate a bit or maybe link to relevant resources/examples?
I know how I wish this would work in flows, but I dare not let my imagination run wild only to be disappointed later :slight_smile:

Love node-red btw, now I only make rules there now and am yet to find a limitation. There is a lot of place for improvements, but it is mostly due to “simplicity” of nodes, would like some extra functionality for nodes but hey… I might have to make that myself :slight_smile:
Using subflows makes things A LOT easier for repetitive things (like checking on openhab item states and parsing them etc…)

Yesterday I made relatively complex heating control with time schedules and sensor-based auto control, as well as “manual override”, and integrated it easily with openhab basic UI (and android app).
And it is one of the few things my wife actually liked, she can now set min and max temperature and manually override the heating mode if she wants to. And it was fun for me to “program”, not to mention veeeery easy debuging and testing.
It will also log all activity (via custom flow) in database, send me daily “digest” of what was happening, alert me if something is not right etc etc.

As I am developer myself so it is not difficult for me to write the code for rules, but using my spare time with some boring repetitive code is not a favorite thing to do. Not to mention tedious debugging and documenting things, and googling for syntax etc.

Enough about how awesome node-red is, I might someday write a novel about my romance with it :slight_smile:


(Brian M. Pedersen) #162

I think you would inject a string with the same HSB command that you would send to your item directly from OH.
I normally use the RESt api to test the strings out/debugging, it’s a bit faster.


(Simon) #163

Thanks. Can you share some examples?


(Brian M. Pedersen) #164

sure, there is my adjustment of my light brightness:

[{"id":"d9021708.ce6308","type":"openhab2-get","z":"b44f7d9a.bc6dc","name":"","controller":"b5665ec0.78463","itemname":"Color_Stue_LED","x":870,"y":520,"wires":[["d82004b4.3a7138","d6b05b45.5d4f28"]]},{"id":"d6b05b45.5d4f28","type":"function","z":"b44f7d9a.bc6dc","name":"split HSB value","func":"var values = msg.payload.state.split(\",\");\nvar result = [];\n\n\nfor(i=0; i<values.length; i++) {\n    msg.payload[i] = { payload: values[i] }\n}\n\n\nreturn msg;","outputs":"1","noerr":0,"x":1060,"y":420,"wires":[["cb911c99.f2ca2","733b57bb.9a8028"]]},{"id":"733b57bb.9a8028","type":"function","z":"b44f7d9a.bc6dc","name":"Add to B","func":"var brightness = msg.payload[\"2\"].payload;\nvar CubeAngel = msg.angel;\nvar newBrightness;\n\nnewBrightness = brightness*1 + CubeAngel*1;\n\nif (newBrightness > 100){ newBrightness = 100;}\n\nif (newBrightness < 0){ newBrightness = 0;}\n\nmsg.payload = newBrightness;\n\nnode.status({fill:\"green\",shape:\"ring\",text: msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1240,"y":420,"wires":[["b4033a45.d8d448","93ca70cb.b14ee"]]},{"id":"b4033a45.d8d448","type":"openhab2-out","z":"b44f7d9a.bc6dc","name":"","controller":"b5665ec0.78463","itemname":"gLights_color","topic":"ItemCommand","payload":"","x":1450,"y":400,"wires":[]},{"id":"b5665ec0.78463","type":"openhab2-controller","z":"","name":"Openhab","protocol":"http","host":"192.168.1.109","port":"8080","path":"","username":"","password":""}]

and generate random color:

[{"id":"d9021708.ce6308","type":"openhab2-get","z":"b44f7d9a.bc6dc","name":"","controller":"b5665ec0.78463","itemname":"Color_Stue_LED","x":870,"y":520,"wires":[["d82004b4.3a7138","d6b05b45.5d4f28"]]},{"id":"d6b05b45.5d4f28","type":"function","z":"b44f7d9a.bc6dc","name":"split HSB value","func":"var values = msg.payload.state.split(\",\");\nvar result = [];\n\n\nfor(i=0; i<values.length; i++) {\n    msg.payload[i] = { payload: values[i] }\n}\n\n\nreturn msg;","outputs":"1","noerr":0,"x":1060,"y":420,"wires":[["cb911c99.f2ca2","733b57bb.9a8028"]]},{"id":"733b57bb.9a8028","type":"function","z":"b44f7d9a.bc6dc","name":"Add to B","func":"var brightness = msg.payload[\"2\"].payload;\nvar CubeAngel = msg.angel;\nvar newBrightness;\n\nnewBrightness = brightness*1 + CubeAngel*1;\n\nif (newBrightness > 100){ newBrightness = 100;}\n\nif (newBrightness < 0){ newBrightness = 0;}\n\nmsg.payload = newBrightness;\n\nnode.status({fill:\"green\",shape:\"ring\",text: msg.payload});\nreturn msg;","outputs":1,"noerr":0,"x":1240,"y":420,"wires":[["b4033a45.d8d448","93ca70cb.b14ee"]]},{"id":"b4033a45.d8d448","type":"openhab2-out","z":"b44f7d9a.bc6dc","name":"","controller":"b5665ec0.78463","itemname":"gLights_color","topic":"ItemCommand","payload":"","x":1450,"y":400,"wires":[]},{"id":"b5665ec0.78463","type":"openhab2-controller","z":"","name":"Openhab","protocol":"http","host":"192.168.1.109","port":"8080","path":"","username":"","password":""}]

(Simon) #165

Thanks. That helps a lot.


(shane kevin) #166

Hi node-red guruers, how to interactive with more than one items in node-red? For example:
when I arrive home: a presence item stats changed to ON,
and it’s dark outside(a time of day item),
then turn the lights on(a light item),
if I arrive home but it’s daylight, then the light stays OFF.

It can be done by rule engine inside openhab, but how to do this in node-red?
I am pretty sure this can be done via a single function node, but I don’t know how, could someone please help me? Thanks


(Brian M. Pedersen) #167

I have a flow like that here:

code:

[{"id":"a4cfead0.cc9458","type":"openhab2-in","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotion_Sensor_Gang_Status","x":210,"y":120,"wires":[[],["5d828df3.af3d44"]]},{"id":"67a8dc9d.c6e354","type":"openhab2-in","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotion_Sensor_Stue_Vindue_Status","x":230,"y":240,"wires":[[],["5d828df3.af3d44"]]},{"id":"36585125.36309e","type":"openhab2-in","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotion_Sensor_Stue2_Status","x":210,"y":300,"wires":[[],["5d828df3.af3d44"]]},{"id":"d0b85519.2ba3b8","type":"openhab2-in","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotion_Sensor_Sove_Status","x":210,"y":180,"wires":[[],["5d828df3.af3d44"]]},{"id":"b03fe8f4.cc5bf8","type":"openhab2-in","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotion_Sensor_Kitchen_Status","x":220,"y":60,"wires":[[],["5d828df3.af3d44"]]},{"id":"6951d663.52b568","type":"switch","z":"9c38b59d.29bee8","name":"On?","property":"payload.payload.value","propertyType":"msg","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","outputs":1,"x":550,"y":240,"wires":[["63a5e555.de2c2c","194af219.c6eefe"]]},{"id":"4c52683d.1cc438","type":"switch","z":"9c38b59d.29bee8","name":"","property":"item","propertyType":"msg","rules":[{"t":"eq","v":"swMotion_Sensor_Kitchen_Status","vt":"str"},{"t":"eq","v":"swMotion_Sensor_Gang_Status","vt":"str"},{"t":"eq","v":"swMotion_Sensor_Sove_Status","vt":"str"},{"t":"eq","v":"swMotion_Sensor_Stue_Status","vt":"str"},{"t":"eq","v":"swMotion_Sensor_Stue2_Status","vt":"str"}],"checkall":"true","outputs":5,"x":1090,"y":120,"wires":[["d410c389.1fb6c"],["9ffca470.064758"],["88af2ec.9635ad"],["d479fddd.a0de5"],["d479fddd.a0de5","a225af8c.de63c"]]},{"id":"d410c389.1fb6c","type":"openhab2-out","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"gLights_Kitchen_toggle","topic":"ItemCommand","payload":"","x":1430,"y":100,"wires":[]},{"id":"9ffca470.064758","type":"openhab2-out","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"gLights_Gang_toggle","topic":"ItemCommand","payload":"","x":1420,"y":140,"wires":[]},{"id":"9af01c6a.938b4","type":"openhab2-out","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"gLights_Stue_toggle","topic":"ItemCommand","payload":"","x":1440,"y":240,"wires":[]},{"id":"5dddabc1.108fb4","type":"openhab2-out","z":"9c38b59d.29bee8","name":"Plug_stue_lampe","controller":"b5665ec0.78463","itemname":"swPlug_Stue_LAMPE","topic":"ItemCommand","payload":"","x":1430,"y":280,"wires":[]},{"id":"88af2ec.9635ad","type":"openhab2-out","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"gLights_Sove_toggle","topic":"ItemCommand","payload":"","x":1440,"y":180,"wires":[]},{"id":"55bc5258.61eb3c","type":"debug","z":"9c38b59d.29bee8","name":"","active":false,"console":"false","complete":"true","x":870,"y":280,"wires":[]},{"id":"63a5e555.de2c2c","type":"switch","z":"9c38b59d.29bee8","name":"Dark?","property":"IsItDark","propertyType":"global","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","outputs":1,"x":630,"y":120,"wires":[["5e2495e9.0c272c","83a90d29.5906c"]]},{"id":"3dc78b12.6057c4","type":"inject","z":"9c38b59d.29bee8","name":"","topic":"","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"x":1170,"y":40,"wires":[["d410c389.1fb6c","9ffca470.064758","88af2ec.9635ad","9af01c6a.938b4","5dddabc1.108fb4"]]},{"id":"194af219.c6eefe","type":"debug","z":"9c38b59d.29bee8","name":"","active":false,"console":"false","complete":"true","x":690,"y":280,"wires":[]},{"id":"5e2495e9.0c272c","type":"debug","z":"9c38b59d.29bee8","name":"","active":false,"console":"false","complete":"true","x":690,"y":40,"wires":[]},{"id":"7e18f04f.71e09","type":"switch","z":"9c38b59d.29bee8","name":"swMotionSensorLightON?","property":"payload.state","propertyType":"msg","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","outputs":1,"x":870,"y":120,"wires":[["cea75303.c2a1","277bfe1d.5dedc2"]]},{"id":"83a90d29.5906c","type":"openhab2-get","z":"9c38b59d.29bee8","name":"","controller":"b5665ec0.78463","itemname":"swMotionSensorLight","x":720,"y":180,"wires":[["7e18f04f.71e09","55bc5258.61eb3c"]]},{"id":"cea75303.c2a1","type":"debug","z":"9c38b59d.29bee8","name":"","active":false,"console":"false","complete":"true","x":890,"y":40,"wires":[]},{"id":"5d828df3.af3d44","type":"trigger","z":"9c38b59d.29bee8","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"200","extend":false,"units":"ms","reset":"","name":"","x":460,"y":160,"wires":[["6951d663.52b568","ee85a1e8.c96bc"]]},{"id":"ee85a1e8.c96bc","type":"debug","z":"9c38b59d.29bee8","name":"","active":false,"console":"false","complete":"true","x":530,"y":40,"wires":[]},{"id":"277bfe1d.5dedc2","type":"change","z":"9c38b59d.29bee8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":220,"wires":[["4c52683d.1cc438"]]},{"id":"d479fddd.a0de5","type":"switch","z":"9c38b59d.29bee8","name":"MotionSensingTriggerStue?","property":"MotionSensingTriggerStue","propertyType":"global","rules":[{"t":"neq","v":"OFF","vt":"str"}],"checkall":"true","outputs":1,"x":1160,"y":280,"wires":[["5dddabc1.108fb4","9af01c6a.938b4","31a54a7d.cfbd36"]]},{"id":"31a54a7d.cfbd36","type":"debug","z":"9c38b59d.29bee8","name":"","active":true,"console":"false","complete":"true","x":1390,"y":340,"wires":[]},{"id":"a225af8c.de63c","type":"debug","z":"9c38b59d.29bee8","name":"","active":true,"console":"false","complete":"true","x":1210,"y":340,"wires":[]},{"id":"b5665ec0.78463","type":"openhab2-controller","z":"","name":"Openhab","protocol":"http","host":"192.168.1.109","port":"8080","path":"","username":"","password":""}]

(shane kevin) #168

Hey @Moellegaard Thanks for providing such a nice flow for me, however the presence dection is a bit tricky, because usually we need to check if the “presence item” is really “not presence”(which means there is turely no one at home), and we have to deal with many false aleart(like off for several mins and on again).

so my thought was when detecting item sends a OFF state, I use a delay node and set to 10 mins to delay the off msg, and then check again if the item still remain OFF state, if ture then turn off lights. if during the 10 mins delay the item state becomes ON again, then do nothing to the lights…


I’ve managed to set the first part, but not sure how to do the “check the item state after 10mins and if still reports off state then trun off lights, if item state is on then do nothing” part…
sorry for the noob question… although there is no false state during actual “I am out”, but I just want to make sure that I kill all false reports during 10 mins delay…


(shane kevin) #169

OK I think I figure it out with a stupid solution for this

so, here is some explain, and please help to simple the flow:

  1. when a phone is in house(returns True), and it’s dark outside(from BigTimer node, returns True), then both true go to the AND node(reutrn ture of cuz).
  2. a switch node to seperate the turn and false situration
  3. when true = phone item(green node) is true = I am home! go ahead and send the ON payload to lights
  4. when false, first wait for a delay node, and then check the current phone state(OR node), so if it’s a false alert, means I am still home, the phone still return true, then the OR node turns True, so the light still ON.
  5. when false, again wait for the delay node then check again the phone state(OR node), if I really outside, the phone state(green node) of cuz remains OFF=false, then the OR node returns a FALSE state, so turn the light OFF.

So in this case even when a false alert reports I am outside and then after few sec I am home again, the OR node will always make sure do not put my light off and on again and again…

But still… this look silly… could someone please simple the rule process, thanks


(furax54) #170

It’s a bad idea to use boolean operator in node-red. node-red is working with event and you should use event and avoid logic nodes like AND/OR …
For you example, a good solution is to store your bigtimer in a flow variable.
In the following example, the two inject nodes with night topic are for the bigtimer node (output ON/OFF and store in flow)
and presence:ON/OFF are for your wifi detection.


here is the flow :

[{"id":"468344b0.e670bc","type":"change","z":"662e1686.65a5","name":"","rules":[{"t":"set","p":"night","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":80,"wires":[[]]},{"id":"8285bc1d.408e18","type":"switch","z":"662e1686.65a5","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":370,"y":180,"wires":[["1488fa50.5f54be"]]},{"id":"1488fa50.5f54be","type":"switch","z":"662e1686.65a5","name":"","property":"night","propertyType":"flow","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":200,"wires":[["952f6407.c87e48"]]},{"id":"81ecc84e.bba5d","type":"trigger","z":"662e1686.65a5","op1":"","op2":"OFF","op1type":"nul","op2type":"str","duration":"10","extend":false,"units":"s","reset":"ON","bytopic":"all","name":"","x":390,"y":260,"wires":[["1488fa50.5f54be"]]},{"id":"95740e23.0e7508","type":"inject","z":"662e1686.65a5","name":"","topic":"presence","payload":"ON","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":220,"wires":[["8285bc1d.408e18","81ecc84e.bba5d"]]},{"id":"cd3ffd8b.c6bc2","type":"inject","z":"662e1686.65a5","name":"","topic":"presence","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":260,"wires":[["8285bc1d.408e18","81ecc84e.bba5d"]]},{"id":"1363e402.33a5c4","type":"inject","z":"662e1686.65a5","name":"","topic":"night","payload":"ON","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":40,"wires":[["468344b0.e670bc"]]},{"id":"86d3372f.55c578","type":"inject","z":"662e1686.65a5","name":"","topic":"night","payload":"OFF","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":80,"wires":[["468344b0.e670bc"]]},{"id":"952f6407.c87e48","type":"debug","z":"662e1686.65a5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":200,"wires":[]}]

(furax54) #171

And I forgot if you want lights to turn off when night is comming and phone is already off use an “openhab get” node to retrieve phone state and process the flow for testing it. something like this :


(shane kevin) #172

Thanks man, really simple flow with buildin node to do this job.
but what if 2 phones need to check? I need the lights go off when 2 phones are both “not at home”, and if one of the phone at home will maintain lights on stat(of cuz need to compare the daylight, when night lights on, when day lights off)?
also, could u please explain why using logic node is a bad idea inside nodered? Does this logic will cause event problem or somehow make nodered unstable?


I was wondering before why node red doesn’t provide a logic node, looks like there must have some reason not to do that, but why?


(shane kevin) #173


and still, we need to double check the phone state, is it really off or just a false off caused by such as arping false off state… sometimes arping(or hping) may report a off state(iphone deep sleep) and then after a few sec it reports on state(which will causing the lights off a few sec and go back to on, pretty annoying)

and btw, I don’t have a false off in my router side, but I just want to make sure…you know, kill the possibility…

so, still need to check back to the phone state
when it’s truely off, turn off lights
when it’s a false off, the phone reports on state, do nothing(or send on)

of cuz with 2 phones need to check, but how… I am pretty a super noob here…


(joris) #174

hello All

this may be painfully obvious to some of you, but i read and i read, and i did not find the answer. Is there a way to let node-red send push notifications through the myopenHAB cloud to attached devices, an equivalent to the sendNotification (be it sendNotification, sendBroadcastNotification, or sendLogNotification) function in rules?


(Brian M. Pedersen) #175

Yes, you make a rule e.g. like this:

rule "stSay "
when
    Item stSay received update
    
then
    say(stSay.state.toString)
    
end 

And you update your item in NR


(joris) #176

Okay I understand, but I was examining NR specifically to avoid writing rules. So there is no direct way of doing this?


(Brian M. Pedersen) #177

Well, there might be, but for me this seems like a easy solution, I think you can find others.
Oh btw, this is the rules im using for sending notifications:

rule "Send Notification"
when
	Item stNotification received update
then
	sendBroadcastNotification(stNotification.state.toString)
end

(furax54) #178

We check after 10s please look the trigger node properties, if we recieve ON, we reset the trigger. We send OFF only 10 seconds after Fabien_Wifi is OFF. It’s like a check because if we recieve ON, the trigger is reset. Please test the flow I send in my previous message.
With 2 phone, I think it’s better to use a Group inside openhab with AND from the 2 phones. I’m using it in combination with motion sensors.


(shane kevin) #179

Thanks man, I misunderstanding the trigger node, I thought the trigger node when receive back to a ON msg means reset the counting time and then send OFF again… very stupid I know… :frowning:
Yeah your flow is way much better than me and it’s all built in node, thanks again man! You really helped a lot!


(David De Marco) #180

Have been following the various threads of using Node-RED as the rule engine and have added onto my OpenHab Hub (Raspberry PI 3 using standard manual install). Now slowing moving my routines over to it as definitely find it easy to build and debug with Node-RED.

I was a programmer and still work in VB, Javascript, Python and abit of Java so the transition to using Javascript within Node-RED was relatively easy. Some observations to share so far.

What I like:
The building and debug is massively easier that using OpenHab as you can add injections and debug messages very quickly. Deploy, test and see results very quickly.

There are a huge number of Node-Red integrations which you can expand the base install with. From what I’ve read I think the OpenHabian team have been adding alot of these as default if you use OpenHabian.

The javascript object model (once you understand it - see below - makes it really easy to enrich the messages being sent between nodes.

What I don’t like
Basing this more on that I am familiar with Javascript. You need to have or build a good understanding of the Javascript object model. And as above once you get your head around this alot of possibilities open up.

The third party additions to the system require some learning to understand how they work. For example, the LIFX binding in Openhab makes it very easy to work with the lights, where as in Node-RED you need to learn how to make the correct calls to the LIFX API, also found that not all the new additions work. Will do a post next on this next for LIFX.

Lastly you need to get your head around event processing. I’ve seen a few posts in the threads that have added in nodes for boolean logic (AND/OR etc). These do work, but are shims on making Node-RED behave a way it’s not designed to do (nor intends to address). This is also a part of learning on Javascript events etc. Fully admit it took me ages to move from the mindset of Visual Basic sequential execution to the event driven of the paradigm of Javascript event handlers.

Overall I do like Node-RED and working on moving the presence detection routines provided by Rik over to it if I can. At the moment they work fine via OpenHAB and two systems work very well together. Don’t really have any intention of getting rid of OpenHAB as its very solid (and I’m on the edge release version). Will share shortly some of the work I’ve been doing in OpenHAB to help others who want to dabble in.

Final note to those who havent’ use Node-RED before and want to add it to your OpenHAB system is go slowly. Start with a couple of simple items which give you insight into how Node-RED works.

Hope the above helps.