Best Way to organise Triggers and Actions in a node red automation system?

Hi folks, I'm starting a new project where node red will handle the basic automation tasks.

I'll have various inputs ranging from Video Analytics, Door contacts, Switches to name a few.
My outputs will Vary from relays to email alerts and the odd audio notification but essentially the system will have inputs, and outputs.

I'd like to keep it clean and tidy, and build a system which is easy to modify and add to in the future.

The inputs and outputs are not always related. Some inputs will switch many outputs, whilst some outputs will be switched by many inputs.

I was hoping to have some kind of table or array which will hold the cause and effect info. I've made a demo spreadsheet to try and show what I mean:

Take the intruder alarm as an example. Following the row along we see that it will force on the three lights but those lights will also have other triggers from other events.

I'm not sure the best way to do this but I'd like to keep it as simple and straightforward as possible. I'm sure there's a great way! but I'm still relatively new to node-red so hopefully I'll get some great pointers here.

Thank you :slight_smile:

I'm going to beat everyone here to the punch. There is one way I know of to keep things clean and tidy.

Functions.

Each output gets an associated function. All inputs go to every function. If you want to really keep it tidy, use link ins and outs so it all looks like this:
image
Notice how all the inputs (I used inject nodes) feed into one link out. Each link in on the functions connect to that link out. Inside the function, you'll simply put if statements to check for the specific conditions that would turn something on or off. And if you keep the logic simple for whatever is simple on/off, it gets really easy. Take your intruder alarm example. It turns on the smoking shelter light. So for the smoking shelter light, your function would look like this (assuming each input is either on/off and represented true/false):

if(intruderAlarm || fireAlarm || smokeAreaFireDoor || wpLights){
    return({payload:true});
else{
    return({payload:false});
}

That's the simplest way of explanation. Obviously you can add things to the function to keep track of the various inputs and such so you can reference any/all of them in your function without having to call them. That's the versatility of functions. Plus, the design scales well so you can copy an output group and paste several copies back into your flow for more outputs. You can do the same for inputs by simply adding the input, tying it to the link node and editing the functions for the appropriate outputs to accommodate.

Make sense?

I would do something like this:

Where each location would be on a tab of it's own (in my example I have them all on one tab).

You build a link call flow for each action/location (Smoking Shelter Light, Carpark Alarm etc) and in it define the actions to be taken. (in my example I have one action for on and off. You might need to split this into several if multiple actions needed to be done))

You build a link call flow for each Cause that links to each device you will control. You add as many as needed to deal with that Cause.

Once you have them all created, it will be just a matter of tying them together. Here is the sample flow:

