One thing I've always thought missing in core Node-RED is a gate node.
A block that can be switched off or on to prevent or pass messages, controlled simply in the editor, without having to re-deploy.
I tried a few solutions previously but when Blocky arrived in Node-RED, I thought - this would make a good project to try out - and here is result.
Cheerlights MQTT and timestamp nodes are just for testing.
If the Gate node receives a true message on topic gate, its sets itself to pass messages, false sets it to block messages.
gate:toggle just switches the state from true->false or false ->true
The gate:init just simply sends an "init" string to trigger the node into displaying its status (Needed when you re-deploy to regenerate the status text - this won't be needed if/when Node-RED is enhanced to provide a system deploy start message)
Any messages on topic gate are not passed through.
Minimally, you need just a gate:toggle inject node but this is my normally used configuration
[{"id":"a80a47ce.814a98","type":"inject","z":"ed0f5786.2ba6d8","name":"","topic":"gate","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":240,"wires":[["c57c2c6e.d7efa"]]},{"id":"bbcbdea4.7395c","type":"inject","z":"ed0f5786.2ba6d8","name":"","topic":"gate","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":280,"wires":[["c57c2c6e.d7efa"]]},{"id":"94c4d029.581f1","type":"inject","z":"ed0f5786.2ba6d8","name":"","topic":"gate","payload":"toggle","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":200,"wires":[["c57c2c6e.d7efa"]]},{"id":"1b21a7e9.ed9108","type":"inject","z":"ed0f5786.2ba6d8","name":"","topic":"gate","payload":"init","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":420,"y":160,"wires":[["c57c2c6e.d7efa"]]},{"id":"c57c2c6e.d7efa","type":"Blockly","z":"ed0f5786.2ba6d8","language":"en","func":"var gateMsg;\n\n/**\n * Describe this function...\n */\nfunction setStatus() {\n if (!(context.get('gate'))) {\n node.status({fill:\"red\", shape:\"dot\", text:'closed'});\n } else {\n node.status({fill:\"green\", shape:\"dot\", text:'open'});\n }\n}\n\n\nif ((context.get('gate')) != false) {\n context.set('gate', true);\n}\nif ((msg['topic']) == 'gate') {\n gateMsg = (msg['payload']);\n if (gateMsg == true) {\n context.set('gate', true);\n } else if (gateMsg == false) {\n context.set('gate', false);\n } else if (gateMsg == 'toggle') {\n context.set('gate', (!(context.get('gate'))));\n }\n setStatus();\n} else {\n if (context.get('gate')) {\n return msg;\n } else {\n setStatus();\n }\n}\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"d`=BUYN]|[8b:+QnCvIG\">gateMsg</variable></variables><block type=\"controls_if\" id=\"32ef6ggKH_Uy4XVr)t*H\" x=\"-187\" y=\"-188\"><value name=\"IF0\"><block type=\"logic_compare\" id=\"h:L;a-RTj5*WigvnV-[Y\"><field name=\"OP\">NEQ</field><value name=\"A\"><block type=\"node_object_get\" id=\"18/sklXD`tpFg7QX;*Ve\"><value name=\"object\"><shadow type=\"node_msg\" id=\"~Hd~wjelxUU}%v21r0Qu\"></shadow><block type=\"node_context_memory\" id=\"iGV|Xlw_^:`Tf8vQ3+E*\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"gDB@4aU?`X@P{(UFL(:R\"><field name=\"TEXT\">gate</field></shadow></value></block></value><value name=\"B\"><block type=\"logic_boolean\" id=\"d1_Qw[79U.(S{~He%*|#\"><field name=\"BOOL\">FALSE</field></block></value></block></value><statement name=\"DO0\"><block type=\"node_object_set\" id=\"{iGS)N)j0I.p6n]?EH{4\" inline=\"false\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"5}39@%9{W{rR9xY(iV0V\"></shadow><block type=\"node_context_memory\" id=\"-l0cj0`~k$HnFTESKV8^\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"yTSAkB!(^QJGRPW[dUXn\"><field name=\"TEXT\">gate</field></shadow></value><value name=\"value_field\"><shadow type=\"logic_null\" id=\",mjKFv0Dg^RS4Cy?XC6i\"></shadow><block type=\"logic_boolean\" id=\"!(S$f7!}#.a6vQRNN0DQ\"><field name=\"BOOL\">TRUE</field></block></value></block></statement><next><block type=\"controls_if\" id=\"~.:itwduZrf}*w;n$t*j\"><mutation else=\"1\"></mutation><value name=\"IF0\"><block type=\"logic_compare\" id=\"Cj]G08l?x*%LwLmtY!(A\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"node_object_get\" id=\"7~/[1#LEPey[JA+V7yzS\"><value name=\"object\"><shadow type=\"node_msg\" id=\"#1_AsUcJPPBeoeG_GWG2\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"!;pa;Awt6D`3}sf8dts$\"><field name=\"TEXT\">topic</field></shadow></value></block></value><value name=\"B\"><block type=\"text\" id=\"Dm-Uq,Num{~zgpw,TJUP\"><field name=\"TEXT\">gate</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\"2V%]c!T?_v{u8W_xl;9C\"><field name=\"VAR\" id=\"d`=BUYN]|[8b:+QnCvIG\" variabletype=\"\">gateMsg</field><value name=\"VALUE\"><block type=\"node_object_get\" id=\"SIC_2OBlHzAT=+}Q#|Um\"><value name=\"object\"><shadow type=\"node_msg\" id=\"AD)GyD|pWT,|_c+`4^VC\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"]D~MMG!kBUXy70n+y1yv\"><field name=\"TEXT\">payload</field></shadow></value></block></value><next><block type=\"controls_if\" id=\";n,9rOKYpJ2{N#5}gm7}\"><mutation elseif=\"2\"></mutation><value name=\"IF0\"><block type=\"logic_compare\" id=\"RwGh;o}ui:a|bU.@kLDv\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"variables_get\" id=\"MYUJV@Lrv]^B7%081]h?\"><field name=\"VAR\" id=\"d`=BUYN]|[8b:+QnCvIG\" variabletype=\"\">gateMsg</field></block></value><value name=\"B\"><block type=\"logic_boolean\" id=\"Y@gBFVD/A^{%us[ioT)w\"><field name=\"BOOL\">TRUE</field></block></value></block></value><statement name=\"DO0\"><block type=\"node_object_set\" id=\"kWe7w$xw).]09[lNrXHo\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"5}39@%9{W{rR9xY(iV0V\"></shadow><block type=\"node_context_memory\" id=\"5M#~GLEo)3t6GhP8:L]_\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"WQE.)c`vN#x]E|R(*gk6\"><field name=\"TEXT\">gate</field></shadow></value><value name=\"value_field\"><shadow type=\"logic_null\" id=\",mjKFv0Dg^RS4Cy?XC6i\"></shadow><block type=\"logic_boolean\" id=\"cXS9gB~);.R^}~@mWG9W\"><field name=\"BOOL\">TRUE</field></block></value></block></statement><value name=\"IF1\"><block type=\"logic_compare\" id=\"S.Gf0wI`3NL*U_,_YWa2\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"variables_get\" id=\"M4c2sC$`%I?H%7=N+QNZ\"><field name=\"VAR\" id=\"d`=BUYN]|[8b:+QnCvIG\" variabletype=\"\">gateMsg</field></block></value><value name=\"B\"><block type=\"logic_boolean\" id=\"6tYNZlkiu8)ABulMbey(\"><field name=\"BOOL\">FALSE</field></block></value></block></value><statement name=\"DO1\"><block type=\"node_object_set\" id=\"I=b:?92]h3*s8U#7ahR~\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"5}39@%9{W{rR9xY(iV0V\"></shadow><block type=\"node_context_memory\" id=\".bD:_3An(+heBObs^kvw\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"K4lQYjhe#5:|!aF#xk}c\"><field name=\"TEXT\">gate</field></shadow></value><value name=\"value_field\"><shadow type=\"logic_null\" id=\",mjKFv0Dg^RS4Cy?XC6i\"></shadow><block type=\"logic_boolean\" id=\"3UyGiv9b1#wIH_R,MUQ5\"><field name=\"BOOL\">FALSE</field></block></value></block></statement><value name=\"IF2\"><block type=\"logic_compare\" id=\"z]}#wU$HhS~7Tx}(xcb|\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"variables_get\" id=\"vLs`dSDZt%X_@O,C}dju\"><field name=\"VAR\" id=\"d`=BUYN]|[8b:+QnCvIG\" variabletype=\"\">gateMsg</field></block></value><value name=\"B\"><block type=\"text\" id=\"6jA}zPbnzdWEW*w3_x1M\"><field name=\"TEXT\">toggle</field></block></value></block></value><statement name=\"DO2\"><block type=\"node_object_set\" id=\"!SAaPGR=NM^zEr`p:E+[\" inline=\"false\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"5}39@%9{W{rR9xY(iV0V\"></shadow><block type=\"node_context_memory\" id=\"v,Y^I6%=Y/bVfZrs0Kaf\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"?YDPewBU84,%ZWrk|pFU\"><field name=\"TEXT\">gate</field></shadow></value><value name=\"value_field\"><shadow type=\"logic_null\" id=\",mjKFv0Dg^RS4Cy?XC6i\"></shadow><block type=\"logic_negate\" id=\"OoJEu+)0QV$T7[=W$Uo9\"><value name=\"BOOL\"><block type=\"node_object_get\" id=\"|M^$@Rs3oJ]}IfZMx!o8\"><value name=\"object\"><shadow type=\"node_msg\" id=\"~Hd~wjelxUU}%v21r0Qu\"></shadow><block type=\"node_context_memory\" id=\")$m/Lsc9`F34E=!qmMCn\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"$J0,]XZbR.8Ao#oX640h\"><field name=\"TEXT\">gate</field></shadow></value></block></value></block></value></block></statement><next><block type=\"procedures_callnoreturn\" id=\"u}lB4+Z7LbP(oibz$5?Z\"><mutation name=\"setStatus\"></mutation></block></next></block></next></block></statement><statement name=\"ELSE\"><block type=\"controls_if\" id=\"s{![6_[TJAu8o%zTPo^W\"><mutation else=\"1\"></mutation><value name=\"IF0\"><block type=\"node_object_get\" id=\",cKR;lB+k6hYi9e-TuVj\"><value name=\"object\"><shadow type=\"node_msg\" id=\"X)d#jye;o4PN@I3X_(u?\"></shadow><block type=\"node_context_memory\" id=\"ZDT?I{L3,GFla?p@ch6y\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"?aCsZ(tpX3tf~@0~A?f_\"><field name=\"TEXT\">gate</field></shadow></value></block></value><statement name=\"DO0\"><block type=\"node_return_message\" id=\"Dug-9(Hm8D}{Xz*$-F+$\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"P{XZf5BwBz7JJN}%WyEF\"></shadow></value></block></statement><statement name=\"ELSE\"><block type=\"procedures_callnoreturn\" id=\"MG,Le/TTrMyCoE2m!b;g\"><mutation name=\"setStatus\"></mutation></block></statement></block></statement></block></next></block><block type=\"procedures_defnoreturn\" id=\"VW#k7XZ{CFx+VtbYvavB\" x=\"-163\" y=\"662\"><field name=\"NAME\">setStatus</field><comment pinned=\"false\" h=\"80\" w=\"160\">Describe this function...</comment><statement name=\"STACK\"><block type=\"controls_if\" id=\"l4`[$C%ap^pmsp$7tLc|\"><mutation else=\"1\"></mutation><value name=\"IF0\"><block type=\"logic_negate\" id=\"!s$ngmsL];IK-mbU[X0_\"><value name=\"BOOL\"><block type=\"node_object_get\" id=\"zkUDZ6P)hpPWDemRd:[m\"><value name=\"object\"><shadow type=\"node_msg\" id=\"X)d#jye;o4PN@I3X_(u?\"></shadow><block type=\"node_context_memory\" id=\"muYmwwU4}b7cV~L^qa`W\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"]It@[mD?Gy)qnP]4h5M!\"><field name=\"TEXT\">gate</field></shadow></value></block></value></block></value><statement name=\"DO0\"><block type=\"node_status\" id=\"g|R#AV4vWOU$ok8CV?,q\"><field name=\"COLOUR\">#ff0000</field><field name=\"SHAPE\">DOT</field><value name=\"TEXT_INPUT\"><block type=\"text\" id=\"[@x,-=Y:s/z{^3sFfvF#\"><field name=\"TEXT\">closed</field></block></value></block></statement><statement name=\"ELSE\"><block type=\"node_status\" id=\"repdr,@:$XxBOCYQm+rG\"><field name=\"COLOUR\">#00ff00</field><field name=\"SHAPE\">DOT</field><value name=\"TEXT_INPUT\"><block type=\"text\" id=\"cRrXdQ|PF~MO=u)jo-{l\"><field name=\"TEXT\">open</field></block></value></block></statement></block></statement></block></xml>","outputs":1,"name":"Gate","x":610,"y":120,"wires":[["9c2a9d9c.c3daa"]],"icon":"node-red/alert.png"}]
PS. Here is the generated JS code if you would like to try out the functionality without installing Blocky contrib-node
var gateMsg;
/**
* Describe this function...
*/
function setStatus() {
if (!(context.get('gate'))) {
node.status({fill:"red", shape:"dot", text:'closed'});
} else {
node.status({fill:"green", shape:"dot", text:'open'});
}
}
if ((context.get('gate')) != false) {
context.set('gate', true);
}
if ((msg['topic']) == 'gate') {
gateMsg = (msg['payload']);
if (gateMsg == true) {
context.set('gate', true);
} else if (gateMsg == false) {
context.set('gate', false);
} else if (gateMsg == 'toggle') {
context.set('gate', (!(context.get('gate'))));
}
setStatus();
} else {
if (context.get('gate')) {
return msg;
} else {
setStatus();
}