Help with dashboard buttons and `disable` text to be displayed

Folks, I have entered a seldom visited area.

I have buttons on the dashboard and sometimes they need to be disabled.

Sending a message with msg.enable set to false disables the buttons for input/being pressed.

All well and good.

But in my case the text on the button is being wiped.
So I have a blank area on the screen which is not nice visually.

Is there a way I can give it text to be shown (like DISABLED) when it is disabled?

I think the label only disappears if it's set to a message property like {{msg.label}}?

If so, the solution is to always provide msg.label as well as msg.enabled.

[{"id":"6bbf4c48f32c4f9e","type":"ui_button","z":"e85ba206cdb13e7d","name":"","group":"f149abdd741ca58e","order":6,"width":"2","height":"1","passthru":false,"label":"Disable","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"button 2","topicType":"str","x":260,"y":220,"wires":[["45db7059c7b0742d"]]},{"id":"dde43e74b41cfb02","type":"ui_button","z":"e85ba206cdb13e7d","name":"","group":"f149abdd741ca58e","order":6,"width":"2","height":"1","passthru":false,"label":"{{msg.label}}","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"Button pressed","payloadType":"str","topic":"topic","topicType":"msg","x":610,"y":200,"wires":[[]]},{"id":"45db7059c7b0742d","type":"change","z":"e85ba206cdb13e7d","name":"","rules":[{"t":"set","p":"enabled","pt":"msg","to":"false","tot":"bool"},{"t":"set","p":"label","pt":"msg","to":"DISABLED","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":220,"wires":[["dde43e74b41cfb02"]]},{"id":"b1cab71c757723fa","type":"ui_button","z":"e85ba206cdb13e7d","name":"","group":"f149abdd741ca58e","order":6,"width":"2","height":"1","passthru":false,"label":"Enable","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"button 2","payloadType":"str","topic":"topic","topicType":"msg","x":260,"y":180,"wires":[["8d36f4cb2f93c9fd"]]},{"id":"8d36f4cb2f93c9fd","type":"change","z":"e85ba206cdb13e7d","name":"","rules":[{"t":"set","p":"enabled","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"label","pt":"msg","to":"The Button","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":180,"wires":[["dde43e74b41cfb02"]]},{"id":"38ea50d011fbc17a","type":"inject","z":"e85ba206cdb13e7d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":270,"y":140,"wires":[["8d36f4cb2f93c9fd"]]},{"id":"f149abdd741ca58e","type":"ui_group","name":"Demo","tab":"1caa8458.b17814","order":1,"disp":true,"width":"12","collapse":false,"className":"test"},{"id":"1caa8458.b17814","type":"ui_tab","name":"Demo","icon":"dashboard","order":10,"disabled":false,"hidden":false}]
2 Likes

Thanks.

Yeah, I kind of was on that path myself - strangely enough.
Though not with msg.label.

Sorry, I don't want to drag you into this, but as you replied, would you mind looking at this sub-flow I wrote/made and see if it is at least on the way to being useful?

[{"id":"402169a8.8a791","type":"subflow","name":"B Toggle 2","info":"2023 11 23\n==\nRe-write code to allow force reloading of desired state.\n\nToggle output at receipt of message.\nConfigurable output and message to send back to button node.\n(2022 12 16)\n\nIf `msg.payload == 0` (number) the output is forced to the OFF condition.\n\nIf `msg.payload == 1` (number) the output is forced to the ON condition.\n\nIf `msg.payload == \"RELOAD\"` (text) the output is set to what you determined in the\n                             `StartMode` value.\n\nAny other input toggles the output.\n\n## ENV variables:\n```\nStartMode - set start condition (`0` off `1` on).\nOnCLR - the colour when ON condition active.\nOnTXT - the text when ON condition active.\nOffCLR - the colour when OFF condition active.\nOffTXT - the text when OFF conditin active.\nON - payload when ON condition active.\nOFF - payload when OFF condition active.\nCTOPIC - the topic of the output message.\n```\n\nOutputs:\n - 1 $OFF for OFF and $ON for ON.\n - 2 $ON for OFF and $OFF for ON.  (Opposite of 1)\n - 3 to be sent back to button with `msg.colour` to set buttons colour and `msg.txt` for the text to be displayed.\n","category":"","in":[{"x":80,"y":190,"wires":[{"id":"69ae694095adea75"}]}],"out":[{"x":670,"y":180,"wires":[{"id":"5a9848b4303ef8d2","port":0},{"id":"8c41e6c213bcdefe","port":0}]},{"x":670,"y":280,"wires":[{"id":"3a564786d2308bdd","port":0},{"id":"a2ec504194f78107","port":0}]},{"x":670,"y":380,"wires":[{"id":"f14d0daf4ad33691","port":0},{"id":"aff48be4199bcfab","port":0},{"id":"69ae694095adea75","port":1}]}],"env":[{"name":"StartMode","type":"num","value":"","ui":{"label":{"en-US":"Start Mode (0/1) (off/on)"},"type":"input","opts":{"types":["num"]}}},{"name":"OffTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OffCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OnTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OnCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OFF","type":"str","value":""},{"name":"ON","type":"str","value":""},{"name":"CTOPIC","type":"str","value":""}],"meta":{"desc":"Button toggle node with feedback to button"},"color":"#D8BFD8","outputLabels":["Normal output","Inverted output","To button"],"icon":"node-red-dashboard/ui_switch.png","status":{"x":690,"y":510,"wires":[{"id":"4cca89516db73bd2","port":0}]}},{"id":"69ae694095adea75","type":"function","z":"402169a8.8a791","name":"toggle","func":"let a = msg.payload;\nlet msg1 = {};\nlet x = context.get(\"counter\") || 0;\n\nif (msg.enabled != undefined)\n{\n    //      Work to be done here.\n    const en = msg.enabled;\n    if (en == true)\n    {\n        //   ENABLE\n        context.set(\"disabled\",0);\n        a = context.get(\"counter\") || 0;\n    }\n    else\n    if (en == false)\n    {\n        //    DISABLE\n        context.set(\"disabled\",1);\n        msg1.txt = \"disabled\";\n        msg1.colour = env.get(\"OffCLR\");\n        node.status({text:\"DISABLED\"});\n        return [null,msg1];\n    }\n}\n\nif (context.get(\"disabled\") == 1)\n{\n    //  Can't do anything.\n    node.status({text:\"skipped\"});\n    return;\n}\n\nif (a == \"RELOAD\")\n{\n    a = env.get(\"StartMode\");\n}\n\nif (a == 0)\n{\n    context.set(\"counter\",0);\n    msg.payload = 0;\n    node.status({text:\"Force OFF\"});\n    return [msg,null];\n}\nif (a == 1)\n{\n    context.set(\"counter\",1);\n    msg.payload = 1;\n    node.status({ text: \"Force ON\" });\n    return [msg,null];\n}\n\nif (x === 0)\n{\n    msg.payload = 1;\n    node.status({ text: \"ON\" });\n} else\nif (x === 1)\n{\n    msg.payload = 0;\n    node.status({ text: \"OFF\" });\n}\n\nx = (x + 1) % 2;\n\ncontext.set(\"counter\",x);\n\nreturn [msg,null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":190,"wires":[["0db7c2da3958ea2c"],[]],"info":"##  Outputs `1` or `0` for ON/OFF and `msg.colour` to send to button."},{"id":"f14d0daf4ad33691","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"colour","pt":"msg","to":"OffCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OffTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":350,"wires":[[]]},{"id":"aff48be4199bcfab","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"colour","pt":"msg","to":"OnCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OnTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":410,"wires":[[]]},{"id":"0db7c2da3958ea2c","type":"switch","z":"402169a8.8a791","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":350,"y":190,"wires":[["5a9848b4303ef8d2","3a564786d2308bdd","f14d0daf4ad33691"],["8c41e6c213bcdefe","a2ec504194f78107","aff48be4199bcfab"]]},{"id":"5a9848b4303ef8d2","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":160,"wires":[[]]},{"id":"8c41e6c213bcdefe","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":210,"wires":[[]]},{"id":"a2ec504194f78107","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":300,"wires":[[]]},{"id":"3a564786d2308bdd","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":250,"wires":[[]]},{"id":"a035346e85f036ba","type":"inject","z":"402169a8.8a791","name":"Start Mode","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.2","topic":"","payload":"StartMode","payloadType":"env","x":130,"y":140,"wires":[["69ae694095adea75"]]},{"id":"4cca89516db73bd2","type":"status","z":"402169a8.8a791","name":"","scope":["69ae694095adea75"],"x":370,"y":510,"wires":[[]]},{"id":"a830a46179143049","type":"subflow:402169a8.8a791","z":"1283f6a97005461c","name":"","x":440,"y":510,"wires":[[],[],[]]}]

No foreign nodes.

Oh, just so establish what/how it is used a basic flow.
No dashboard nodes.

[{"id":"402169a8.8a791","type":"subflow","name":"B Toggle 2","info":"2023 11 23\n==\nRe-write code to allow force reloading of desired state.\n\nToggle output at receipt of message.\nConfigurable output and message to send back to button node.\n(2022 12 16)\n\nIf `msg.payload == 0` (number) the output is forced to the OFF condition.\n\nIf `msg.payload == 1` (number) the output is forced to the ON condition.\n\nIf `msg.payload == \"RELOAD\"` (text) the output is set to what you determined in the\n                             `StartMode` value.\n\nAny other input toggles the output.\n\n## ENV variables:\n```\nStartMode - set start condition (`0` off `1` on).\nOnCLR - the colour when ON condition active.\nOnTXT - the text when ON condition active.\nOffCLR - the colour when OFF condition active.\nOffTXT - the text when OFF conditin active.\nON - payload when ON condition active.\nOFF - payload when OFF condition active.\nCTOPIC - the topic of the output message.\n```\n\nOutputs:\n - 1 $OFF for OFF and $ON for ON.\n - 2 $ON for OFF and $OFF for ON.  (Opposite of 1)\n - 3 to be sent back to button with `msg.colour` to set buttons colour and `msg.txt` for the text to be displayed.\n","category":"","in":[{"x":80,"y":190,"wires":[{"id":"69ae694095adea75"}]}],"out":[{"x":670,"y":180,"wires":[{"id":"5a9848b4303ef8d2","port":0},{"id":"8c41e6c213bcdefe","port":0}]},{"x":670,"y":280,"wires":[{"id":"3a564786d2308bdd","port":0},{"id":"a2ec504194f78107","port":0}]},{"x":670,"y":380,"wires":[{"id":"f14d0daf4ad33691","port":0},{"id":"aff48be4199bcfab","port":0},{"id":"69ae694095adea75","port":1}]}],"env":[{"name":"StartMode","type":"num","value":"","ui":{"label":{"en-US":"Start Mode (0/1) (off/on)"},"type":"input","opts":{"types":["num"]}}},{"name":"OffTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OffCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OnTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OnCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OFF","type":"str","value":""},{"name":"ON","type":"str","value":""},{"name":"CTOPIC","type":"str","value":""}],"meta":{"desc":"Button toggle node with feedback to button"},"color":"#D8BFD8","outputLabels":["Normal output","Inverted output","To button"],"icon":"node-red-dashboard/ui_switch.png","status":{"x":690,"y":510,"wires":[{"id":"4cca89516db73bd2","port":0}]}},{"id":"69ae694095adea75","type":"function","z":"402169a8.8a791","name":"toggle","func":"let a = msg.payload;\nlet msg1 = {};\nlet x = context.get(\"counter\") || 0;\n\nif (msg.enabled != undefined)\n{\n    //      Work to be done here.\n    const en = msg.enabled;\n    if (en == true)\n    {\n        //   ENABLE\n        context.set(\"disabled\",0);\n        a = context.get(\"counter\") || 0;\n    }\n    else\n    if (en == false)\n    {\n        //    DISABLE\n        context.set(\"disabled\",1);\n        msg1.txt = \"disabled\";\n        msg1.colour = env.get(\"OffCLR\");\n        node.status({text:\"DISABLED\"});\n        return [null,msg1];\n    }\n}\n\nif (context.get(\"disabled\") == 1)\n{\n    //  Can't do anything.\n    node.status({text:\"skipped\"});\n    return;\n}\n\nif (a == \"RELOAD\")\n{\n    a = env.get(\"StartMode\");\n}\n\nif (a == 0)\n{\n    context.set(\"counter\",0);\n    msg.payload = 0;\n    node.status({text:\"Force OFF\"});\n    return [msg,null];\n}\nif (a == 1)\n{\n    context.set(\"counter\",1);\n    msg.payload = 1;\n    node.status({ text: \"Force ON\" });\n    return [msg,null];\n}\n\nif (x === 0)\n{\n    msg.payload = 1;\n    node.status({ text: \"ON\" });\n} else\nif (x === 1)\n{\n    msg.payload = 0;\n    node.status({ text: \"OFF\" });\n}\n\nx = (x + 1) % 2;\n\ncontext.set(\"counter\",x);\n\nreturn [msg,null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":190,"wires":[["0db7c2da3958ea2c"],[]],"info":"##  Outputs `1` or `0` for ON/OFF and `msg.colour` to send to button."},{"id":"f14d0daf4ad33691","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"colour","pt":"msg","to":"OffCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OffTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":350,"wires":[[]]},{"id":"aff48be4199bcfab","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"colour","pt":"msg","to":"OnCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OnTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":410,"wires":[[]]},{"id":"0db7c2da3958ea2c","type":"switch","z":"402169a8.8a791","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":350,"y":190,"wires":[["5a9848b4303ef8d2","3a564786d2308bdd","f14d0daf4ad33691"],["8c41e6c213bcdefe","a2ec504194f78107","aff48be4199bcfab"]]},{"id":"5a9848b4303ef8d2","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":160,"wires":[[]]},{"id":"8c41e6c213bcdefe","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":210,"wires":[[]]},{"id":"a2ec504194f78107","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":300,"wires":[[]]},{"id":"3a564786d2308bdd","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":250,"wires":[[]]},{"id":"a035346e85f036ba","type":"inject","z":"402169a8.8a791","name":"Start Mode","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.2","topic":"","payload":"StartMode","payloadType":"env","x":130,"y":140,"wires":[["69ae694095adea75"]]},{"id":"4cca89516db73bd2","type":"status","z":"402169a8.8a791","name":"","scope":["69ae694095adea75"],"x":370,"y":510,"wires":[[]]},{"id":"5077b4ba298d5790","type":"subflow:402169a8.8a791","z":"fe5670ff.ea94e","name":"","env":[{"name":"StartMode","value":"1","type":"num"},{"name":"OffTXT","value":"OFF","type":"str"},{"name":"OffCLR","value":"red","type":"str"},{"name":"OnTXT","value":"ON","type":"str"},{"name":"OnCLR","value":"green","type":"str"},{"name":"OFF","value":"off command","type":"str"},{"name":"ON","value":"on command","type":"str"},{"name":"CTOPIC","value":"ctl_topic","type":"str"}],"x":2330,"y":310,"wires":[["8c31cf77f3bb4a8f"],["313d32e3301a1334"],["55852d37f54ce4aa"]]},{"id":"8c31cf77f3bb4a8f","type":"debug","z":"fe5670ff.ea94e","name":"debug 291","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2540,"y":260,"wires":[]},{"id":"313d32e3301a1334","type":"debug","z":"fe5670ff.ea94e","name":"debug 292","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2540,"y":310,"wires":[]},{"id":"55852d37f54ce4aa","type":"debug","z":"fe5670ff.ea94e","name":"debug 293","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2540,"y":360,"wires":[]},{"id":"a983f23c1fe734e3","type":"inject","z":"fe5670ff.ea94e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":2070,"y":250,"wires":[["5077b4ba298d5790"]]},{"id":"6161f88f12c31c21","type":"inject","z":"fe5670ff.ea94e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":2070,"y":310,"wires":[["5077b4ba298d5790"]]},{"id":"2bf216ccb9770f76","type":"inject","z":"fe5670ff.ea94e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"X","payloadType":"str","x":2070,"y":370,"wires":[["5077b4ba298d5790"]]},{"id":"3d273f7721b4b809","type":"inject","z":"fe5670ff.ea94e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"RELOAD","payloadType":"str","x":2080,"y":420,"wires":[["5077b4ba298d5790"]]},{"id":"ee742bf63945e992","type":"inject","z":"fe5670ff.ea94e","name":"disable","props":[{"p":"enabled","v":"false","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2050,"y":130,"wires":[["5077b4ba298d5790"]]},{"id":"8b819c8ad5c4bcd9","type":"inject","z":"fe5670ff.ea94e","name":"enable","props":[{"p":"enabled","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2050,"y":170,"wires":[["5077b4ba298d5790"]]}]

1 sets the output to the ON state
0 sets the output to the OFF state
RELOAD is used to force the text to what is was set to initially.
X toggles the output.
The two enable / disable are used to en/disable the node.
These signals would also go to the GUI node to control it's condition.

Can you show us a simple example showing the node wiping the text when you disable it?

The flow I posted does just that.

I would not describe that as a simple flow. I was thinking more of a button node and two or three Inject nodes.

It only has inject nodes to save anyone who loads the flow to have to mess around with the dashboard and the button.

But if you really insist.

Button not assigned to any dashboard.

[{"id":"402169a8.8a791","type":"subflow","name":"B Toggle 2","info":"2023 11 23\n==\nRe-write code to allow force reloading of desired state.\n\nToggle output at receipt of message.\nConfigurable output and message to send back to button node.\n(2022 12 16)\n\nIf `msg.payload == 0` (number) the output is forced to the OFF condition.\n\nIf `msg.payload == 1` (number) the output is forced to the ON condition.\n\nIf `msg.payload == \"RELOAD\"` (text) the output is set to what you determined in the\n                             `StartMode` value.\n\nAny other input toggles the output.\n\n## ENV variables:\n```\nStartMode - set start condition (`0` off `1` on).\nOnCLR - the colour when ON condition active.\nOnTXT - the text when ON condition active.\nOffCLR - the colour when OFF condition active.\nOffTXT - the text when OFF conditin active.\nON - payload when ON condition active.\nOFF - payload when OFF condition active.\nCTOPIC - the topic of the output message.\n```\n\nOutputs:\n - 1 $OFF for OFF and $ON for ON.\n - 2 $ON for OFF and $OFF for ON.  (Opposite of 1)\n - 3 to be sent back to button with `msg.colour` to set buttons colour and `msg.txt` for the text to be displayed.\n","category":"","in":[{"x":80,"y":190,"wires":[{"id":"69ae694095adea75"}]}],"out":[{"x":670,"y":180,"wires":[{"id":"5a9848b4303ef8d2","port":0},{"id":"8c41e6c213bcdefe","port":0}]},{"x":670,"y":280,"wires":[{"id":"3a564786d2308bdd","port":0},{"id":"a2ec504194f78107","port":0}]},{"x":670,"y":380,"wires":[{"id":"f14d0daf4ad33691","port":0},{"id":"aff48be4199bcfab","port":0},{"id":"69ae694095adea75","port":1}]}],"env":[{"name":"StartMode","type":"num","value":"","ui":{"label":{"en-US":"Start Mode (0/1) (off/on)"},"type":"input","opts":{"types":["num"]}}},{"name":"OffTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OffCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OnTXT","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","num"]}}},{"name":"OnCLR","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"OFF","type":"str","value":""},{"name":"ON","type":"str","value":""},{"name":"CTOPIC","type":"str","value":""}],"meta":{"desc":"Button toggle node with feedback to button"},"color":"#D8BFD8","outputLabels":["Normal output","Inverted output","To button"],"icon":"node-red-dashboard/ui_switch.png","status":{"x":690,"y":510,"wires":[{"id":"4cca89516db73bd2","port":0}]}},{"id":"69ae694095adea75","type":"function","z":"402169a8.8a791","name":"toggle","func":"let a = msg.payload;\nlet msg1 = {};\nlet x = context.get(\"counter\") || 0;\n\nif (msg.enabled != undefined)\n{\n    //      Work to be done here.\n    const en = msg.enabled;\n    if (en == true)\n    {\n        //   ENABLE\n        context.set(\"disabled\",0);\n        a = context.get(\"counter\") || 0;\n    }\n    else\n    if (en == false)\n    {\n        //    DISABLE\n        context.set(\"disabled\",1);\n        msg1.txt = \"disabled\";\n        msg1.colour = env.get(\"OffCLR\");\n        node.status({text:\"DISABLED\"});\n        return [null,msg1];\n    }\n}\n\nif (context.get(\"disabled\") == 1)\n{\n    //  Can't do anything.\n    node.status({text:\"skipped\"});\n    return;\n}\n\nif (a == \"RELOAD\")\n{\n    a = env.get(\"StartMode\");\n}\n\nif (a == 0)\n{\n    context.set(\"counter\",0);\n    msg.payload = 0;\n    node.status({text:\"Force OFF\"});\n    return [msg,null];\n}\nif (a == 1)\n{\n    context.set(\"counter\",1);\n    msg.payload = 1;\n    node.status({ text: \"Force ON\" });\n    return [msg,null];\n}\n\nif (x === 0)\n{\n    msg.payload = 1;\n    node.status({ text: \"ON\" });\n} else\nif (x === 1)\n{\n    msg.payload = 0;\n    node.status({ text: \"OFF\" });\n}\n\nx = (x + 1) % 2;\n\ncontext.set(\"counter\",x);\n\nreturn [msg,null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":190,"wires":[["0db7c2da3958ea2c"],[]],"info":"##  Outputs `1` or `0` for ON/OFF and `msg.colour` to send to button."},{"id":"f14d0daf4ad33691","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"colour","pt":"msg","to":"OffCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OffTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":350,"wires":[[]]},{"id":"aff48be4199bcfab","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"colour","pt":"msg","to":"OnCLR","tot":"env"},{"t":"set","p":"txt","pt":"msg","to":"OnTXT","tot":"env","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":410,"wires":[[]]},{"id":"0db7c2da3958ea2c","type":"switch","z":"402169a8.8a791","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":350,"y":190,"wires":[["5a9848b4303ef8d2","3a564786d2308bdd","f14d0daf4ad33691"],["8c41e6c213bcdefe","a2ec504194f78107","aff48be4199bcfab"]]},{"id":"5a9848b4303ef8d2","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":160,"wires":[[]]},{"id":"8c41e6c213bcdefe","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":210,"wires":[[]]},{"id":"a2ec504194f78107","type":"change","z":"402169a8.8a791","name":"OFF","rules":[{"t":"set","p":"payload","pt":"msg","to":"OFF","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":300,"wires":[[]]},{"id":"3a564786d2308bdd","type":"change","z":"402169a8.8a791","name":"ON","rules":[{"t":"set","p":"payload","pt":"msg","to":"ON","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"CTOPIC","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":250,"wires":[[]]},{"id":"a035346e85f036ba","type":"inject","z":"402169a8.8a791","name":"Start Mode","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.2","topic":"","payload":"StartMode","payloadType":"env","x":130,"y":140,"wires":[["69ae694095adea75"]]},{"id":"4cca89516db73bd2","type":"status","z":"402169a8.8a791","name":"","scope":["69ae694095adea75"],"x":370,"y":510,"wires":[[]]},{"id":"5077b4ba298d5790","type":"subflow:402169a8.8a791","z":"fe5670ff.ea94e","name":"","env":[{"name":"StartMode","value":"1","type":"num"},{"name":"OffTXT","value":"OFF","type":"str"},{"name":"OffCLR","value":"red","type":"str"},{"name":"OnTXT","value":"ON","type":"str"},{"name":"OnCLR","value":"green","type":"str"},{"name":"OFF","value":"off command","type":"str"},{"name":"ON","value":"on command","type":"str"},{"name":"CTOPIC","value":"ctl_topic","type":"str"}],"x":2330,"y":310,"wires":[["8c31cf77f3bb4a8f"],["313d32e3301a1334"],["55852d37f54ce4aa","5a592316731eff5a"]]},{"id":"8c31cf77f3bb4a8f","type":"debug","z":"fe5670ff.ea94e","name":"debug 291","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2540,"y":260,"wires":[]},{"id":"313d32e3301a1334","type":"debug","z":"fe5670ff.ea94e","name":"debug 292","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2540,"y":310,"wires":[]},{"id":"55852d37f54ce4aa","type":"debug","z":"fe5670ff.ea94e","name":"debug 293","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2540,"y":360,"wires":[]},{"id":"ee742bf63945e992","type":"inject","z":"fe5670ff.ea94e","name":"disable","props":[{"p":"enabled","v":"false","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2050,"y":130,"wires":[["5077b4ba298d5790"]]},{"id":"8b819c8ad5c4bcd9","type":"inject","z":"fe5670ff.ea94e","name":"enable","props":[{"p":"enabled","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2050,"y":170,"wires":[["5077b4ba298d5790"]]},{"id":"5a592316731eff5a","type":"ui_button","z":"fe5670ff.ea94e","name":"","group":"48d9dd9c.267f3c","order":36,"width":0,"height":0,"passthru":false,"label":"{{msg.txt}}","tooltip":"","color":"","bgcolor":"{{msg.colour}}","className":"","icon":"","payload":"X","payloadType":"str","topic":"topic","topicType":"msg","x":2320,"y":200,"wires":[["5077b4ba298d5790"]]},{"id":"48d9dd9c.267f3c","type":"ui_group","d":true,"name":"Full_Remote","tab":"b128eb09.9f681","order":1,"disp":false,"width":"3","collapse":false},{"id":"b128eb09.9f681","type":"ui_tab","name":"HDMI_TV_control","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

I don't use subflows for a few reasons, partly because I don't like them taking up space at the top of the palette, partly becasuse I didn't see much use for them.

Probably if I wanted this sort of multiple input - multiple actions feature I would use a function node. If it was likely to be re-used, a link-call.

But you have given me a good example of a subflow so thank you.

The advantage I see is that it maintains context storage for the state of each instance, which my way wouldn't do. :grinning:

1 Like

Can you get it to fail with a button and only inject nodes?

I am still a bit torn between using them.

But ..... needs must....

If you don't mind having a look though at the .... structure of how I get that to work it would be appreciated.

This is about the 3'rd version of it, and before this there were some nasty monsters/bugs in it.
So after chasing them and all that, this is about the third version.

(The notes may tell the story)

I am trying to learn a good structure on how to write things.

Yes, this may not be the ideal scenario, time or place. But it is the best I seem to be in the most.
So I guess it is a better platform than picking another one.

I don't understand the question.

I am using this and it addresses the problem I asked about.
(Sod's law... I have to ask before I learn.)

But I'm asking if there is another way which is more .... standard which I am not seeing with the nodes so when they are disabled there is a way to put text on the button/node's GUI.

Again: As with many of my problems if I don't ask, I don't then go on and try other ways.

That's a bit trickey! I hope this is what you mean.

There are always many different ways to achieve the same thing in programming.
Some people would probably use a finite state machine node, others a subflow, others a function.
As long as it works reliably and you can look at it after 6 months and understand how it works they are equally fine.

Looking at your subflow:

  1. It's not obvious to me what the "Start mode" inject node does, if anything.
  2. In the function you have variables x and a and I can't see what they represent, they are both (sometimes) set to context.get("counter").
    Longer variable names are harder to type but easier to understand.

And looking at the flow:

  • You are using status to show two properties: enabled/disabled and ON/OFF.
    Because a button can be disabled but the light it controls is on, maybe show
    ON/OFF/Disabled - ON/Disabled - OFF ?
  • The "skipped" status is neat but maybe a RELOAD input should replace it with DISABLED - ON etc?

Best I can do...

1 Like

Yeah, thanks.

The a and x,,,, I am in a bit of a quandary with names I can use.
payload is kinda reserved. :wink: I have a poor vocabulary and alas I am not good at picking a valid name for the variable.

I think the reason I did it with the payload is that I needed to change the payload in certain conditions.
I don't know if I could use the msg.payload and manipulate it as I did in the rest of the code.

x is a counter to count the invocations and states in normal use.
And again it needs to be changed.

In the subflow it is used so when it is originally deployed it sets the node to the given condition.
I'm not sure if that could be done in the function node in the on start tab.
(Need to learn more)

That way you can set it so when deployed (first time) you set if the condition to be either on or off.

Ok, the second part:
I am also confused.

What I am using this for:
I can have the light on (or off) and pressing the button toggles the state.
If I disable the button, pressing the button has no effect on the bulb.
When the button is enabled again it retains the previous value it had before being disabled.
The skipped is only decoration to help with me testing things are working and I left it as it's cost isn't too much having it there.

The RELOAD is maybe not needed but if I want to force it back to the condition I set it to have on deployment: this is a handy way to do it.

The force is (could be) handy in certain situations also, and the node keeps track of this input and it has a baring on the next press.

The finite state machine is way above my skill set / understanding. It may be better but alas this is all I understand.

Does that clear up some confusion?

1 Like

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