A little bit of a flow that others may like

It was just for to see actually button disabled state for one second before it switches the state. And also as there is no actual device in this flow, there is no way to get actual state of device to figure out correct state for button.
This kind of button setup works as device state indicator as well as button to change device state.
In real life flow might look something like this


What will happen is that if you press the button the button itself stays disabled and you can't send out another message to device before you get response from device. Kind of safety feature :slight_smile:

Thanks again.

It is nice/handy, and I am learning.

In one of my flows I have two buttons (and switch). One button acts as a “safety” on the second one being accidentally pressed.

You have to press the first one, then in the time allowed, press the second one.

I shall (timer permitting) try to apply what you have shown in that flow to that idea.

On making things look nicer, I am still stuck with how to add background pictures to a flow.
(though that is off topic on this thread.)

There is thread about this topic also
https://discourse.nodered.org/t/getting-image-in-dashboard/228

Oh, I have also tried “tweaking” your flow to this:

[{"id":"19a965e4.4e2ee2","type":"inject","z":"2d44537.f26082c","name":"Once","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":100,"y":2750,"wires":[["60f8f5f7.8c0054"]]},{"id":"60f8f5f7.8c0054","type":"function","z":"2d44537.f26082c","name":"Init","func":"var devicestate =  {active:false};\nglobal.set(\"devicestate\",devicestate);\nreturn msg;","outputs":1,"noerr":0,"x":240,"y":2750,"wires":[["1861ab3d.598525"]]},{"id":"1861ab3d.598525","type":"function","z":"2d44537.f26082c","name":"determineButtonState","func":"var state = global.get(\"devicestate\");\nvar label;\nvar color;\n\nif(state.active === true){\n    label = \"ON\";\n    color = \"green\";\n}\nelse{\n    label = \"OFF\";\n    color = \"red\";\n}\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":2750,"wires":[["92efd03b.82bcb"]]},{"id":"92efd03b.82bcb","type":"ui_button","z":"2d44537.f26082c","name":"on/off","group":"e92a3b22.d9a7f","order":0,"width":"0","height":"0","passthru":false,"label":"{{msg.topic}}","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"","payloadType":"date","topic":"","x":600,"y":2750,"wires":[["adbb8ea9.5ccf28"]]},{"id":"adbb8ea9.5ccf28","type":"function","z":"2d44537.f26082c","name":"buttonHandler","func":"var state = global.get(\"devicestate\");\nvar label;\nvar color;\n\nif(state.active === true){\n    state.active = false;\n    label = \"OFF\";\n    color = \"red\";\n}\nelse{\n    state.active = true;\n    label = \"ON\";\n    color = \"green\";\n    msg.payload = \"whatever data needs to be sent to proccessing\"\n}\nglobal.set(\"devicestate\", state);\n\n\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\nreturn [buttonstate,msg];\n","outputs":"2","noerr":0,"x":570,"y":2800,"wires":[["1861ab3d.598525"],["3023154b.5e7e0a"]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"3023154b.5e7e0a","type":"debug","z":"2d44537.f26082c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":2800,"wires":[]},{"id":"e92a3b22.d9a7f","type":"ui_group","name":"Group 1","tab":"ca0660be.1a8d2","order":1,"disp":true,"width":6},{"id":"ca0660be.1a8d2","type":"ui_tab","z":"","name":"Testing","icon":"build","order":6}]

That way the “message to do what ever” is only sent when the button is pressed and turned ON.
But I seem to also be getting the timestamp sent to the DEBUG node.

Yeah, I’ve tried that but can’t get anywhere with it.

I edit the “settings.js” file and add the line with:

httpStatic: 'home/pi/',

then put a node with a path to the picture and it doesn’t work.

[{"id":"2473f965.2a5456","type":"ui_template","z":"2d44537.f26082c","group":"e92a3b22.d9a7f","name":"","order":0,"width":0,"height":0,"format":"<style>\n    body {\n        background-image: url(\"/Pictures/clocl.jpg\");\n    }\n</style>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":230,"y":330,"wires":[[]]},{"id":"e92a3b22.d9a7f","type":"ui_group","name":"Group 1","tab":"ca0660be.1a8d2","order":1,"disp":true,"width":6},{"id":"ca0660be.1a8d2","type":"ui_tab","z":"","name":"Testing","icon":"build","order":6}]

But I am not getting joy.

I am probably missing the elephant.

Just to help: the file I want as the background is in the path:
/home/pi/Pictures/clock.jpg

I’ll be honest and post here that I can’t spell.

Found the spelling mistake and it works.

Sorry.

Most cases the best way to figure out reasons to this kind of issues is to use browser dev tools.

For your httpStatic setting to work, you need to point at the absolute pathname to the directory (so “/home/pi”) – when you don’t start it with a slash, you are telling it to use a directory called “home” under the current node-red directory, which probably does not exist.

Also, one other “gotcha” is that you will need to have either an httpAdmin or httpRoot prefix defined in your settings.js, since enabling httpStatic means that the URL “/” now gets intercepted by the static file service. Once you are able to type the URL http://localhost:1880/Pictures/clock.jpg into your browser and see the image, your background template should work…

I would also strong recommend not setting httpStatic to just /home/pi - as that will expose your entire home directory and all its contents.

I suggest you create a directory just for this purpose and use that - for example /home/pi/node-red-static

1 Like

Thanks again both.

I am setting httpStatic to /home/pi for now because I am just playing with pictures (etc) - well actually only pictures - and don’t want to have multiple copies of them here and there.

Also the machine is not on the net (96% of the time) and so isn’t that much likely to be hacked.

I shall work in changing that at some time when it is more … needed?

But I do get the flaw in what I am doing.

Something like this? Can be done also with a function directly but with nodes fomr palette is also easy.

[{"id":"82689cc3.2322b","type":"ui_button","z":"3a79879.af7b678","name":"","group":"b55f6d5b.83d05","order":0,"width":0,"height":0,"passthru":false,"label":"unlock","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"unlock","x":160,"y":2680,"wires":[["fa87c63e.5dfbd8"]]},{"id":"34f094b2.0d5fcc","type":"ui_button","z":"3a79879.af7b678","name":"","group":"b55f6d5b.83d05","order":0,"width":0,"height":0,"passthru":false,"label":"button","color":"","bgcolor":"","icon":"","payload":"set","payloadType":"str","topic":"","x":170,"y":2740,"wires":[["f74da7eb.39c238"]]},{"id":"fa87c63e.5dfbd8","type":"trigger","z":"3a79879.af7b678","op1":"true","op2":"false","op1type":"bool","op2type":"bool","duration":"2","extend":false,"units":"s","reset":"","bytopic":"all","name":"","x":320,"y":2680,"wires":[["d3583814.de9a38"]]},{"id":"8a9150cb.f14b7","type":"change","z":"3a79879.af7b678","name":"","rules":[{"t":"set","p":"unlock","pt":"global","to":"unlocked","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":2660,"wires":[[]]},{"id":"f74da7eb.39c238","type":"switch","z":"3a79879.af7b678","name":"","property":"unlock","propertyType":"global","rules":[{"t":"eq","v":"unlocked","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":330,"y":2740,"wires":[["2fa30573.c5e9aa","9673bb0.b681b48","496c1215.3052fc"]]},{"id":"2fa30573.c5e9aa","type":"debug","z":"3a79879.af7b678","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":510,"y":2740,"wires":[]},{"id":"d3583814.de9a38","type":"switch","z":"3a79879.af7b678","name":"","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":450,"y":2680,"wires":[["8a9150cb.f14b7"],["eff06a4f.29a578"]]},{"id":"eff06a4f.29a578","type":"change","z":"3a79879.af7b678","name":"","rules":[{"t":"set","p":"unlock","pt":"global","to":"locked","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":2700,"wires":[[]]},{"id":"9673bb0.b681b48","type":"ui_switch","z":"3a79879.af7b678","name":"","label":"switch","group":"b55f6d5b.83d05","order":0,"width":0,"height":0,"passthru":false,"decouple":"true","topic":"button","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":170,"y":2820,"wires":[["f74da7eb.39c238"]]},{"id":"496c1215.3052fc","type":"ui_text","z":"3a79879.af7b678","group":"b55f6d5b.83d05","order":0,"width":0,"height":0,"name":"","label":"debug","format":"{{msg.payload}}","layout":"row-spread","x":520,"y":2800,"wires":[]},{"id":"b55f6d5b.83d05","type":"ui_group","z":"","name":"test","tab":"32649d72.d1e1b2","disp":true,"width":"6","collapse":false},{"id":"32649d72.d1e1b2","type":"ui_tab","z":"","name":"test","icon":"dashboard"}]

Yes. Like that.

I did post my version of that though?

One thing I am now noticing with buttons, that when you press them, they turn white and STAY white.

:frowning:

With yours, the text area on the dashboard doesn’t wipe. (just mentioning) And I am not seeing the switch toggle indicating the “enabled” state. I suspect with a quick look it is the names used. But I understand that it is easy to get confused with all the names. :wink:

But thanks for the effort. Though as I mentioned, I am sure I put something like that up already.

Anyway, do you know what is going on with the buttons staying white when pressed?

This is what I have - maybe slightly better done now:

[{"id":"e300107f.8667e8","type":"ui_button","z":"fb549e2f.4d026","name":"","group":"5a16edf3.798c04","order":3,"width":0,"height":0,"passthru":true,"label":"Reset All!","color":"","bgcolor":"","icon":"","payload":"RESET","payloadType":"str","topic":"","x":680,"y":250,"wires":[["1f5cca83.8f19c5"]]},{"id":"f18e898d.b5f0a8","type":"inject","z":"fb549e2f.4d026","name":"Wipe","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":670,"y":290,"wires":[["e300107f.8667e8"]]},{"id":"1f5cca83.8f19c5","type":"function","z":"fb549e2f.4d026","name":"EN","func":"if (msg.topic === \"ENABLE\")\n{\n    //\n    if (msg.payload === 'true')\n    {\n        node.status({fill:\"yellow\",shape:\"dot\",text:\"ENABLED\"});\n        context.set('enable',1);\n    }\n    //if (msg.payload === 'false')\n    else\n    {\n        context.set('enable',0);\n//        context.enable = 0;\n//        context.set('enable',enable_topic);\n        node.status({fill:\"red\",shape:\"dot\",text:\"DISABLED\"});\n    }\n}\nif (msg.topic != \"ENABLE\")\n{\n    if (context.get('enable') == 1)\n    {\n        //\n        node.status({fill:\"green\",shape:\"dot\",text:\"On-line\"});\n        return msg;\n    }\n}\n","outputs":1,"noerr":0,"x":830,"y":250,"wires":[["2205799b.d99d3e","5bb56ab7.6882ac","e1f2b034.e7e33","297a07ec.e91a38"]]},{"id":"99fc784c.cb71b8","type":"function","z":"fb549e2f.4d026","name":"Set Topic","func":"msg.topic=\"ENABLE\";\nreturn msg;","outputs":1,"noerr":0,"x":820,"y":150,"wires":[["9f1b1a02.1ab5"]]},{"id":"14983a82.e709bd","type":"ui_button","z":"fb549e2f.4d026","name":"","group":"5a16edf3.798c04","order":1,"width":0,"height":0,"passthru":true,"label":"Enable","color":"","bgcolor":"","icon":"","payload":"true","payloadType":"str","topic":"","x":680,"y":150,"wires":[["99fc784c.cb71b8"]]},{"id":"9f1b1a02.1ab5","type":"timeouttrigger","z":"fb549e2f.4d026","ontimeouttype":"bool","ontimeoutval":"false","duration":"2","units":"s","name":"","x":690,"y":190,"wires":[["1f5cca83.8f19c5","f81b8be4.ad3f7"]]},{"id":"f81b8be4.ad3f7","type":"ui_switch","z":"fb549e2f.4d026","name":"","label":"Enabled","group":"5a16edf3.798c04","order":2,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"true","onvalueType":"str","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":830,"y":190,"wires":[["4d56bc1b.f1220c"]]},{"id":"4d56bc1b.f1220c","type":"debug","z":"fb549e2f.4d026","name":"Junk","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":960,"y":190,"wires":[]},{"id":"88ae8fe4.52d99","type":"inject","z":"fb549e2f.4d026","name":"Enable","topic":"","payload":"true","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":670,"y":110,"wires":[["14983a82.e709bd"]]},{"id":"297a07ec.e91a38","type":"debug","z":"fb549e2f.4d026","name":"Wipe message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1120,"y":250,"wires":[]},{"id":"5a16edf3.798c04","type":"ui_group","z":"","name":"Wipe all Graphs","tab":"cababfc5.7b2f6","order":4,"disp":true,"width":"4","collapse":false},{"id":"cababfc5.7b2f6","type":"ui_tab","z":"","name":"Control Display","icon":"dashboard","order":6}]

I have injection points too for testing.

Ups you have one node that I don’t have and will have to install it, right now I can’t I will try on another moment because my testing raspi is disconnected now and don’t wnat to start installing now stuff on the one is on use controlling home.

Just a couple of things… on the “enable” button why you set a function afterwards to change the topic while you can set directy the topic on the button config itself?
Other one, on the “enabled” button one payload is a boolean and the other one a string, this kind of things can give you troubles depending what you do later on.

Regards

Being very new to node red, I stumbled across the sample flow that you shared and liked it a lot. Of course I am looking for the type of flow you added as an image, but at my current stage I am not competent to transfer one to the other. What I HAVE managed is to extract status from my MQTT topic so I know whether my physical button is True or False. What I'd love to be able to do is to use your flow and send a on/off payload depending on current state. I also want the button to change state if the physical button and is pushed, thereby changing the state.
So question is - how do i go from your post #17 to the one drawn out in post #20?
Best regards,
Ranur

There is another thread where you can find more examples about this.

Explore and try them out and if no luck then let's deal with more specific questions based on where you exactly stuck :slight_smile:

Cool! Actually I was looking at and have copied that specific thread. AND - Lord and behold - I have manged to make it work. (Proud Newbie!) The challenge is that I will be using 12 buttons, so I thought I'd copy each sequence over and over and - yeah you get it.
Unfortunately that doesn't seem to work. When starting from button 1 ->4 it works, but I can not seem to be able to turn off 1 again before i've turned off the higher number ones.
I think it is the global variable lightstate that creates the problem. Unfortunately, I'm too newbie to understand what I should do. Changing the name lightstate to lighstate1, ls2, ls3... didn't work so I need help.
The input from the mqtt from my Shelly RGBW switch is
ison: t/f
mode: "white"
brightness: nn
power: nn
overpower: t/f
Thankful for any assistance or pointers in this project! :smiley:

[{"id":"932c9a5e.6c66f8","type":"tab","label":"Flow 6","disabled":false,"info":""},{"id":"cd8ee5a7.6a6d48","type":"mqtt out","z":"932c9a5e.6c66f8","name":"","topic":"","qos":"","retain":"","broker":"c86985b9.a9ab78","x":846,"y":70,"wires":[]},{"id":"e298b010.3eff","type":"template","z":"932c9a5e.6c66f8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"brightness\" :{{payload}}}","output":"str","x":616,"y":70,"wires":[["cd8ee5a7.6a6d48","5db7e0e5.e58de"]]},{"id":"5db7e0e5.e58de","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":846,"y":110,"wires":[]},{"id":"27598731.c5b6f8","type":"change","z":"932c9a5e.6c66f8","name":"Brightness","rules":[{"t":"move","p":"payload.brightness","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":70,"wires":[["5bade9f2.8815a8"]]},{"id":"64bdea3d.42a334","type":"json","z":"932c9a5e.6c66f8","name":"","property":"payload","action":"","pretty":false,"x":106,"y":110,"wires":[["27598731.c5b6f8","e5a8e727.96e478"]]},{"id":"12ab70a3.8bcd0f","type":"mqtt in","z":"932c9a5e.6c66f8","name":"Status 1_1","topic":"shellies/shellyrgbw2-B0D733/white/0/status","qos":"2","broker":"c86985b9.a9ab78","x":96,"y":50,"wires":[["64bdea3d.42a334"]]},{"id":"e5a8e727.96e478","type":"change","z":"932c9a5e.6c66f8","name":"On/off Status","rules":[{"t":"move","p":"payload.ison","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":110,"wires":[["bdc56e85.850af"]]},{"id":"4da04575.f9b24c","type":"mqtt out","z":"932c9a5e.6c66f8","name":"S1_1 On/off","topic":"shellies/shellyrgbw2-B0D733/white/0/command","qos":"","retain":"","broker":"761dfb74.752d64","x":826,"y":150,"wires":[]},{"id":"8796405f.b5d5f","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"off","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":636,"y":150,"wires":[["4da04575.f9b24c"]]},{"id":"7b70b363.12362c","type":"ui_button","z":"932c9a5e.6c66f8","name":"on/off","group":"c6364af0.be9fe8","order":1,"width":3,"height":1,"passthru":false,"label":"{{msg.topic}}","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"lightstate","payloadType":"global","topic":"shellies/shellyrgbw2-B0D733/white/0/command","x":326,"y":150,"wires":[["d3896a5f.0c44a8","8796405f.b5d5f","e0188c68.fdae4"]]},{"id":"d3896a5f.0c44a8","type":"function","z":"932c9a5e.6c66f8","name":"buttonHandler","func":"//this function runs when you are pressing the button.\n\n// read current state of light\nvar state = global.get(\"lightstate\") || false;\n\nvar label;\nvar color;\n\nif(state === true){\n  // current state is true (light is on) lets turn it off \n    label = \"1\";\n    color = \"red\";\n}\nelse{\n    // current state is false (light is off) lets turn it on \n    label = \"1\";\n    color = \"green\";\n}\n\n// buttonstate is message, which goes straight back to button. It disables button. \n// button stays disabled until MQTT message comes in and tells to node-red \n// what is actual state of that light\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\n// I dont know anything about your mqtt commands\n// usually the commands are created by using msg topic for device select and and msg payload for command\n// Find info about it from your device documentation \n// if the command onoff/set does the toggle action, then it may work\n// but if not, then you must create the command with correct action (on or off)\n\n//msg.payload = \"here I need to way to set an on/off  payload depending on state...\"\n\nreturn [buttonstate,msg];","outputs":"2","noerr":0,"x":476,"y":150,"wires":[["7b70b363.12362c"],[]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"795c95f.d0f286c","type":"function","z":"932c9a5e.6c66f8","name":"determineButtonState","func":"// this function runs every time the MQTT message is arrived (previous node changed the state of light).\n// read the state (if not set somehow, let assume it is false)\nvar state = global.get(\"lightstate\") || false;\nvar label;\nvar color;\n\nif(state === true){\n// state is true (lets make button green)\n label = \"1\";\n color = \"darkorange\";\n}\nelse{\n    // state is false (lets make button red)\n label = \"1\";\n color = \"mediumgray\";\n}\n\n// send out message to button, this outgoing message only changes button visuals\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":156,"y":150,"wires":[["7b70b363.12362c"]]},{"id":"a4c990e2.05ea4","type":"function","z":"932c9a5e.6c66f8","name":"store the state of light","func":"// read current state of light \nvar lightstate = global.get(\"lightstate\") || undefined\nif(msg.payload === \"true\"){\n   lightstate = true\n}\nelse{\n   lightstate = false \n}\n// write state to global context, so we can read it where ever the state is needed\nglobal.set(\"lightstate\",lightstate)\n\n\n// return last known state (we dont use it but the flow must continue)\nmsg.payload = lightstate\nmsg.topic = \"state-of-light-changed\"\nreturn msg;","outputs":1,"noerr":0,"x":656,"y":110,"wires":[["795c95f.d0f286c"]]},{"id":"5bade9f2.8815a8","type":"ui_slider","z":"932c9a5e.6c66f8","name":"slider S1_1","label":"slider S1_1","group":"c6364af0.be9fe8","order":2,"width":9,"height":1,"passthru":true,"topic":"shellies/shellyrgbw2-B0D733/white/0/set","min":0,"max":"100","step":"5","x":446,"y":70,"wires":[["e298b010.3eff"]]},{"id":"bdc56e85.850af","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"true","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"false","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":456,"y":110,"wires":[["a4c990e2.05ea4"]]},{"id":"30840bae.a97b74","type":"mqtt out","z":"932c9a5e.6c66f8","name":"S1_2 On/off","topic":"shellies/shellyrgbw2-B0D733/white/1/command","qos":"","retain":"","broker":"761dfb74.752d64","x":826,"y":310,"wires":[]},{"id":"893c9409.723278","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"off","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":656,"y":310,"wires":[["30840bae.a97b74"]]},{"id":"1263cf58.a3b441","type":"ui_button","z":"932c9a5e.6c66f8","name":"on/off","group":"c6364af0.be9fe8","order":3,"width":3,"height":1,"passthru":false,"label":"{{msg.topic}}","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"lightstate","payloadType":"global","topic":"shellies/shellyrgbw2-B0D733/white/1/command","x":326,"y":310,"wires":[["5fe1a98a.1d9d48","893c9409.723278","a16579e1.d31c78"]]},{"id":"5fe1a98a.1d9d48","type":"function","z":"932c9a5e.6c66f8","name":"buttonHandler","func":"//this function runs when you are pressing the button.\n\n// read current state of light\nvar state = global.get(\"lightstate\") || false;\n\nvar label;\nvar color;\n\nif(state === true){\n  // current state is true (light is on) lets turn it off \n    label = \"2\";\n    color = \"red\";\n}\nelse{\n    // current state is false (light is off) lets turn it on \n    label = \"2\";\n    color = \"green\";\n}\n\n// buttonstate is message, which goes straight back to button. It disables button. \n// button stays disabled until MQTT message comes in and tells to node-red \n// what is actual state of that light\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\n// I dont know anything about your mqtt commands\n// usually the commands are created by using msg topic for device select and and msg payload for command\n// Find info about it from your device documentation \n// if the command onoff/set does the toggle action, then it may work\n// but if not, then you must create the command with correct action (on or off)\n\n//msg.payload = \"here I need to way to set an on/off  payload depending on state...\"\n\nreturn [buttonstate,msg];","outputs":"2","noerr":0,"x":476,"y":310,"wires":[["1263cf58.a3b441"],[]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"6bb1c44c.fb56bc","type":"function","z":"932c9a5e.6c66f8","name":"determineButtonState","func":"// this function runs every time the MQTT message is arrived (previous node changed the state of light).\n// read the state (if not set somehow, let assume it is false)\nvar state = global.get(\"lightstate\") || false;\nvar label;\nvar color;\n\nif(state === true){\n// state is true (lets make button green)\n label = \"2\";\n color = \"darkorange\";\n}\nelse{\n    // state is false (lets make button red)\n label = \"2\";\n color = \"mediumgray\";\n}\n\n// send out message to button, this outgoing message only changes button visuals\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":156,"y":310,"wires":[["1263cf58.a3b441"]]},{"id":"ee6489b4.7b97f8","type":"function","z":"932c9a5e.6c66f8","name":"store the state of light","func":"// read current state of light \nvar lightstate = global.get(\"lightstate\") || undefined\nif(msg.payload === \"true\"){\n   lightstate = true\n}\nelse{\n   lightstate = false \n}\n// write state to global context, so we can read it where ever the state is needed\nglobal.set(\"lightstate\",lightstate)\n\n\n// return last known state (we dont use it but the flow must continue)\nmsg.payload = lightstate\nmsg.topic = \"state-of-light-changed\"\nreturn msg;","outputs":1,"noerr":0,"x":656,"y":270,"wires":[["6bb1c44c.fb56bc"]]},{"id":"abfbee5c.b1c6f","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"true","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"false","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":456,"y":270,"wires":[["ee6489b4.7b97f8"]]},{"id":"109224ab.0a311b","type":"change","z":"932c9a5e.6c66f8","name":"On/off Status","rules":[{"t":"move","p":"payload.ison","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":270,"wires":[["abfbee5c.b1c6f"]]},{"id":"ee86c2ab.f0251","type":"json","z":"932c9a5e.6c66f8","name":"","property":"payload","action":"","pretty":false,"x":106,"y":270,"wires":[["6c97f925.9a2828","109224ab.0a311b"]]},{"id":"6c97f925.9a2828","type":"change","z":"932c9a5e.6c66f8","name":"Brightness","rules":[{"t":"move","p":"payload.brightness","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":230,"wires":[["82a647ca.4b8f68"]]},{"id":"ad69712.850479","type":"mqtt in","z":"932c9a5e.6c66f8","name":"Status 1_2","topic":"shellies/shellyrgbw2-B0D733/white/1/status","qos":"2","broker":"c86985b9.a9ab78","x":96,"y":210,"wires":[["ee86c2ab.f0251"]]},{"id":"82a647ca.4b8f68","type":"ui_slider","z":"932c9a5e.6c66f8","name":"slider S1_2","label":"slider S1_2","group":"c6364af0.be9fe8","order":4,"width":9,"height":1,"passthru":true,"topic":"shellies/shellyrgbw2-B0D733/white/1/set","min":0,"max":"100","step":"5","x":446,"y":230,"wires":[["29371b43.65e7e4"]]},{"id":"29371b43.65e7e4","type":"template","z":"932c9a5e.6c66f8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"brightness\" :{{payload}}}","output":"str","x":616,"y":230,"wires":[["24cc6d1f.95fc32","75137cf2.5b0534"]]},{"id":"24cc6d1f.95fc32","type":"mqtt out","z":"932c9a5e.6c66f8","name":"","topic":"","qos":"","retain":"","broker":"c86985b9.a9ab78","x":846,"y":230,"wires":[]},{"id":"75137cf2.5b0534","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":846,"y":270,"wires":[]},{"id":"a16579e1.d31c78","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":486,"y":350,"wires":[]},{"id":"e0188c68.fdae4","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":466,"y":190,"wires":[]},{"id":"230664c5.d45d2c","type":"mqtt out","z":"932c9a5e.6c66f8","name":"S1_3 On/off","topic":"shellies/shellyrgbw2-B0D733/white/2/command","qos":"","retain":"","broker":"761dfb74.752d64","x":826,"y":470,"wires":[]},{"id":"3f219df9.3f0802","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"off","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":636,"y":470,"wires":[["230664c5.d45d2c"]]},{"id":"c89b69a9.b0a1a8","type":"ui_button","z":"932c9a5e.6c66f8","name":"on/off","group":"c6364af0.be9fe8","order":5,"width":3,"height":1,"passthru":false,"label":"{{msg.topic}}","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"lightstate","payloadType":"global","topic":"shellies/shellyrgbw2-B0D733/white/2/command","x":326,"y":470,"wires":[["53d50749.8b3cd8","3f219df9.3f0802","2acea899.86a798"]]},{"id":"53d50749.8b3cd8","type":"function","z":"932c9a5e.6c66f8","name":"buttonHandler","func":"//this function runs when you are pressing the button.\n\n// read current state of light\nvar state = global.get(\"lightstate\") || false;\n\nvar label;\nvar color;\n\nif(state === true){\n  // current state is true (light is on) lets turn it off \n    label = \"3\";\n    color = \"red\";\n}\nelse{\n    // current state is false (light is off) lets turn it on \n    label = \"3\";\n    color = \"green\";\n}\n\n// buttonstate is message, which goes straight back to button. It disables button. \n// button stays disabled until MQTT message comes in and tells to node-red \n// what is actual state of that light\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\n// I dont know anything about your mqtt commands\n// usually the commands are created by using msg topic for device select and and msg payload for command\n// Find info about it from your device documentation \n// if the command onoff/set does the toggle action, then it may work\n// but if not, then you must create the command with correct action (on or off)\n\n//msg.payload = \"here I need to way to set an on/off  payload depending on state...\"\n\nreturn [buttonstate,msg];","outputs":"2","noerr":0,"x":476,"y":470,"wires":[["c89b69a9.b0a1a8"],[]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"3a45d750.bb0578","type":"function","z":"932c9a5e.6c66f8","name":"determineButtonState","func":"// this function runs every time the MQTT message is arrived (previous node changed the state of light).\n// read the state (if not set somehow, let assume it is false)\nvar state = global.get(\"lightstate\") || false;\nvar label;\nvar color;\n\nif(state === true){\n// state is true (lets make button green)\n label = \"3\";\n color = \"darkorange\";\n}\nelse{\n    // state is false (lets make button red)\n label = \"3\";\n color = \"mediumgray\";\n}\n\n// send out message to button, this outgoing message only changes button visuals\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":156,"y":470,"wires":[["c89b69a9.b0a1a8"]]},{"id":"2acea899.86a798","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":466,"y":510,"wires":[]},{"id":"199a9a13.0a4076","type":"function","z":"932c9a5e.6c66f8","name":"store the state of light","func":"// read current state of light \nvar lightstate = global.get(\"lightstate\") || undefined\nif(msg.payload === \"true\"){\n   lightstate = true\n}\nelse{\n   lightstate = false \n}\n// write state to global context, so we can read it where ever the state is needed\nglobal.set(\"lightstate\",lightstate)\n\n\n// return last known state (we dont use it but the flow must continue)\nmsg.payload = lightstate\nmsg.topic = \"state-of-light-changed\"\nreturn msg;","outputs":1,"noerr":0,"x":656,"y":430,"wires":[["3a45d750.bb0578"]]},{"id":"885a6776.943e38","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"true","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"false","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":456,"y":430,"wires":[["199a9a13.0a4076"]]},{"id":"16b0b10f.c9589f","type":"change","z":"932c9a5e.6c66f8","name":"On/off Status","rules":[{"t":"move","p":"payload.ison","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":430,"wires":[["885a6776.943e38"]]},{"id":"75ba85d7.2a7f2c","type":"json","z":"932c9a5e.6c66f8","name":"","property":"payload","action":"","pretty":false,"x":106,"y":430,"wires":[["a0e79d88.3a49e","16b0b10f.c9589f"]]},{"id":"a0e79d88.3a49e","type":"change","z":"932c9a5e.6c66f8","name":"Brightness","rules":[{"t":"move","p":"payload.brightness","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":390,"wires":[["22485e30.2d8b92"]]},{"id":"95083081.157c7","type":"mqtt in","z":"932c9a5e.6c66f8","name":"Status 1_3","topic":"shellies/shellyrgbw2-B0D733/white/2/status","qos":"2","broker":"c86985b9.a9ab78","x":96,"y":370,"wires":[["75ba85d7.2a7f2c"]]},{"id":"22485e30.2d8b92","type":"ui_slider","z":"932c9a5e.6c66f8","name":"slider S1_3","label":"slider S1_3","group":"c6364af0.be9fe8","order":6,"width":9,"height":1,"passthru":true,"topic":"shellies/shellyrgbw2-B0D733/white/2/set","min":0,"max":"100","step":"5","x":446,"y":390,"wires":[["ed4114b4.150248"]]},{"id":"ed4114b4.150248","type":"template","z":"932c9a5e.6c66f8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"brightness\" :{{payload}}}","output":"str","x":616,"y":390,"wires":[["a3804ed9.6f47a","bf4cffe3.5bb88"]]},{"id":"a3804ed9.6f47a","type":"mqtt out","z":"932c9a5e.6c66f8","name":"","topic":"","qos":"","retain":"","broker":"c86985b9.a9ab78","x":846,"y":390,"wires":[]},{"id":"bf4cffe3.5bb88","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":846,"y":430,"wires":[]},{"id":"b6715d55.c552e","type":"mqtt out","z":"932c9a5e.6c66f8","name":"S1_4 On/off","topic":"shellies/shellyrgbw2-B0D733/white/3/command","qos":"","retain":"","broker":"761dfb74.752d64","x":824,"y":633,"wires":[]},{"id":"b5aac05.c2b954","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"off","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":634,"y":633,"wires":[["b6715d55.c552e"]]},{"id":"5b21a3cc.b8f66c","type":"ui_button","z":"932c9a5e.6c66f8","name":"on/off","group":"c6364af0.be9fe8","order":7,"width":3,"height":1,"passthru":false,"label":"{{msg.topic}}","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"lightstate","payloadType":"global","topic":"shellies/shellyrgbw2-B0D733/white/3/command","x":324,"y":633,"wires":[["e8e8ad71.3e2c7","b5aac05.c2b954","ed5b9cbd.383c1"]]},{"id":"e8e8ad71.3e2c7","type":"function","z":"932c9a5e.6c66f8","name":"buttonHandler","func":"//this function runs when you are pressing the button.\n\n// read current state of light\nvar state = global.get(\"lightstate\") || false;\n\nvar label;\nvar color;\n\nif(state === true){\n  // current state is true (light is on) lets turn it off \n    label = \"4\";\n    color = \"red\";\n}\nelse{\n    // current state is false (light is off) lets turn it on \n    label = \"4\";\n    color = \"green\";\n}\n\n// buttonstate is message, which goes straight back to button. It disables button. \n// button stays disabled until MQTT message comes in and tells to node-red \n// what is actual state of that light\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\n// I dont know anything about your mqtt commands\n// usually the commands are created by using msg topic for device select and and msg payload for command\n// Find info about it from your device documentation \n// if the command onoff/set does the toggle action, then it may work\n// but if not, then you must create the command with correct action (on or off)\n\n//msg.payload = \"here I need to way to set an on/off  payload depending on state...\"\n\nreturn [buttonstate,msg];","outputs":"2","noerr":0,"x":474,"y":633,"wires":[["5b21a3cc.b8f66c"],[]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"ed5b9cbd.383c1","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":464,"y":673,"wires":[]},{"id":"26a90a47.0dc9c6","type":"function","z":"932c9a5e.6c66f8","name":"determineButtonState","func":"// this function runs every time the MQTT message is arrived (previous node changed the state of light).\n// read the state (if not set somehow, let assume it is false)\nvar state = global.get(\"lightstate\") || false;\nvar label;\nvar color;\n\nif(state === true){\n// state is true (lets make button green)\n label = \"4\";\n color = \"darkorange\";\n}\nelse{\n    // state is false (lets make button red)\n label = \"4\";\n color = \"mediumgray\";\n}\n\n// send out message to button, this outgoing message only changes button visuals\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":154,"y":633,"wires":[["5b21a3cc.b8f66c"]]},{"id":"c90ba206.29967","type":"function","z":"932c9a5e.6c66f8","name":"store the state of light","func":"// read current state of light \nvar lightstate = global.get(\"lightstate\") || undefined\nif(msg.payload === \"true\"){\n   lightstate = true\n}\nelse{\n   lightstate = false \n}\n// write state to global context, so we can read it where ever the state is needed\nglobal.set(\"lightstate\",lightstate)\n\n\n// return last known state (we dont use it but the flow must continue)\nmsg.payload = lightstate\nmsg.topic = \"state-of-light-changed\"\nreturn msg;","outputs":1,"noerr":0,"x":654,"y":593,"wires":[["26a90a47.0dc9c6"]]},{"id":"3191abbd.355684","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"true","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"false","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":454,"y":593,"wires":[["c90ba206.29967"]]},{"id":"2f3c1bb0.1da084","type":"change","z":"932c9a5e.6c66f8","name":"On/off Status","rules":[{"t":"move","p":"payload.ison","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":264,"y":593,"wires":[["3191abbd.355684"]]},{"id":"e19335fe.9b8228","type":"json","z":"932c9a5e.6c66f8","name":"","property":"payload","action":"","pretty":false,"x":104,"y":593,"wires":[["a3e3c4da.f537f8","2f3c1bb0.1da084"]]},{"id":"a3e3c4da.f537f8","type":"change","z":"932c9a5e.6c66f8","name":"Brightness","rules":[{"t":"move","p":"payload.brightness","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":264,"y":553,"wires":[["39c54957.6406f6"]]},{"id":"316822e7.007d7e","type":"mqtt in","z":"932c9a5e.6c66f8","name":"Status 1_4","topic":"shellies/shellyrgbw2-B0D733/white/3/status","qos":"2","broker":"c86985b9.a9ab78","x":94,"y":533,"wires":[["e19335fe.9b8228"]]},{"id":"39c54957.6406f6","type":"ui_slider","z":"932c9a5e.6c66f8","name":"slider S1_4","label":"slider S1_3","group":"c6364af0.be9fe8","order":8,"width":9,"height":1,"passthru":true,"topic":"shellies/shellyrgbw2-B0D733/white/3/set","min":0,"max":"100","step":"5","x":444,"y":553,"wires":[["1c5ee82a.cab098"]]},{"id":"1c5ee82a.cab098","type":"template","z":"932c9a5e.6c66f8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"brightness\" :{{payload}}}","output":"str","x":614,"y":553,"wires":[["3a516240.5b51ae","4afae4da.a0009c"]]},{"id":"3a516240.5b51ae","type":"mqtt out","z":"932c9a5e.6c66f8","name":"","topic":"","qos":"","retain":"","broker":"c86985b9.a9ab78","x":844,"y":553,"wires":[]},{"id":"4afae4da.a0009c","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":844,"y":593,"wires":[]},{"id":"c86985b9.a9ab78","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"761dfb74.752d64","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"c6364af0.be9fe8","type":"ui_group","z":"","name":"Light","tab":"7be54798.217718","disp":true,"width":"12","collapse":false},{"id":"7be54798.217718","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":1}]```

You have four different lights (devices). For every one of them you'll need to use unique variable to store the state of that unique light. (can be combined into one variable but let's keep things simple for now) So in every flow (from mqtt input to mqtt output) you'll use only one of those unique flow variables to identfy and store state of this light.

From button you'll need only one wire to go to button handler. Inside button handler determine current state and make decision for outoing messages.
2 messages going out. One goes back to button and the other goes to device (mqtt out)

buttonHandler

//this function runs when you are pressing the button.

// read current state of light. 
// for every light it will be needed to define unique variable
//and store it in flow context (or global context)

// used number 4 here, but should be unique for each flow (device) stream
var state = global.get("lightstate_4") || false;

var label;
var color;
var command;

if(state === true){
  // current state is true (light is on) lets turn it off 
    label = "4";
    color = "red";
    command = "off"
}
else{
    // current state is false (light is off) lets turn it on 
    label = "4";
    color = "green";
    command = "on"
}

// buttonstate is message, which goes straight back to button. It disables button. 
// button stays disabled until MQTT message comes in and tells to node-red 
// what is actual state of that light
var buttonstate = {enabled:false, background:color, topic:label};


msg.payload = command
return [buttonstate,msg];
1 Like

Thanks you! It seemed the obvious easy way out right? I made the change and replaced the "lightstate" for "lightstate_n" for the other button functions as well. However it doesn't work. The MQTT messages are sent as they are supposed to and the Shelly does its magic, but the button hangs in limbo. In my determinebuttonstate function - which is the one that should change AFTER the MQTT msg has confirmed an actual switch change, I have defined the button as orange/gray. It never changes to these colors, but stays at green, which is a color defined in button handler, and as I interpret it - it is the color that is supposed to show between button push and actual confirmation of state.
So what do I try next? Is there a place where the global variables are set where I need to add lightstate_n?

Share the flow again. But not entire flow but only select one stream from end to end.

Here is one flow. I also came across the last post of the link you sent previously. Will se if I can make that work as it is cleaner with less nodes. I guess I still need the variable_1 setup though
. ```

[{"id":"4da04575.f9b24c","type":"mqtt out","z":"932c9a5e.6c66f8","name":"S1_1 On/off","topic":"shellies/shellyrgbw2-B0D733/white/0/command","qos":"","retain":"","broker":"761dfb74.752d64","x":826,"y":150,"wires":[]},{"id":"8796405f.b5d5f","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"off","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":636,"y":150,"wires":[["4da04575.f9b24c"]]},{"id":"7b70b363.12362c","type":"ui_button","z":"932c9a5e.6c66f8","name":"on/off","group":"c6364af0.be9fe8","order":1,"width":3,"height":2,"passthru":false,"label":"{{msg.topic}}","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"lightstate","payloadType":"global","topic":"shellies/shellyrgbw2-B0D733/white/0/command","x":326,"y":150,"wires":[["d3896a5f.0c44a8","8796405f.b5d5f","e0188c68.fdae4"]]},{"id":"d3896a5f.0c44a8","type":"function","z":"932c9a5e.6c66f8","name":"buttonHandler","func":"//this function runs when you are pressing the button.\n\n// read current state of light\nvar state = global.get(\"lightstate\") || false;\n\nvar label;\nvar color;\n\nif(state === true){\n  // current state is true (light is on) lets turn it off \n    label = \"1\";\n    color = \"red\";\n}\nelse{\n    // current state is false (light is off) lets turn it on \n    label = \"1\";\n    color = \"green\";\n}\n\n// buttonstate is message, which goes straight back to button. It disables button. \n// button stays disabled until MQTT message comes in and tells to node-red \n// what is actual state of that light\nvar buttonstate = {enabled:false, background:color, topic:label};\n\n\n// I dont know anything about your mqtt commands\n// usually the commands are created by using msg topic for device select and and msg payload for command\n// Find info about it from your device documentation \n// if the command onoff/set does the toggle action, then it may work\n// but if not, then you must create the command with correct action (on or off)\n\n//msg.payload = \"here I need to way to set an on/off  payload depending on state...\"\n\nreturn [buttonstate,msg];","outputs":"2","noerr":0,"x":476,"y":150,"wires":[["7b70b363.12362c"],[]],"inputLabels":["input"],"outputLabels":["to button","to proccessing"]},{"id":"e0188c68.fdae4","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":466,"y":190,"wires":[]},{"id":"795c95f.d0f286c","type":"function","z":"932c9a5e.6c66f8","name":"determineButtonState","func":"// this function runs every time the MQTT message is arrived (previous node changed the state of light).\n// read the state (if not set somehow, let assume it is false)\nvar state = global.get(\"lightstate\") || false;\nvar label;\nvar color;\n\nif(state === true){\n// state is true (lets make button green)\n label = \"1\";\n color = \"darkorange\";\n}\nelse{\n    // state is false (lets make button red)\n label = \"1\";\n color = \"mediumgray\";\n}\n\n// send out message to button, this outgoing message only changes button visuals\nmsg = {enabled:true, topic:label, background:color};\nreturn msg;","outputs":1,"noerr":0,"x":156,"y":150,"wires":[["7b70b363.12362c"]]},{"id":"a4c990e2.05ea4","type":"function","z":"932c9a5e.6c66f8","name":"store the state of light","func":"// read current state of light \nvar lightstate = global.get(\"lightstate\") || undefined\nif(msg.payload === \"true\"){\n   lightstate = true\n}\nelse{\n   lightstate = false \n}\n// write state to global context, so we can read it where ever the state is needed\nglobal.set(\"lightstate\",lightstate)\n\n\n// return last known state (we dont use it but the flow must continue)\nmsg.payload = lightstate\nmsg.topic = \"state-of-light-changed\"\nreturn msg;","outputs":1,"noerr":0,"x":656,"y":110,"wires":[["795c95f.d0f286c"]]},{"id":"bdc56e85.850af","type":"change","z":"932c9a5e.6c66f8","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"true","fromt":"bool","to":"true","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"false","fromt":"bool","to":"false","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":456,"y":110,"wires":[["a4c990e2.05ea4"]]},{"id":"e5a8e727.96e478","type":"change","z":"932c9a5e.6c66f8","name":"On/off Status","rules":[{"t":"move","p":"payload.ison","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":110,"wires":[["bdc56e85.850af"]]},{"id":"64bdea3d.42a334","type":"json","z":"932c9a5e.6c66f8","name":"","property":"payload","action":"","pretty":false,"x":106,"y":110,"wires":[["27598731.c5b6f8","e5a8e727.96e478"]]},{"id":"27598731.c5b6f8","type":"change","z":"932c9a5e.6c66f8","name":"Brightness","rules":[{"t":"move","p":"payload.brightness","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":266,"y":70,"wires":[["5bade9f2.8815a8"]]},{"id":"12ab70a3.8bcd0f","type":"mqtt in","z":"932c9a5e.6c66f8","name":"Status 1_1","topic":"shellies/shellyrgbw2-B0D733/white/0/status","qos":"2","broker":"c86985b9.a9ab78","x":96,"y":50,"wires":[["64bdea3d.42a334"]]},{"id":"5bade9f2.8815a8","type":"ui_slider","z":"932c9a5e.6c66f8","name":"slider S1_1","label":"slider S1_1","tooltip":"","group":"c6364af0.be9fe8","order":2,"width":9,"height":2,"passthru":true,"outs":"all","topic":"shellies/shellyrgbw2-B0D733/white/0/set","min":0,"max":"100","step":"5","x":446,"y":70,"wires":[["e298b010.3eff"]]},{"id":"e298b010.3eff","type":"template","z":"932c9a5e.6c66f8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"brightness\" :{{payload}}}","output":"str","x":616,"y":70,"wires":[["cd8ee5a7.6a6d48","5db7e0e5.e58de"]]},{"id":"cd8ee5a7.6a6d48","type":"mqtt out","z":"932c9a5e.6c66f8","name":"","topic":"","qos":"","retain":"","broker":"c86985b9.a9ab78","x":846,"y":70,"wires":[]},{"id":"5db7e0e5.e58de","type":"debug","z":"932c9a5e.6c66f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":846,"y":110,"wires":[]},{"id":"761dfb74.752d64","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"c6364af0.be9fe8","type":"ui_group","z":"","name":"Light","tab":"7be54798.217718","order":1,"disp":true,"width":13,"collapse":false},{"id":"c86985b9.a9ab78","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"7be54798.217718","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":2}]```