How to use the same button to turn the lights on/off in node red

Hi, I came across a one small problem. I want to turn on/off the the light system with the same button with node red, but I don’t know how. My idea is to use toggle button but don’t know how to read/keep last used state. So when the lights are off I want to turn them on, and turn them off if they were on. Feel free to help me LoL

Hi and welcome to Node-Red.

Storing states is called CONTEXT.

It will require a bit of coding in a function node.

The button always sends the same thing and the function node does all the work.

EXAMPLE code:

//  read previous state and set to `0` if not set.
let x = context.get("state") || 0

if (x == 0)
{
    msg.payload = "OFF"
}
if (x == 1)
{
    msg.payload = "ON"
}
//  toggle state from `0` to `1`
x = (x + 1) % 2
//  save to context
context.set("state",x)

return msg

But there are a lot of ways to do it.

But just to get you started.

All the best.

1 Like

I tend to use function nodes since I come from a C/C++/Python background, but you might find this documentation useful in using the flow option in the various dropdown properties: https://nodered.org/docs/user-guide/context

If you want to dive into function nodes, start here: https://nodered.org/docs/user-guide/writing-functions

A super compact version for a function node :wink:

const x = context.get("state") || 0;
msg.payload = ["OFF", "ON"][x];
context.set("state", 1-x);
return msg;

Any incoming message, will result in alternating ON OFF messages being output.

As the current state is stored in the function nodes "local" context, you can make multiple copies if you need them, and each will remember it's own state.

Example flow

[{"id":"77db1fa576cb54a2","type":"inject","z":"90084585.8983b8","name":"Trigger","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":580,"y":3420,"wires":[["9d562eb57f4f1ff0"]]},{"id":"82e85d0fcb517759","type":"debug","z":"90084585.8983b8","name":"debug 40","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1000,"y":3420,"wires":[]},{"id":"9d562eb57f4f1ff0","type":"function","z":"90084585.8983b8","name":"Toggle State","func":"const x = context.get(\"state\") || 0;\nmsg.payload = [\"OFF\", \"ON\"][x];\ncontext.set(\"state\", 1-x);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":3420,"wires":[["82e85d0fcb517759"]]}]

Personally I prefer to use ui-switch node rather than a button for things like this. The switch can output On or Off as required for the two states and also then the position of the switch tells you whether the light is on or off.

That assumes that you are using Dashboard 1 or 2 of course.
WinkEyeWinkGIF

You might find this tutorial useful - I wrote it for my IoT students a couple of years ago.

Note: There is a link to the Node-RED flows on the very last page of the tutorial.

Are these physical lights?
Presumably you send a message "on" or "off" somewhere.
What happens if you send "toggle"?

My light is controlled by an esp32 running tasmota. It does respond to "toggle".