Smoke detected, wait X minutes then turn on fan once smoke cleared

I'm working with Node-Red and want it to turn off my fans if smoke is detected to prevent possible spread of fire. What I would like for it to do is that one the status turns to clear, to wait X minutes and see if it's still clear. If so then turn on the fan to clear out smoke. Is there a good way to accomplish this?

Welcome to the forum, you opened 3 topics, with no information about your devices, no example flow etc.

Did you read through the documentation and watched the whole playlist (short videos that cover the essentials) to get an idea on how node-red works and how you could apply in your situation.

I have a very large flow for my WHF (Whole House Fan) and have a few areas I am working on which I need some guidance to. I didn't want to post the complete flow as it's VERY big, but can post the part which I am looking for some guidance to. I was hopeful that the description I posted would provide enough info so that I could view a sample flow as to how to get these 3 different topics to work.
I have reviewed the documentation to a healthy extent, and am just having a few what I thought are minor challenges, but they are kicking me in the rear.

[{"id":"a607dc72.c9d2f","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"d2c9384f.681518","type":"server-state-changed","z":"a607dc72.c9d2f","name":"Guestroom Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":130,"y":180,"wires":[["6c5323dc.27025c","46f215f1.89b04c"]]},{"id":"6c5323dc.27025c","type":"change","z":"a607dc72.c9d2f","name":"topic","rules":[{"t":"set","p":"topic","pt":"msg","to":"guest","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":220,"wires":[["46f215f1.89b04c"]]},{"id":"46f215f1.89b04c","type":"join","z":"a607dc72.c9d2f","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":180,"wires":[["775940bc.796e6"]]},{"id":"775940bc.796e6","type":"function","z":"a607dc72.c9d2f","name":"Check smoke","func":"if (msg.payload.guest == \"13\" && msg.payload.michael == \"13\" && msg.payload.paige == \"13\" && msg.payload.downstairs == \"Ok\" && msg.payload.upstairs == \"Ok\")\n{\n return [msg, null]\n} else \n{    \n  return [null, msg]\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":520,"y":180,"wires":[["e04a77a3.e229c8"],["72a941cc.01d18"]]},{"id":"e04a77a3.e229c8","type":"debug","z":"a607dc72.c9d2f","name":"once smoke is clear, wait 5 minutes then check HVAC status","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":890,"y":140,"wires":[]},{"id":"72a941cc.01d18","type":"api-current-state","z":"a607dc72.c9d2f","name":"Upstairs HVAC","server":"2ee084e7.d905bc","version":1,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"climate.upstairs_hallway","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":740,"y":200,"wires":[[],[]]},{"id":"2ee084e7.d905bc","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

So I've made some progress, but feel like I'm missing something. Basically on first run it will not start after the trigger till 5mins has come up. I'd like to have it so that on first run it will do everything after the trigger, unless it senses smoke, then for it to stop. If it does sense smoke, wait 5 minutes till the smoke has cleared.

Here's the code I am using

[{"id":"64275f30.98b31","type":"tab","label":"Flow 4","disabled":false,"info":""},{"id":"5049a919.6b81a8","type":"inject","z":"64275f30.98b31","name":"Guest Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"guest","payload":"13","payloadType":"num","x":100,"y":220,"wires":[["1a31e66e.5066fa"]]},{"id":"7ccd155b.37cc3c","type":"inject","z":"64275f30.98b31","name":"Guest Smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"guest","payload":"1","payloadType":"num","x":110,"y":260,"wires":[["1a31e66e.5066fa"]]},{"id":"1a31e66e.5066fa","type":"function","z":"64275f30.98b31","name":"Smoke compare","func":"context.data = context.data || {};\nswitch (msg.topic) {\n    case \"guest\": \n        context.data.guest = msg.payload;\n        break;\n    case \"office\":\n        context.data.office = msg.payload;\n        break;    \n    case \"hall\": \n        context.data.hall = msg.payload;\n        break;  \n    default:\n        msg = null;\n        break;\n}    \nmsg.topic = \"smoke\";\nif (context.data.guest == 13 && context.data.office == 13 && context.data.hall == \"Ok\")\n{\n    msg.payload = \"on\";\n    return [msg, null]\n}\nelse\n{\n    msg.payload = \"off\";\n    return [null, msg]\n}\nreturn msg;\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":480,"y":400,"wires":[["ae6d2f91.75728"],["54f46bc1.fcfc04"]]},{"id":"ae6d2f91.75728","type":"trigger","z":"64275f30.98b31","name":"","op1":"wait","op2":"on","op1type":"str","op2type":"str","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"off","bytopic":"all","topic":"topic","outputs":1,"x":640,"y":380,"wires":[["54f46bc1.fcfc04"]]},{"id":"54f46bc1.fcfc04","type":"function","z":"64275f30.98b31","name":"Compare","func":"var runonce = runonce;\nif (runonce == \"null\")\n{\n    opencount = 0;\n    msg.payload = 'on';\n    runonce = 1;\n}\nif (msg.payload == 'on')\n{\n    return [msg, null]\n}\nelse if (msg.payload == 'wait')\n{\n    return [msg, null]\n}\nelse if (msg.payload == 'off')\n{\n    return [null, msg]\n}\nreturn msg;","outputs":2,"noerr":0,"initialize":"","finalize":"","x":640,"y":440,"wires":[["b7e21e4.c2b3ae","6e47d13e.5844d","a7d15c3a.473"],["74337857.fe07e8","a7d15c3a.473"]]},{"id":"b7e21e4.c2b3ae","type":"api-current-state","z":"64275f30.98b31","name":"Upstairs HVAC","server":"2ee084e7.d905bc","version":1,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"climate.upstairs_hallway","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":840,"y":320,"wires":[[],[]]},{"id":"74337857.fe07e8","type":"debug","z":"64275f30.98b31","name":"Stop fan","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":810,"y":500,"wires":[]},{"id":"3a951fa1.3b54c","type":"inject","z":"64275f30.98b31","name":"Office Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"office","payload":"13","payloadType":"num","x":100,"y":400,"wires":[["1a31e66e.5066fa"]]},{"id":"dec145e8.6ded38","type":"inject","z":"64275f30.98b31","name":"Office smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"office","payload":"1","payloadType":"num","x":110,"y":440,"wires":[["1a31e66e.5066fa"]]},{"id":"f8ec7639.77d058","type":"inject","z":"64275f30.98b31","name":"Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hall","payload":"Ok","payloadType":"str","x":90,"y":540,"wires":[["1a31e66e.5066fa"]]},{"id":"9d711977.1b01f8","type":"inject","z":"64275f30.98b31","name":"Warning","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hall","payload":"Warning","payloadType":"str","x":100,"y":580,"wires":[["1a31e66e.5066fa"]]},{"id":"6e47d13e.5844d","type":"debug","z":"64275f30.98b31","name":"Continue","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":810,"y":380,"wires":[]},{"id":"22986f14.a7bd1","type":"server-state-changed","z":"64275f30.98b31","name":"Guestroom Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":110,"y":180,"wires":[["ac834b66.49e568"]]},{"id":"ac834b66.49e568","type":"change","z":"64275f30.98b31","name":"Guest","rules":[{"t":"set","p":"topic","pt":"msg","to":"guest","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":180,"wires":[["1a31e66e.5066fa"]]},{"id":"ca5f0088.be68b","type":"server-state-changed","z":"64275f30.98b31","name":"office Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.paiges_smoke_and_carbon_monoxide_alarm_alarmtype","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":90,"y":360,"wires":[["cd28e358.1c0ee"]]},{"id":"cd28e358.1c0ee","type":"change","z":"64275f30.98b31","name":"office","rules":[{"t":"set","p":"topic","pt":"msg","to":"office","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":360,"wires":[["1a31e66e.5066fa"]]},{"id":"fd9411f5.ca4f3","type":"server-state-changed","z":"64275f30.98b31","name":"Hall Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.downstairs_hallway_protect_smoke_status","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":90,"y":500,"wires":[["bb9f276.fe776d8"]]},{"id":"bb9f276.fe776d8","type":"change","z":"64275f30.98b31","name":"Hall","rules":[{"t":"set","p":"topic","pt":"msg","to":"hall","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":500,"wires":[["1a31e66e.5066fa"]]},{"id":"a7d15c3a.473","type":"debug","z":"64275f30.98b31","name":"Continue","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":810,"y":440,"wires":[]},{"id":"2ee084e7.d905bc","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Any thoughts so that on first run it doesn't have to wait unless it detects smoke?

In your 'compare' function node you start with:

var runonce = runonce;
if (runonce == "null")
{
    opencount = 0;
    msg.payload = 'on';
    runonce = 1;
}

so you are comparing 'runonce' with a string of null...why?
since the function node starts fresh each time it receives a msg, the if statement will always fail (and you are testing against a string)

[debugging a function node tip: use node.warn("runonce="+ runonce); to see what it contains]

If that doesn't help, what does the output of the server-state-changed node look like? Please put a debug node (set to display the Complete msg object) on it's output and the copy the output
Screen Shot 2021-03-02 at 4.42.42 AM
and paste it into a response.

If I understand right:
You have n sensors with digital output.
If one or more of this outputs goes high (alarm for fire) you will wait 5 minutes and then turn on fan on until all sensors reports ok. If all sensors reports ok during this 5 minutes the fan don´t turn on.
Like this example (I have set Time to 3s not 5min) ?

iiot2k, logic is very close but slightly modified.

What I want it to do is when I first start Node Red - for it to check the digital output (Alarm). If it notices smoke - turn off fan, else turn on fan. Once its initially started running then if it notices smoke to stop (turn off fan). Then wait for 5 minutes once smoke has cleared, then turn on fan (only if no smoke has been detected). Again if smoke is detected turn off, then wait 5 minutes after smoke is cleared.

Do you mind sharing your code?

Its odd as Node.warn doesn't appear to be a command in my node-red. node.status works, but node.warn doesn't appear to be a command.
When it starts, the it still goes off, wait then on.
Here's the message I get though - note I changed the debug to Smoke Combo:

First message

{"topic":"smoke","payload":"off","data":{"entity_id":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","old_state":{"entity_id":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","state":"13","attributes":{"value":13,"friendly_name":"Guest Bedroom Smoke and Carbon Monoxide Alarm: alarmType"},"last_changed":"2021-03-02T16:11:07.107237+00:00","last_updated":"2021-0 3-02T16:11:07.107237+00:00","context":{"id":"b6938d48531591d64fd68a8c23525837","parent_id":null,"user_id":null},"original_state":"13","timeSinceChangedMs":3183120},"new_state":{"entity_id":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","state":"13","attributes":{"value":13,"friendly_name":"Guest Bedroom Smoke and Carbon Monoxide Alarm: alarmType"},"last_changed":"2021-03-02T16:11:07.107237+00:00","last_updated":"2021-03-02T16:11:07.107237+00:00","context":{"id":"b6938d48531591d64fd68a8c23525837","parent_id":null,"user_id":null},"original_state":"13","timeSinceChangedMs":3183120}},"_msgid":"49b9b2a9.89f3bc"}

Second message

{"topic":"smoke","payload":"off","data":{"entity_id":"sensor.paiges_smoke_and_carbon_monoxide_alarm_alarmtype","old_state":{"entity_id":"sensor.paiges_smoke_and_carbon_monoxide_alarm_alarmtype","state":"13","attributes":{"value":13,"friendly_name":"Paige's Smoke and Carbon Monoxide Alarm: alarmType"},"last_changed":"2021-03-02T16:49:05.251355+00:00","last_updated":"2021-03-02T16:49:05.251355+00:00","context":{"id":"4c67315c2d7310825878c3f45c079ddc","parent_id":null,"user_id":null},"original_state":"13","timeSinceChangedMs":905024},"new_state":{"entity_id":"sensor.paiges_smoke_and_carbon_monoxide_alarm_alarmtype","state":"13","attributes":{"value":13,"friendly_name":"Paige's Smoke and Carbon Monoxide Alarm: alarmType"},"last_changed":"2021-03-02T16:49:05.251355+00:00","last_updated":"2021-03-02T16:49:05.251355+00:00","context":{"id":"4c67315c2d7310825878c3f45c079ddc","parent_id":null,"user_id":null},"original_state":"13","timeSinceChangedMs":905024}},"_msgid":"b2697a9c.7e46b8"}

Third Message:

{"topic":"smoke","payload":"wait","data":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","old_state":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","state":"Ok","attributes":{"friendly_name":"Downstairs (Downstairs Hallway) Protect smoke_status"},"last_changed":"2021-03-02T05:55:36.550870+00:00","last_updated":"2021-03-02T05:55:36.550870+00:00","context":{"id":"ca2a1d85c1458f8a9c362dab4202410a","parent_id":null,"user_id":null},"original_state":"Ok","timeSinceChangedMs":40113761},"new_state":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","state":"Ok","attributes":{"friendly_name":"Downstairs (Downstairs Hallway) Protect smoke_status"},"last_changed":"2021-03-02T05:55:36.550870+00:00","last_updated":"2021-03-02T05:55:36.550870+00:00","context":{"id":"ca2a1d85c1458f8a9c362dab4202410a","parent_id":null,"user_id":null},"original_state":"Ok","timeSinceChangedMs":40113761}},"_msgid":"fd74280d.4bc7c8"}

Fourth Message:

{"topic":"smoke","payload":"on","data":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","old_state":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","state":"Ok","attributes":{"friendly_name":"Downstairs (Downstairs Hallway) Protect smoke_status"},"last_changed":"2021-03-02T05:55:36.550870+00:00","last_updated":"2021-03-02T05:55:36.550870+00:00","context":{"id":"ca2a1d85c1458f8a9c362dab4202410a","parent_id":null,"user_id":null},"original_state":"Ok","timeSinceChangedMs":40113761},"new_state":{"entity_id":"sensor.downstairs_hallway_protect_smoke_status","state":"Ok","attributes":{"friendly_name":"Downstairs (Downstairs Hallway) Protect smoke_status"},"last_changed":"2021-03-02T05:55:36.550870+00:00","last_updated":"2021-03-02T05:55:36.550870+00:00","context":{"id":"ca2a1d85c1458f8a9c362dab4202410a","parent_id":null,"user_id":null},"original_state":"Ok","timeSinceChangedMs":40113761}},"_msgid":"fd74280d.4bc7c8"}

This is the ladder logic for fan control:


Rung 01: Or logic all rooms and store in memory M0.0
Rung 02: Memory M0.0 starts OFF Timer T0 on edge from 1 to 0
Rung 03: If not M0.0 and not Timer T0 turn fan on
Timer T0 is set to 10s for test, change to 5minutes.
This ladder diagram works also on a other plc.

[{"id":"aa2756e3.30b8b8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"3b97d5ae.70010a","type":"redplc-cpu","z":"aa2756e3.30b8b8","sdelay":200,"tinput":30,"toutput":30,"trungs":5,"outputs":4,"stime":false,"x":130,"y":260,"wires":[["d53fe1e7.97dd7"],["167a6846.d7dbc8"],["8742c6b1.aff018"],["6a9868cb.38eb78"]]},{"id":"d53fe1e7.97dd7","type":"piface","z":"aa2756e3.30b8b8","devadr":"0","addressdi":0,"addressdo":0,"addressspi":"0","x":330,"y":100,"wires":[[]]},{"id":"aedd3a0c.611438","type":"contact","z":"aa2756e3.30b8b8","operation":"read","operand":"I","address":0,"bit":0,"counter":"QU","timer":"Q","flipflop":"R","name":"Room1","x":450,"y":160,"wires":[["384efcfa.e53e64"]]},{"id":"73e9da3e.e912a4","type":"contact","z":"aa2756e3.30b8b8","operation":"read","operand":"I","address":0,"bit":"1","counter":"QU","timer":"Q","flipflop":"R","name":"Room2","x":450,"y":220,"wires":[["384efcfa.e53e64"]]},{"id":"5d0d6bad.4b0674","type":"contact","z":"aa2756e3.30b8b8","operation":"read","operand":"I","address":0,"bit":"2","counter":"QU","timer":"Q","flipflop":"R","name":"Room3","x":450,"y":280,"wires":[["384efcfa.e53e64"]]},{"id":"71483cd.029e5c4","type":"contact","z":"aa2756e3.30b8b8","operation":"read","operand":"I","address":0,"bit":"3","counter":"QU","timer":"Q","flipflop":"R","name":"Room4","x":450,"y":340,"wires":[["384efcfa.e53e64"]]},{"id":"167a6846.d7dbc8","type":"rung-start","z":"aa2756e3.30b8b8","comment":"","x":275,"y":160,"wires":[["aedd3a0c.611438","73e9da3e.e912a4","5d0d6bad.4b0674","71483cd.029e5c4"]],"l":false},{"id":"b3fa29be.afaa58","type":"coil","z":"aa2756e3.30b8b8","operation":"store","operand":"Q","address":0,"bit":0,"counter":"R","flipflop":"S","name":"Fan","x":690,"y":480,"wires":[[]]},{"id":"20e9964.8836b6a","type":"timer","z":"aa2756e3.30b8b8","operation":"tof","address":0,"td":0,"th":0,"tm":"0","ts":"10","tms":0,"name":"Timer","x":560,"y":420,"wires":[[]]},{"id":"384efcfa.e53e64","type":"coil","z":"aa2756e3.30b8b8","operation":"store","operand":"M","address":0,"bit":0,"counter":"R","flipflop":"S","name":"Alarm","x":650,"y":160,"wires":[[]]},{"id":"6a9868cb.38eb78","type":"rung-start","z":"aa2756e3.30b8b8","comment":"","x":295,"y":480,"wires":[["8c6354f1.b13748"]],"l":false},{"id":"8c6354f1.b13748","type":"contact","z":"aa2756e3.30b8b8","operation":"not","operand":"M","address":0,"bit":0,"counter":"QU","timer":"Q","flipflop":"R","name":"Alarm","x":410,"y":480,"wires":[["2943468b.181dda"]]},{"id":"8742c6b1.aff018","type":"rung-start","z":"aa2756e3.30b8b8","comment":"","x":295,"y":420,"wires":[["4be1071c.6e8828"]],"l":false},{"id":"4be1071c.6e8828","type":"contact","z":"aa2756e3.30b8b8","operation":"read","operand":"M","address":0,"bit":0,"counter":"QU","timer":"Q","flipflop":"R","name":"Alarm","x":410,"y":420,"wires":[["20e9964.8836b6a"]]},{"id":"2943468b.181dda","type":"contact","z":"aa2756e3.30b8b8","operation":"not","operand":"T","address":0,"bit":0,"counter":"QU","timer":"Q","flipflop":"R","name":"Timer","x":550,"y":480,"wires":[["b3fa29be.afaa58"]]}]

This will display the results in the debug log in the editor:


You should use:

if (runounce == undefined)

I moved the node.warn to under var (I had it towards the end.). This time I get
runonce=undefined.
and it never changed value.

So I keep getting off, off, wait, on. I want on the first run.

[{"id":"64275f30.98b31","type":"tab","label":"Flow 4","disabled":false,"info":""},{"id":"5049a919.6b81a8","type":"inject","z":"64275f30.98b31","name":"Guest Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"guest","payload":"13","payloadType":"num","x":100,"y":220,"wires":[["1a31e66e.5066fa"]]},{"id":"7ccd155b.37cc3c","type":"inject","z":"64275f30.98b31","name":"Guest Smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"guest","payload":"1","payloadType":"num","x":110,"y":260,"wires":[["1a31e66e.5066fa"]]},{"id":"1a31e66e.5066fa","type":"function","z":"64275f30.98b31","name":"Smoke compare","func":"context.data = context.data || {};\nswitch (msg.topic) {\n    case \"guest\": \n        context.data.guest = msg.payload;\n        break;\n    case \"office\":\n        context.data.office = msg.payload;\n        break;    \n    case \"hall\": \n        context.data.hall = msg.payload;\n        break;  \n    default:\n        msg = null;\n        break;\n}    \nmsg.topic = \"smoke\";\nif (context.data.guest == 13 && context.data.office == 13 && context.data.hall == \"Ok\")\n{\n    msg.payload = \"on\";\n    return [msg, null]\n}\nelse\n{\n    msg.payload = \"off\";\n    return [null, msg]\n}\nreturn msg;\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":480,"y":400,"wires":[["ae6d2f91.75728"],["54f46bc1.fcfc04"]]},{"id":"ae6d2f91.75728","type":"trigger","z":"64275f30.98b31","name":"","op1":"wait","op2":"on","op1type":"str","op2type":"str","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"off","bytopic":"all","topic":"topic","outputs":1,"x":640,"y":380,"wires":[["54f46bc1.fcfc04"]]},{"id":"54f46bc1.fcfc04","type":"function","z":"64275f30.98b31","name":"Compare","func":"var runonce = runonce;\nnode.warn(\"runonce=\"+ runonce);\nif (runonce == \"null\")\n{\n    opencount = 0;\n    msg.payload = 'on';\n    runonce = 1;\n}\nif (msg.payload == 'on')\n{\n    return [msg, null]\n}\nelse if (msg.payload == 'wait')\n{\n    return [msg, null]\n}\nelse if (msg.payload == 'off')\n{\n    return [null, msg]\n}\nnode.status({fill:\"green\",shape:\"dot\",text:`Runonce: ${runonce}`})\nreturn msg;","outputs":2,"noerr":0,"initialize":"","finalize":"","x":640,"y":440,"wires":[["b7e21e4.c2b3ae","6e47d13e.5844d","a7d15c3a.473"],["74337857.fe07e8","a7d15c3a.473"]]},{"id":"b7e21e4.c2b3ae","type":"api-current-state","z":"64275f30.98b31","name":"Upstairs HVAC","server":"2ee084e7.d905bc","version":1,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"climate.upstairs_hallway","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":820,"y":300,"wires":[[],[]]},{"id":"74337857.fe07e8","type":"debug","z":"64275f30.98b31","name":"Smoke Off","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":810,"y":500,"wires":[]},{"id":"3a951fa1.3b54c","type":"inject","z":"64275f30.98b31","name":"Office Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"office","payload":"13","payloadType":"num","x":100,"y":400,"wires":[["1a31e66e.5066fa"]]},{"id":"dec145e8.6ded38","type":"inject","z":"64275f30.98b31","name":"Office smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"office","payload":"1","payloadType":"num","x":110,"y":440,"wires":[["1a31e66e.5066fa"]]},{"id":"f8ec7639.77d058","type":"inject","z":"64275f30.98b31","name":"Ok","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hall","payload":"Ok","payloadType":"str","x":90,"y":540,"wires":[["1a31e66e.5066fa"]]},{"id":"9d711977.1b01f8","type":"inject","z":"64275f30.98b31","name":"Warning","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hall","payload":"Warning","payloadType":"str","x":100,"y":580,"wires":[["1a31e66e.5066fa"]]},{"id":"6e47d13e.5844d","type":"debug","z":"64275f30.98b31","name":"Smoke On","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":810,"y":380,"wires":[]},{"id":"22986f14.a7bd1","type":"server-state-changed","z":"64275f30.98b31","name":"Guestroom Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.guest_bedroom_smoke_and_carbon_monoxide_alarm_alarmtype","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":110,"y":180,"wires":[["ac834b66.49e568"]]},{"id":"ac834b66.49e568","type":"change","z":"64275f30.98b31","name":"Guest","rules":[{"t":"set","p":"topic","pt":"msg","to":"guest","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":180,"wires":[["1a31e66e.5066fa"]]},{"id":"ca5f0088.be68b","type":"server-state-changed","z":"64275f30.98b31","name":"office Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.paiges_smoke_and_carbon_monoxide_alarm_alarmtype","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":90,"y":360,"wires":[["cd28e358.1c0ee"]]},{"id":"cd28e358.1c0ee","type":"change","z":"64275f30.98b31","name":"office","rules":[{"t":"set","p":"topic","pt":"msg","to":"office","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":360,"wires":[["1a31e66e.5066fa"]]},{"id":"fd9411f5.ca4f3","type":"server-state-changed","z":"64275f30.98b31","name":"Hall Smoke","server":"2ee084e7.d905bc","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.downstairs_hallway_protect_smoke_status","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":90,"y":500,"wires":[["bb9f276.fe776d8"]]},{"id":"bb9f276.fe776d8","type":"change","z":"64275f30.98b31","name":"Hall","rules":[{"t":"set","p":"topic","pt":"msg","to":"hall","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":500,"wires":[["1a31e66e.5066fa"]]},{"id":"a7d15c3a.473","type":"debug","z":"64275f30.98b31","name":"Smoke Combo","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":830,"y":440,"wires":[]},{"id":"2ee084e7.d905bc","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

It looks like you are using this flow: node-red-contrib-redplc (node) - Node-RED?
I'll have to read up about this - I see you can do and/or with it so this could help me out. Thanks for sending this over.

Yes, these are the redPlc nodes. For hardware I/O on Raspberry PI I use piFace module. I notice, that Node-Red user don´t like ladder logic. It is an other logic. You must think in loops. But this is standard on programable logic controller (plc). Millions of plc around the world use this logic. On youtube are lot of videos that explain ladder logic. You can use this example and program a Siemens, Allen-Bradley or other plc without changes.

Remember, when a function node runs, it starts fresh. Your first line
var runonce = runonce;
is defining a variable and setting it to a variable that has never been defined - which is why it shows as undefined.

You then have an 'if' statement
if (runonce == "null")
where you are comparing 'runonce' (which is undefined) to the string "null" - it will never equal a string bcause it is undefined.

From the looks of it, you are a beginner with JavaScript and you would gain alot by taking a tutorial like this one

@zenofmud,
Appreciate all of your help. In further looking at the tutorial (and your commends), I'm still having a hard time understanding how I can create the flow to operate the way I'm visualizing it. I now fully understand that when the function node runs, it starts fresh and the pictures you sent make perfect sense now (I had to do it a few times to realize this). To your knowledge, is there a way to accomplish what I am trying to do (possibly outside of a function)?

Basically when it first starts I want it to perform the below - but only perform this once.

if (msg.payload == 'on' || msg.payload == 'wait')
{
    msg.payload = 'on';
    return [msg, null]
}
if (msg.payload == 'off')
{
   msg.payload = 'off';
   return [null, msg]
}

then the next anytime the msg.payload changes I want it to run

if (msg.payload == 'on')
{
    msg.payload = 'on';
    return [msg, null]
}
if (msg.payload == 'wait')
{
    msg.payload = 'off';
    return [null, msg]
}
if (msg.payload == 'off')
{
    msg.payload = 'off';
    return [null, msg]
}

This way if smoke is ever detected it will turn the system off.
But, the first time I start the flow, if there is no smoke it turns the system on or if smoke is detected, it turns the system off. If smoke was detected, it waits five minutes before trying to turn it back on.

I'm thinking the ladder logic @iiot2k makes the most sense for what I am trying to accomplish - but I haven't read up on how it works yet, and feel there has to be a simple way to do what I am thinking.

I use to use webcore and am porting over to node-red. Some am learning a lot while I do this.

You can do anything and it doesn't have to be in a function node, but you will have more nodes in your flow. It all depends on what you are comfortable with. You have three IF statements so you might need three switch nodes followed by some change nodes.

Just take baby steps, after all you couldn't do algebra whn you were in first grade...right?

I made a little progress, but am notice it's constantly running versus running on new input.

[{"id":"65a22b1f.4bb5d4","type":"tab","label":"Flow 8","disabled":false,"info":""},{"id":"e1a45eb6.67c15","type":"inject","z":"65a22b1f.4bb5d4","name":"on - smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"smoke","payload":"on","payloadType":"str","x":150,"y":120,"wires":[["8566892f.ece808","6bc6d515.e5941c"]]},{"id":"bef9d9fa.fd4d58","type":"inject","z":"65a22b1f.4bb5d4","name":"off - smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"smoke","payload":"off","payloadType":"str","x":150,"y":180,"wires":[["8566892f.ece808","6bc6d515.e5941c"]]},{"id":"640881d4.187a9","type":"change","z":"65a22b1f.4bb5d4","name":"","rules":[{"t":"change","p":"topic","pt":"msg","from":"","fromt":"str","to":"","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":340,"wires":[["8d1d0268.0fa57"]]},{"id":"8566892f.ece808","type":"trigger","z":"65a22b1f.4bb5d4","name":"","op1":"wait","op2":"on","op1type":"str","op2type":"str","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"off","bytopic":"all","topic":"topic","outputs":1,"x":380,"y":120,"wires":[["6bc6d515.e5941c"]]},{"id":"6bc6d515.e5941c","type":"function","z":"65a22b1f.4bb5d4","name":"Compare","func":"context.data = context.data || {};\nswitch (msg.topic) {\n    case \"runonce\": \n        context.data.runonce = msg.payload;\n        break;\n    case \"smoke\": \n        context.data.smoke = msg.payload;\n        break;\n    default:\n        msg = null;\n        break;\n}\nvar runonce = context.data.runonce;\nvar smoke = context.data.smoke;\n\nnode.warn(\"runonce=\"+ runonce);\n\nif (runonce == undefined)\n{\n    if (smoke == 'on')\n    {\n       msg.payload = 'on';\n       return [msg, null]\n    }\n    if (smoke == 'wait')\n    {\n       msg.payload = 'on';\n       return [msg, null]\n    }\n\n    if (smoke == 'off')\n    {\n       msg.payload = 'off';\n       return [null, msg]\n    }\n}\nif (runonce == 1)\n{\n    if (smoke == 'on')\n    {\n        msg.payload = 'on';\n        return [msg, null]\n    }\n    if (smoke == 'wait')\n    {\n        msg.payload = 'off';\n        return [null, msg]\n    }\n    if (smoke == 'off')\n    {\n        msg.payload = 'off';\n        return [null, msg]\n    }\n}\nnode.status({fill:\"green\",shape:\"dot\",text:`VAR: ${context.data.runonce}, Payload: ${msg.payload}`})\n//return msg;","outputs":2,"noerr":0,"initialize":"","finalize":"","x":380,"y":180,"wires":[["10650cf9.71ab43","640881d4.187a9"],["10650cf9.71ab43","640881d4.187a9"]]},{"id":"10650cf9.71ab43","type":"debug","z":"65a22b1f.4bb5d4","name":"","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":600,"y":180,"wires":[]},{"id":"8d1d0268.0fa57","type":"delay","z":"65a22b1f.4bb5d4","name":"1min","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":255,"y":240,"wires":[["6bc6d515.e5941c"]],"l":false}]

Here's one more attempt using inject, and having it inject runonce after a set time - and only injecting once.

[{"id":"65a22b1f.4bb5d4","type":"tab","label":"Flow 8","disabled":false,"info":""},{"id":"e1a45eb6.67c15","type":"inject","z":"65a22b1f.4bb5d4","name":"on - smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"smoke","payload":"on","payloadType":"str","x":150,"y":120,"wires":[["8566892f.ece808","6bc6d515.e5941c"]]},{"id":"bef9d9fa.fd4d58","type":"inject","z":"65a22b1f.4bb5d4","name":"off - smoke","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"smoke","payload":"off","payloadType":"str","x":150,"y":180,"wires":[["8566892f.ece808","6bc6d515.e5941c"]]},{"id":"8566892f.ece808","type":"trigger","z":"65a22b1f.4bb5d4","name":"","op1":"wait","op2":"on","op1type":"str","op2type":"str","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"off","bytopic":"all","topic":"topic","outputs":1,"x":380,"y":120,"wires":[["6bc6d515.e5941c"]]},{"id":"6bc6d515.e5941c","type":"function","z":"65a22b1f.4bb5d4","name":"Compare","func":"context.data = context.data || {};\nswitch (msg.topic) {\n    case \"runonce\": \n        context.data.runonce = msg.payload;\n        break;\n    case \"smoke\": \n        context.data.smoke = msg.payload;\n        break;\n    default:\n        msg = null;\n        break;\n}\nvar runonce = context.data.runonce;\nvar smoke = context.data.smoke;\n\nnode.warn(\"runonce=\"+ runonce);\n\nif (runonce == undefined)\n{\n    if (smoke == 'on')\n    {\n       msg.payload = 'on';\n       return [msg, null]\n    }\n    if (smoke == 'wait')\n    {\n       msg.payload = 'on';\n       return [msg, null]\n    }\n\n    if (smoke == 'off')\n    {\n       msg.payload = 'off';\n       return [null, msg]\n    }\n}\nif (runonce == 1)\n{\n    if (smoke == 'on')\n    {\n        msg.payload = 'on';\n        return [msg, null]\n    }\n    if (smoke == 'wait')\n    {\n        msg.payload = 'off';\n        return [null, msg]\n    }\n    if (smoke == 'off')\n    {\n        msg.payload = 'off';\n        return [null, msg]\n    }\n}\nnode.status({fill:\"green\",shape:\"dot\",text:`VAR: ${context.data.runonce}, Payload: ${msg.payload}`})\n//return msg;","outputs":2,"noerr":0,"initialize":"","finalize":"","x":380,"y":180,"wires":[["10650cf9.71ab43"],["10650cf9.71ab43"]]},{"id":"10650cf9.71ab43","type":"debug","z":"65a22b1f.4bb5d4","name":"","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":600,"y":180,"wires":[]},{"id":"7ed40a42.031434","type":"inject","z":"65a22b1f.4bb5d4","name":"runonce","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"10","topic":"runonce","payload":"1","payloadType":"num","x":140,"y":60,"wires":[["6bc6d515.e5941c"]]}]

Baby steps, but not certain if this is a good way or not.

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