Tuesday, December 19, 2017

The three relay problem


This was a request for help posted in the Node-RED group.


The requirements:

Use Node-RED to control three remote relays via MQTT.
Once the first relay is activated (by sending an ON command via MQTT) it should remain active for 5 minutes. When it turns off the second should start and run for 5 minutes, when it stops the third should start and run 5 min when it stops it should start the first one again and continue looping in such way until an OFF command is triggered.



Proposed Solution:

It was implemented a cycling engine, inside a function node, that "rotates" the desired outputs to the relays. The very first run will command all three relays OFF (without delays). I used a variable in the global context to store the user command to stop the flow. There is an inject node to stop the flow. It will stop immediately after the execution of the ongoing delay (which was configured for 15 seconds to speed up the flow - it should be changed to 5 minutes to comply with the requirements). The way the flow was written facilitates to change the logic if there are any changes in the requirements (more relays or relays being activated in a different sequence, for instance).






Flow:



[{"id":"f98def0.4f2101","type":"function","z":"108c9253.cb4bfe","name":"Cycle","func":"if (msg.firstRun || msg.lastRun) {\n    msg.payload1=\"OFF\"; \n    msg.payload2=\"OFF\"; \n    msg.payload3=\"OFF\";\n    if (msg.firstRun) msg.firstRun=false;\n    \n} else \n    \n\nswitch (msg.cycle) {\n    \n   \n        \n    case 1:\n        msg.payload1=\"ON\"; \n        msg.payload2=\"OFF\"; \n        msg.payload3=\"OFF\";\n        msg.cycle=2;\n        break;\n    case 2:\n        msg.payload1=\"OFF\"; \n        msg.payload2=\"ON\"; \n        msg.payload3=\"OFF\";\n        msg.cycle=3;\n        break;  \n        \n    case 3:\n        msg.payload1=\"OFF\"; \n        msg.payload2=\"OFF\"; \n        msg.payload3=\"ON\";\n        msg.cycle=1;\n        break;\n        \n}\n\n\n   \n    msg1={topic:msg.topic1, payload:msg.payload1};\n    msg2={topic:msg.topic2, payload:msg.payload2};\n    msg3={topic:msg.topic3, payload:msg.payload3}; \n    \n    \n    return [[msg1, msg2, msg3], msg];\n    \n\n\n\n\n\n\n","outputs":"2","noerr":0,"x":544,"y":169.00001430511475,"wires":[["6897db12.4f3d34"],["cb723b20.0ecee8","9019f171.0794a"]]},{"id":"4b6261af.a6b63","type":"function","z":"108c9253.cb4bfe","name":"Initialize","func":"    \n    global.set(\"keepWalking\",true);\n    msg.keepWalking = global.get(\"keepWalking\");\n    \n    msg.cycle = 1;\n    msg.firstRun = true;\n    msg.lastRun = false;\n    msg.topic1 = \"cmnd/kb1/power1\";\n    msg.topic2 = \"cmnd/kb1/power2\";\n    msg.topic3 = \"cmnd/kb1/power3\";\n    \n    msg.payload1 = \"OFF\";\n    msg.payload2 = \"OFF\";\n    msg.payload3 = \"OFF\";\n\nreturn msg;","outputs":1,"noerr":0,"x":379.9999580383301,"y":169.00003814697266,"wires":[["f98def0.4f2101"]]},{"id":"cb723b20.0ecee8","type":"debug","z":"108c9253.cb4bfe","name":"Debug only","active":true,"console":"false","complete":"true","x":744.1001205444336,"y":174.00003051757812,"wires":[]},{"id":"d7233232.fb09b","type":"delay","z":"108c9253.cb4bfe","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":579.1000709533691,"y":308.0000171661377,"wires":[["f98def0.4f2101"]]},{"id":"21c221de.0190de","type":"inject","z":"108c9253.cb4bfe","name":"Switch ON","topic":"","payload":"SON","payloadType":"str","repeat":"","crontab":"","once":false,"x":219.99996185302734,"y":170.00003719329834,"wires":[["4b6261af.a6b63"]]},{"id":"9019f171.0794a","type":"function","z":"108c9253.cb4bfe","name":"Test Stop","func":"// keepWalking: false, lastRun: false=> cycle last time\n// keepWalking: false, lastRun: true => end flow\n\n// keepWalking: true => just return msg\n//\n//\n\nif (!global.get(\"keepWalking\")) {\n    if (!msg.lastRun) {\n        msg.lastRun=true;\n        node.warn(\"Commanding Relays off...\");\n        return msg;\n    } else {\n        node.warn(\"Relays confirmed OFF\");\n        return null;}\n    \n} else {return msg;}\n","outputs":1,"noerr":0,"x":429.0999698638916,"y":308.000018119812,"wires":[["d7233232.fb09b"]]},{"id":"f7ab90b3.cf35f","type":"inject","z":"108c9253.cb4bfe","name":"Switch OFF","topic":"SOFF","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":345.09996795654297,"y":396.00002002716064,"wires":[["78a8b3e0.63e5fc"]]},{"id":"78a8b3e0.63e5fc","type":"function","z":"108c9253.cb4bfe","name":"Command Stop","func":"global.set(\"keepWalking\",false);\nmsg.keepWalking = global.get(\"keepWalking\");\nreturn msg;","outputs":1,"noerr":0,"x":540.0999717712402,"y":397.00002002716064,"wires":[[]]},{"id":"6897db12.4f3d34","type":"mqtt out","z":"108c9253.cb4bfe","name":"","topic":"","qos":"2","retain":"false","broker":"752751ba.451be","x":734.1000061035156,"y":104,"wires":[]},{"id":"752751ba.451be","type":"mqtt-broker","z":"","broker":"broker.mqttdashboard.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]



No comments: