Knowing and controlling state of 4 states lamp. Already stuck on boolean logic

I am going to give you way more context that you probably need to help me because I feel like executing things the way I immagine is kind of dumb for Node-RED and more suitable to a programming language like C.

In my house I have a room where the lights are under a 4 contact step by step relay so that I have 4 "states", all off, all on, half on and other half on.

I have a Sonoff Mini wired so that it simulates a button press. This way I can control it from Home Assistant. The problem is the sonoff has no idea in what states the lights are and neither does HA.

What I wanna achieve is:

  1. Know which state the lights are in
  2. Knowing which state the lights are in, asking for a specific state and having Node Red press the button the correct number of times to reach the desired state

My thinking is (right now I am not concerned on how to interface with HA):

I press a button, said button triggers a counter, based on that counter I know what states the lights are in.
Now that I know what state the lights are in, if I have the lights in all off and want half on, node red needs to press the button until the counter is 2.

Problem is I am already stuck, I have a counter, and I know how to reset said counter (node-red-contrib-counter), I want the counter to reset (return to 0) when the button is pressed and when the counter reaches it's limit. (I am trying to use node-red-contrib-bool-gate, but I also tried node-red-contrib-boolean-logic and still didn't manage to use either of them)

While I would like someone to explain how to use the and gate because at this point I spent more time than what I will admit on it, I think this approach is stupid, I feel like I am not taking advantage of node red, since I am passing around messages it probably makes more sense to have all of this informations in a message and not in a counter from where I will need to interpreter, but I have no idea where to start. So, if someone can point me to the right direction it would be very apreciated.

I am including my flow, it basically only has a not working counter on it

[{"id":"a9fbaedc.8f9c1","type":"tab","label":"Flow 4","disabled":false,"info":""},{"id":"e6bacb66.65bc38","type":"inject","z":"a9fbaedc.8f9c1","name":"Button Press","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":240,"wires":[["f21b4f64.9a67e","5beefa9e.b2cb64"]]},{"id":"f21b4f64.9a67e","type":"counter","z":"a9fbaedc.8f9c1","name":"Counter ","init":"0","step":"1","lower":null,"upper":"3","mode":"increment","outputs":"1","x":400,"y":240,"wires":[["d69c6482.e9b818","f207c0c6.c4fd8"]],"info":"The light I am trying to control has 4 states:\n0 : off\n1 : all on\n2 : right half on\n3 : left half on\n"},{"id":"d69c6482.e9b818","type":"debug","z":"a9fbaedc.8f9c1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":530,"y":240,"wires":[]},{"id":"f207c0c6.c4fd8","type":"switch","z":"a9fbaedc.8f9c1","name":"","property":"countUpperLimitReached","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":510,"y":320,"wires":[["1e498df9.5ee082","a5d1d3ac.0c282"]]},{"id":"1e498df9.5ee082","type":"debug","z":"a9fbaedc.8f9c1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":320,"wires":[]},{"id":"f0e8e408.c96148","type":"change","z":"a9fbaedc.8f9c1","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"countUpperLimitReached","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":180,"y":440,"wires":[["f21b4f64.9a67e"]]},{"id":"8b583c6.0dfb2c","type":"inject","z":"a9fbaedc.8f9c1","name":"Reset for counter","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":620,"wires":[["f0e8e408.c96148"]]},{"id":"5beefa9e.b2cb64","type":"change","z":"a9fbaedc.8f9c1","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":480,"wires":[["7c7b8677.862a98","a5d1d3ac.0c282"]]},{"id":"7c7b8677.862a98","type":"debug","z":"a9fbaedc.8f9c1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1030,"y":480,"wires":[]},{"id":"a5d1d3ac.0c282","type":"and-gate","z":"a9fbaedc.8f9c1","name":"","rules":[{"t":"true","propertyType":"msg","property":"countUpperLimitReached","topic":""},{"t":"true","propertyType":"msg","property":"topic","topic":""}],"outputTopic":"","gateType":"and","emitOnlyIfTrue":true,"x":520,"y":660,"wires":[["7a24d0e5.a889b"]]},{"id":"7a24d0e5.a889b","type":"debug","z":"a9fbaedc.8f9c1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":700,"y":660,"wires":[]}]

Hi Mike,

I might be missing the point (apologies if I am) - but you could do it like this (without any of the extra nodes - all built in standard nodes)