[{"id":"67aa08691d6ea6c3","type":"tab","label":"Flow 4","disabled":false,"info":"","env":[]},{"id":"b9a26efeb089b3ab","type":"group","z":"67aa08691d6ea6c3","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["2639f75b28291139","dd05d4e38a41f36b","f2095e363ed8f841","07c3c54067d5c74f","41607734f9f9ef06"],"x":114,"y":579,"w":712,"h":122},{"id":"d7a993850e0ca402","type":"group","z":"67aa08691d6ea6c3","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["5d6ff60b369ac3b1","43f626ca6affd403","f4efff21199f7543","c1449acf83e42581","88b75e04bd3f55ab"],"x":114,"y":719,"w":712,"h":122},{"id":"95febce1c94afef0","type":"group","z":"67aa08691d6ea6c3","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["52fcb93174a25a00","d7b567decc286a35","bd8739e3ea16cef7","714c8ca6777bed20","0d8ffd44d9cb5b70","07b8250f0d44a5d7"],"x":74,"y":359,"w":922,"h":82},{"id":"625f8219a1e020f9","type":"group","z":"67aa08691d6ea6c3","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["a72f573232bcfdb7","918e3a35baad49ac","faf34bd25867df6e","390f4764d68ccbdf"],"x":74,"y":459,"w":922,"h":82},{"id":"5eb7062cae8db8fb","type":"group","z":"67aa08691d6ea6c3","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["0414954a30bcbe50","83094489e43e3ed0","33f863949d40b65e","567dac9cc1ee5d2c","9e162c3686b1ce5a"],"x":114,"y":859,"w":712,"h":122},{"id":"22d95cbaffe5b632","type":"switch","z":"67aa08691d6ea6c3","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"Cam 1 Line Crossing","vt":"str"},{"t":"eq","v":"Cam 2 Line Crossing","vt":"str"},{"t":"eq","v":"Cam 3 Line Crossing","vt":"str"},{"t":"eq","v":"Cam 4 Line Crossing","vt":"str"},{"t":"eq","v":"Intruder Alarm Activate","vt":"str"},{"t":"eq","v":"Fire Alarm Activate","vt":"str"},{"t":"eq","v":"Recption Light Timer","vt":"str"}],"checkall":"false","repair":false,"outputs":7,"x":350,"y":160,"wires":[["3d7836222e90f9a1"],["6dc38b628a45528c"],["ce57489cec6bd0fb"],["b86dbd3c436f8bfb"],["8e0c2e85884394f3"],["84fdeb98bf46d024"],["9e3e0c305c5a4959"]]},{"id":"3d7836222e90f9a1","type":"link call","z":"67aa08691d6ea6c3","name":"Cam 1 Line Crossing","links":[],"linkType":"static","timeout":"30","x":580,"y":60,"wires":[[]]},{"id":"6dc38b628a45528c","type":"link call","z":"67aa08691d6ea6c3","name":"Cam 2 Line Crossing","links":[],"linkType":"static","timeout":"30","x":580,"y":100,"wires":[[]]},{"id":"ce57489cec6bd0fb","type":"link call","z":"67aa08691d6ea6c3","name":"Cam 3 Line Crossing","links":[],"linkType":"static","timeout":"30","x":580,"y":140,"wires":[[]]},{"id":"b86dbd3c436f8bfb","type":"link call","z":"67aa08691d6ea6c3","name":"Cam 4 Line Crossing","links":[],"linkType":"static","timeout":"30","x":580,"y":180,"wires":[[]]},{"id":"8e0c2e85884394f3","type":"link call","z":"67aa08691d6ea6c3","name":"to Intruder Alarm Activate","links":["52fcb93174a25a00"],"linkType":"static","timeout":"30","x":590,"y":220,"wires":[["938fa47a10c459ad"]]},{"id":"84fdeb98bf46d024","type":"link call","z":"67aa08691d6ea6c3","name":"Fire Alarm Activate","links":[],"linkType":"static","timeout":"30","x":570,"y":260,"wires":[[]]},{"id":"a54dfa1e70e07453","type":"inject","z":"67aa08691d6ea6c3","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Intruder Alarm Activate","payloadType":"str","x":160,"y":160,"wires":[["22d95cbaffe5b632"]]},{"id":"52fcb93174a25a00","type":"link in","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"Intruder Alarm Activate","links":[],"x":200,"y":400,"wires":[["d7b567decc286a35"]],"l":true},{"id":"2639f75b28291139","type":"link in","z":"67aa08691d6ea6c3","g":"b9a26efeb089b3ab","name":"Smoking Shelter Light on/off","links":[],"x":260,"y":640,"wires":[["dd05d4e38a41f36b"]],"l":true},{"id":"dd05d4e38a41f36b","type":"switch","z":"67aa08691d6ea6c3","g":"b9a26efeb089b3ab","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"FON","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":490,"y":640,"wires":[["f2095e363ed8f841"],["07c3c54067d5c74f"]]},{"id":"d7b567decc286a35","type":"change","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"FON","rules":[{"t":"set","p":"payload","pt":"msg","to":"FON","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":400,"wires":[["bd8739e3ea16cef7"]]},{"id":"f2095e363ed8f841","type":"function","z":"67aa08691d6ea6c3","g":"b9a26efeb089b3ab","name":"FON","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":620,"wires":[["41607734f9f9ef06"]]},{"id":"07c3c54067d5c74f","type":"function","z":"67aa08691d6ea6c3","g":"b9a26efeb089b3ab","name":"FOFF","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":660,"wires":[["41607734f9f9ef06"]]},{"id":"bd8739e3ea16cef7","type":"link call","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"SSL ON","links":["2639f75b28291139"],"linkType":"static","timeout":"30","x":520,"y":400,"wires":[["714c8ca6777bed20"]]},{"id":"41607734f9f9ef06","type":"link out","z":"67aa08691d6ea6c3","g":"b9a26efeb089b3ab","name":"SSL return","mode":"return","links":[],"x":785,"y":640,"wires":[]},{"id":"938fa47a10c459ad","type":"debug","z":"67aa08691d6ea6c3","name":"debug 37","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":880,"y":220,"wires":[]},{"id":"5d6ff60b369ac3b1","type":"link in","z":"67aa08691d6ea6c3","g":"d7a993850e0ca402","name":"Carpark Light on/off","links":[],"x":230,"y":780,"wires":[["43f626ca6affd403"]],"l":true},{"id":"43f626ca6affd403","type":"switch","z":"67aa08691d6ea6c3","g":"d7a993850e0ca402","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"FON","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":490,"y":780,"wires":[["f4efff21199f7543"],["c1449acf83e42581"]]},{"id":"f4efff21199f7543","type":"function","z":"67aa08691d6ea6c3","g":"d7a993850e0ca402","name":"FON","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":760,"wires":[["88b75e04bd3f55ab"]]},{"id":"c1449acf83e42581","type":"function","z":"67aa08691d6ea6c3","g":"d7a993850e0ca402","name":"FOFF","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":800,"wires":[["88b75e04bd3f55ab"]]},{"id":"88b75e04bd3f55ab","type":"link out","z":"67aa08691d6ea6c3","g":"d7a993850e0ca402","name":"SSL return","mode":"return","links":[],"x":785,"y":780,"wires":[]},{"id":"0414954a30bcbe50","type":"link in","z":"67aa08691d6ea6c3","g":"5eb7062cae8db8fb","name":"Recption on/off","links":[],"x":220,"y":920,"wires":[["83094489e43e3ed0"]],"l":true},{"id":"83094489e43e3ed0","type":"switch","z":"67aa08691d6ea6c3","g":"5eb7062cae8db8fb","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"FON","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":490,"y":920,"wires":[["33f863949d40b65e"],["567dac9cc1ee5d2c"]]},{"id":"33f863949d40b65e","type":"function","z":"67aa08691d6ea6c3","g":"5eb7062cae8db8fb","name":"FON","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":900,"wires":[["9e162c3686b1ce5a"]]},{"id":"567dac9cc1ee5d2c","type":"function","z":"67aa08691d6ea6c3","g":"5eb7062cae8db8fb","name":"FOFF","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":940,"wires":[["9e162c3686b1ce5a"]]},{"id":"9e162c3686b1ce5a","type":"link out","z":"67aa08691d6ea6c3","g":"5eb7062cae8db8fb","name":"SSL return","mode":"return","links":[],"x":785,"y":920,"wires":[]},{"id":"714c8ca6777bed20","type":"link call","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"CP ON","links":["5d6ff60b369ac3b1"],"linkType":"static","timeout":"30","x":680,"y":400,"wires":[["0d8ffd44d9cb5b70"]]},{"id":"0d8ffd44d9cb5b70","type":"link call","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"Recption ON","links":["0414954a30bcbe50"],"linkType":"static","timeout":"30","x":850,"y":400,"wires":[["07b8250f0d44a5d7"]]},{"id":"07b8250f0d44a5d7","type":"link out","z":"67aa08691d6ea6c3","g":"95febce1c94afef0","name":"link out 4","mode":"return","links":[],"x":955,"y":400,"wires":[]},{"id":"a72f573232bcfdb7","type":"link in","z":"67aa08691d6ea6c3","g":"625f8219a1e020f9","name":"Recption Light Timer","links":[],"x":190,"y":500,"wires":[["918e3a35baad49ac"]],"l":true},{"id":"918e3a35baad49ac","type":"change","z":"67aa08691d6ea6c3","g":"625f8219a1e020f9","name":"FON","rules":[{"t":"set","p":"payload","pt":"msg","to":"FON","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":500,"wires":[["faf34bd25867df6e"]]},{"id":"faf34bd25867df6e","type":"link call","z":"67aa08691d6ea6c3","g":"625f8219a1e020f9","name":"Recption ON","links":["0414954a30bcbe50"],"linkType":"static","timeout":"30","x":850,"y":500,"wires":[["390f4764d68ccbdf"]]},{"id":"390f4764d68ccbdf","type":"link out","z":"67aa08691d6ea6c3","g":"625f8219a1e020f9","name":"link out 5","mode":"return","links":[],"x":955,"y":500,"wires":[]},{"id":"9e3e0c305c5a4959","type":"link call","z":"67aa08691d6ea6c3","name":"Recption Light Timer","links":["a72f573232bcfdb7"],"linkType":"static","timeout":"30","x":580,"y":300,"wires":[["1f975a32acfaf49d"]]},{"id":"1f975a32acfaf49d","type":"debug","z":"67aa08691d6ea6c3","name":"debug 38","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":880,"y":300,"wires":[]}]
2 Likes

Thanks! This is near enough the solution I'm going with. The project is still a work in progress hence no reply here, yet. I wanted to make a post to stop the thread being closed and to say thanks for the help. I'll be sure to post full details when It's all finished.

Sounds great! Hope it turns out just like you envision.