Advanced Blocker node (version 5)

After a few oops things locally this is now working a lot better and now does do what I wanted.

Scope:

You are getting messages and need to control their passage.

There is the filter node (aka RBE) which does do a good job as is.

But this node allows some control of the filtering of messages.
Maybe not always needed, but it is handy if you do need this functionality.

It can:
pass ALL messages.
Block repeats
Allow ONE message to pass
stop ALL messages.

It also has a default (or maybe better called: start up) mode.
You define that (optional) and a topic for the control messages.

The control messages are:
ALL
BLOCK
ONE
STOP

And - I hope - dynamic topics are supported, so if the messages have different topics: they are treated as different.

Yeah, ok... I hope. Not exactly professional.
Sorry, I am not a programmer.
I know/get that it may not take much effort to test it before releasing the node here.

[{"id":"5a6ca5972b0f9e7b","type":"subflow","name":"Advanced blocker","info":"You need to set the `env` variable `TOPIC` to set the control topic.\nInput values:\n - STOP - basically don't pass ANY message.\n - ALL - pass all messages.\n - BLOCK - block repeats of same message.\n - ONE - pass ONLY the next message to arrive.  (ONE)","category":"","in":[{"x":170,"y":130,"wires":[{"id":"685360a3.c08db8"}]}],"out":[{"x":500,"y":130,"wires":[{"id":"685360a3.c08db8","port":0}]}],"env":[{"name":"TOPIC","type":"str","value":""},{"name":"DEFAULT_MODE","type":"str","value":""}],"meta":{},"color":"#3FADB5","icon":"node-red/function.svg","status":{"x":500,"y":190,"wires":[{"id":"197b01d950cf86b4","port":0}]}},{"id":"685360a3.c08db8","type":"function","z":"5a6ca5972b0f9e7b","name":"My blocker node.  V5","func":"//      The shape property can be: ring or dot.\n//      The fill property can be: red, green, yellow, blue or grey\n\n//      These are the three commands accepted.\nconst all = \"ALL\";          //  Allow all message to pass\nconst block = \"BLOCK\";      //  Block repeat message (of same topic)\nconst one = \"ONE\";          //  Allow ONE message to pass.  (may not be perfect)\nconst stop = \"STOP\";        //  Block ALL message...  ALL!\n//  Get topic\nvar topic = msg.topic;\nif (topic == \"\")\n    topic = \"BLANK\";\nif (msg.topic == undefined)\n    topic = \"BLANK\";\n//  Get new value from message\nvar newval = msg.payload;\n\n//  Used to determine if a message was received to change the mode.\nvar updated_mode = context.get(\"updated_mode\") || 0;\n\n/////////////////////\n//\n//  2022 03 06\n//\n//  Needs work here as the *default* topic is being reset\n//  every time a new message comes through.\n//  Set `updated_mode` to `1` so it won't be called again.\n\n//  See if there is a DEFAULT MODE set.\nif (updated_mode == 0)\n{\n    let default_mode = env.get(\"DEFAULT_MODE\");\n    if (default_mode.length > 0)\n    {\n        //\n        context.set(\"MODE\",default_mode);\n        context.set(\"updated_mode\",1)\n    }\n}\n\n//  Get the topic used to determine which messages are to control the mode.\nlet CTLTopic = env.get(\"TOPIC\");\nif (CTLTopic.length < 1)\n    throw\"You must define a TOPIC for controlling the node\";\n\nif (msg.topic == CTLTopic)\n{\n    //\n    //  Set how node works.\n    //\n\n    if (msg.payload == stop)\n    {\n        node.status({ text: \"Set to stop\" });\n        context.set(\"MODE\",msg.payload);\n    } else if (msg.payload == block)\n    {\n        node.status({ text: \"Set to block\" });\n        context.set(\"MODE\",msg.payload);\n    } else if (msg.payload == all) \n    {\n        node.status({ text: \"Set to allow\" });\n        context.set(\"MODE\",msg.payload);\n    } else if (msg.payload == one) \n    {\n        context.set(\"previousMode\",context.get(\"MODE\"));\n        node.warn(context.get(\"previousMode\"));\n        context.set(\"MODE\",msg.payload);\n    } else      //      Show valid commands.\n    {\n        node.warn(\"For control of the node's mode msg.payload must be `\" + all + \"` `\" + block + \"` or `\" + stop + \"` or `\" + one +\"`\");\n    };\n    return;\n}\n\n//        --  Main code starts here.\n//  Get last stored value from topic\nvar lastval = context.get(topic);\n\n//  Get status from context.\nvar mode = context.get(\"MODE\");\n\n//  =============== STOP\nif (mode == stop)\n{\n    return;\n}\n//  =============== ALL\nelse if (mode == all)\n{\n    node.status({fill:\"blue\",shape:\"dot\",text:\"All\"});\n    context.set(topic, newval);\n    return msg;\n}\n//  =============== BLOCK\nelse if (mode == block)\n{\n    //\n    //  See if the new value is different to the old value.\n    //\n    if (newval != lastval)\n    {\n       context.set(topic, newval);\n       node.status({fill:\"green\",shape:\"dot\",text:\"Passed\"});\n       return msg;\n    }\n    node.status({fill:\"red\",shape:\"dot\",text:\"Blocked\"});\n    return;\n}\n//  =============== ONE\nelse if (mode == one)\n{\n    //\n    //  Allow only 1 message to pass\n    //\n    context.set(topic, newval);\n    context.set(\"MODE\",context.get(\"previousMode\"));\n    node.status({ text: \"Set to \" + context.get(\"previousMode\") });\n    return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":130,"wires":[[]]},{"id":"197b01d950cf86b4","type":"status","z":"5a6ca5972b0f9e7b","name":"","scope":["685360a3.c08db8"],"x":310,"y":190,"wires":[[]]},{"id":"02782cfc2e996f6a","type":"subflow:5a6ca5972b0f9e7b","z":"675e227d.d158b4","name":"","env":[],"x":1070,"y":1870,"wires":[[]]}]