[{"id":"e6bacb66.65bc38","type":"inject","z":"a9fbaedc.8f9c1","name":"Button Press","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":200,"wires":[["ea6a803b.62ddb"]]},{"id":"f207c0c6.c4fd8","type":"switch","z":"a9fbaedc.8f9c1","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"},{"t":"eq","v":"3","vt":"num"},{"t":"eq","v":"4","vt":"num"}],"checkall":"true","repair":false,"outputs":5,"x":550,"y":220,"wires":[["1e498df9.5ee082"],["5e494a15.14cea4"],["1b5cca05.e21386"],["2e1e5c20.26c024"],["a291b56d.b8adb8"]]},{"id":"1e498df9.5ee082","type":"debug","z":"a9fbaedc.8f9c1","name":"counter is 0 - do something","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":140,"wires":[]},{"id":"f0e8e408.c96148","type":"change","z":"a9fbaedc.8f9c1","name":"","rules":[{"t":"set","p":"counter","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":140,"wires":[["f207c0c6.c4fd8"]]},{"id":"8b583c6.0dfb2c","type":"inject","z":"a9fbaedc.8f9c1","name":"Reset for counter","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":140,"wires":[["f0e8e408.c96148"]]},{"id":"ea6a803b.62ddb","type":"function","z":"a9fbaedc.8f9c1","name":"inc flow.counter","func":"flow.get(\"counter\") || 0;\ncounter ++;\nflow.set(\"counter\", counter);\nmsg.payload = counter;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":200,"wires":[["f207c0c6.c4fd8"]]},{"id":"5e494a15.14cea4","type":"debug","z":"a9fbaedc.8f9c1","name":"counter is 1 - do something","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":180,"wires":[]},{"id":"1b5cca05.e21386","type":"debug","z":"a9fbaedc.8f9c1","name":"counter is 2 - do something","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":220,"wires":[]},{"id":"2e1e5c20.26c024","type":"debug","z":"a9fbaedc.8f9c1","name":"counter is 3 - do something","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":260,"wires":[]},{"id":"a291b56d.b8adb8","type":"debug","z":"a9fbaedc.8f9c1","name":"counter is 4 - do something","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":300,"wires":[]}]

Its not clever - deliberately so - to demonstrate sometimes people overthink somewhat :wink:

I might be missing the point (apologies if I am)

My problem right now is I am so new I don't even understand what I am not understanding lol, however,
I am gettting this error when trying to press "button press"

ReferenceError: counter is not defined (line 2, col 1)

ah ha - I'll post something I found extremely useful to get to grips with node-red at the end of this post.

Ah - sorry, i didnt test it :blush:
change the code inside the function to this...

var counter = flow.get("counter") || 0;
if(counter < 0) counter = 0; //clamp counter to min 0
if(counter > 4) counter = 4; //clamp counter to max 4
flow.set("counter", counter);
msg.payload = counter;
return msg;

useful info I promised...

I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.

I suppose I got to put some more time into this, i got halfway through that playlist and I thought I could start to tip my toes in, guess not.

I got everything working witht the new configuration and I even managed to reset the counter from the last state of the switch (yeah I know you probably don't percieve this as a big accomplishment but I do lol)

But I have one question, is it feasible getting in node red with no knowledge of Javascript? while seeing what you wrote in the function node I kind of see what's happening I don't think I am able to use function nodes on my own

[edit] this is probably off topic but you are very nice and I will take advantage of that

Yes, you can achieve a lot / most things. I could have used standard nodes but sometimes, it makes things more visually cluttered & if you can compact some things into a function block (that dont need to be visual) then it can help you focus on the flow.

What I will say is, do what you can using standard nodes & as you progress, dip your toes into JS now and again - and don't forget there are literally MILLIONs of JS programmers (I am fairly certain it is currently No.1 language atm) so its not hard to find help.

Ha ha - thanks mate.

PS - this might help a little...

//retrieve counter from flow context (or 0 if it doesnt exist)
var counter = flow.get("counter") || 0; 

//clamp counter to min 0
if(counter < 0) counter = 0; 

//increment the counter by 1

//clamp counter to max 4
if(counter > 4) counter = 4; 

//store the counter for the next time the button is pressed
flow.set("counter", counter);

//set msg.payload to the value of counter - for later use
msg.payload = counter;

//return the msg object to any nodes attached to the output of the function
return msg;
1 Like

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