Adding values but more like `AND` than `+`

This is a recent thing I got working. Thanks to all who helped me with the syntax error I made.

The problem now is it is a bit too good at doing what I want it to do.

The idea is the R G and B values may be used for different things and so if the LED is showing a RED event and a BLUE event comes in, it becomes RED AND BLUE.

The problem is that if another RED value comes in: the RED value is added.
This can quickly go over the allowed 255 for maximum value.

I would prefer if the values were anded together.

So the existing RED value is anded. So if the value hasn't changed, the RED value won't change.

Given that all the events that use RED are the same value.

Code:

if (msg.debug != undefined)
{
    context.set("DEBUG",msg.debug);
    node.warn("Debug set to " + msg.debug);
    return;
}

let debug = context.get("DEBUG") || 0;

//  Get LED number from `payload`
//let led = parseInt(msg.payload.split(",")[1]);
let payload = msg.payload
let blah = payload.split(",")[1];


let led = parseInt(blah);
if (debug == 1)
    node.warn("LED " + led);

if (led > 4)
{
    if (debug == 1)
        node.warn("LED Colour adjustment happening");
    //  Get RGB values from `payload`
    let n_red = parseInt(payload.split(",")[2])
    let n_green = parseInt(payload.split(",")[3])
    let n_blue = parseInt(payload.split(",")[4])
    if (debug == 1)
    {
        node.warn("==== New values below ====");
        node.warn("R " + n_red + " G " + n_green + " B " + n_blue);
    }

    let existing_value = msg.existing[led];
    //  Now get existing RGB values.
    if (existing_value == undefined)
    {
        existing_value = "0,0,0";
    }
    let x_red = parseInt(existing_value.split(",")[0]);
    let x_green = parseInt(existing_value.split(",")[1]);
    let x_blue = parseInt(existing_value.split(",")[2]);
    
    if (debug == 1)
    {
        node.warn("---- Exiting values below ----");
        node.warn("R " + x_red + " G " + x_green + " B " + x_blue);
    }

    let red = n_red + x_red;
    let green = n_green + x_green;
    let blue = n_blue + x_blue;
    
    msg.payload = "rgb," + led + "," + red + "," + green + "," + blue
}


//if (msg.payload.who == "All clear")       //  Old code
if (msg.wipe == "WIPE")
{
    //
    //  Wipe the alarm LEDs
    //
    //  work needed
    msg.payload = "rgb," + led + ",0,0,0";

}
if (msg.clear == "CLEAR")
{
    //  `flow.LEDSTRIP`
    flow.set("LEDSTRIP["+led+"],0,0,0")
}

return msg;

I'm guessing it will be simple. I just am not sure how to do it.

I'm suspicious it is && rather than the + in the lines:

    let red = n_red + x_red;
    let green = n_green + x_green;
    let blue = n_blue + x_blue;

Correct?

So they would become:

    let red = n_red && x_red;
    let green = n_green && x_green;
    let blue = n_blue && x_blue;

Yeah: dumb question.

You can set a maximum value of 255:
let red = Math.min(n_red + x_red, 255); // Either the total or 255, whichever is least
Or a maximum of 255 and minimum of 0:
let red = Math.max(Math.min(n_red + x_red, 255), 0);

Yes, thanks.

But that is kind of ..... avoiding the idea that the alarms are more colour (RGB) than brightness.
So a red alarm is red (and at a fixed brightness) not matter how many times it happens.

Yes if the same alarm keeps happening it would/may be nice to get a brighter indication.
Not really sure that is a good idea to have or not.

Is the && I proposed correct in what I explained I wanted to do?

Since you were adding, I assumed you wanted different brightnesses.

When you AND two integers, if either of them is zero you get zero. Otherwise you get the second one.

10 && 5 = 5
5 && 10 = 10
0 && 10 = 0
10 && 0 = 0

When you OR two integers, you get the first one which is non zero, else zero

10 || 5 = 10
5 || 10 = 5
0 || 10 = 10
10 || 0 = 10
0 || 0 = 0

Sorry, without example incoming messages and the desired output, I don't really understand what you are after!

That's ok. Thanks.

The values are constant for the R G B values. So now I have to work out do I wan to && or ||

But you have confirmed it is &&... Though I may have to use || because I didn't think it through enough.

If you are operating on numbers you may want bitwise operations instead (or may not :-)... which are single | or &

Again: Thanks.

Alas the mention of the || has kind of thrown a spanner in the works.

Ok, more details:

Given now the R G B values are all 0.

and we are only talking one LED. There is an array, but that's handled at another level to what is happening here.

So, we get a message: rgb,30,0,0 That turns on the red to a value of 30.
Soon after I get a message rgb,0,30,0. I need to keep the red at 30 and make the green 30.

The message has the existing value of 30,0,0. So I want the output to be:
rgb,30,30,0

All that happens quite happily with +. But when I get another rgb,30,0,0 I don't want to see/send rgb,60,30,0. Though I have said that could be handy.

I just want to keep the message as rgb,30,30,0.

So it is looking more like I need the || than &&.

There is a problem when I want to turn the LED off, but that's done with a cheat message, as I had already considered the accumulation problem and so wiping the values is handled else where.

I didn't post the code as it is a bit convoluted and I am not sure it is fair expecting you to wrap your head around it. I need the practice/exercise at wording my questions better. (And spelling) :wink:

Woah there! "confirmed" is a bit strong. :grinning:

Ok, sorry.... I didn't mean I was putting the blame on you.

I wasn't sure of the ...... command?

And so && is AND-ing the two values, as opposed to .... something else.

That is what I meant by that statement. :wink:

I think I'd be inclined to send 1 or 0 for each colour. and OR them with the existing value.

FInally, translate 1 to your preferred ON value for each colour

existing = [0,0,1] (Blue is ON)
message = [1,0,0] (want RED as well)
Result = [1, 0, 1]
Output = [30, 0, 30]

A real programmer would probably pass these as bits in a single byte and bitwise OR them.

Ok, here is an exert of the flow:

[{"id":"4a3266fd.5be67","type":"inject","z":"a1911aa3.c45be8","name":"LED 5 ON (test) red","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,20,0,0","payloadType":"str","x":770,"y":900,"wires":[["f866f539.612c18","9765c17e.b692a8"]]},{"id":"c342263d.eed5a","type":"inject","z":"a1911aa3.c45be8","name":"LED 5 ON (test) green","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,0,20,0","payloadType":"str","x":780,"y":940,"wires":[["f866f539.612c18","9765c17e.b692a8"]]},{"id":"18013920.a70a1f","type":"inject","z":"a1911aa3.c45be8","name":"LED 2 ON (test) blue","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,0,0,20","payloadType":"str","x":770,"y":980,"wires":[["f866f539.612c18","9765c17e.b692a8"]]},{"id":"828fbf56.abdc08","type":"inject","z":"a1911aa3.c45be8","name":"LED 2 OFF (test)","props":[{"p":"wipe","v":"WIPE","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,0,0,0","payloadType":"str","x":760,"y":1020,"wires":[["f866f539.612c18","9765c17e.b692a8"]]},{"id":"f866f539.612c18","type":"link out","z":"a1911aa3.c45be8","name":"","links":["ccf13909.72b9f"],"x":935,"y":950,"wires":[]},{"id":"ccf13909.72b9f","type":"link in","z":"a1911aa3.c45be8","name":"Tele_LED command","links":["83a0be11.af7fa","6b0b56b1.42d7e","6dc80421.3dba54","a92024f2.8a95f8","7a3697ed.7f8c7","40aa6c5d.836b7c","2d025d3e.db9caa","8592035a.b9461","b3d937a3.7dfc18","6e4351dc.b4808","36d5ea1.af9fc96","b7ed8dbf.3bf508","5f49a14a.d41a9","17f005b6.ef87ba","caccb33b.17d5e8","b81aee46.41964","4616b7f2.825d8","d8bc91eb.dda1d","3c727657.fcbca2","cfd44ec6.51e508","410375d8.ecfa5c","eca9f37f.557878","b00d31ee.dd87c8","cdb5a49b.9271b8","efcc907f.dddaa8","3023429e.524cd6","f866f539.612c18"],"x":280,"y":640,"wires":[["3ef2d6b1.89130a","3365a854.4c8d5"]],"l":true},{"id":"3365a854.4c8d5","type":"switch","z":"a1911aa3.c45be8","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"rgb,","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":620,"y":660,"wires":[["f901977f.2dbaa8"]]},{"id":"f901977f.2dbaa8","type":"change","z":"a1911aa3.c45be8","name":"get `existing`","rules":[{"t":"set","p":"existing","pt":"msg","to":"LEDSTRIP","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":700,"wires":[["3445206e.094b08"]]},{"id":"3445206e.094b08","type":"function","z":"a1911aa3.c45be8","name":"ADD values","func":"//  Define variables here/now\nlet n_red = \"\";\nlet n_green = \"\";\nlet n_blue = \"\";\nlet e_red = \"\";\nlet e_green = \"\";\nlet e_blue =\"\";\nlet x_red = \"\";\nlet x_green = \"\";\nlet x_blue = \"\";\n\nlet payload = \"\";\nlet blah = \"\";\nlet led = \"\";\n\nif (msg.debug != undefined)\n{\n    context.set(\"DEBUG\",msg.debug);\n    node.warn(\"Debug set to \" + msg.debug);\n    return;\n}\n\nlet debug = context.get(\"DEBUG\") || 0;\n\n//  Get LED number from `payload`\n//let led = parseInt(msg.payload.split(\",\")[1]);\npayload = msg.payload\nblah = payload.split(\",\")[1];\n\n\nled = parseInt(blah);\nif (debug == 1)\n    node.warn(\"LED \" + led);\n\nif (led > 4)\n{\n    if (debug == 1)\n        node.warn(\"LED Colour adjustment happening\");\n    //  Get RGB values from `payload`\n    n_red = parseInt(payload.split(\",\")[2])\n    n_green = parseInt(payload.split(\",\")[3])\n    n_blue = parseInt(payload.split(\",\")[4])\n    if (debug == 1)\n    {\n        node.warn(\"==== New values below ====\");\n        node.warn(\"R \" + n_red + \" G \" + n_green + \" B \" + n_blue);\n    }\n\n    let existing_value = msg.existing[led];\n    //  Now get existing RGB values.\n    if (existing_value == undefined)\n    {\n        existing_value = \"0,0,0\";\n    }\n    x_red = parseInt(existing_value.split(\",\")[0]);\n    x_green = parseInt(existing_value.split(\",\")[1]);\n    x_blue = parseInt(existing_value.split(\",\")[2]);\n    \n    if (debug == 1)\n    {\n        node.warn(\"---- Exiting values below ----\");\n        node.warn(\"R \" + x_red + \" G \" + x_green + \" B \" + x_blue);\n    }\n\n    //  Old code\n    //red = n_red + x_red;\n    //green = n_green + x_green;\n    //blue = n_blue + x_blue;\n    //  New code 2021 12 05         was `&&` changed to `||`\n    red = n_red || x_red;\n    green = n_green || x_green;\n    blue = n_blue || x_blue;\n    \n    msg.payload = \"rgb,\" + led + \",\" + red + \",\" + green + \",\" + blue\n}\n\n\n//if (msg.payload.who == \"All clear\")       //  Old code\nif (msg.wipe == \"WIPE\")\n{\n    //\n    //  Wipe the alarm LEDs\n    //\n    //  work needed\n    msg.payload = \"rgb,\" + led + \",0,0,0\";\n\n}\nif (msg.clear == \"CLEAR\")\n{\n    //  `flow.LEDSTRIP`\n    flow.set(\"LEDSTRIP[\"+led+\"],0,0,0\")\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":700,"wires":[["a3bdb00e.d03ab","90101528.4eda98"]]}]

Given all flow.variables exist and are correct.

The RBG values are 0 - 255. They are basically NEO-PIXEL leds.

If 0,30,0 only means "set green to 30", what message do you send to turn off the red led?

1 Like

A sneaky message like this:

{"_msgid":"59a12393.ebcd1c","wipe":"WIPE","payload":"rgb,5,0,0,0"}

Though that also includes the information that it is for LED 5.

I realised that with what I was wanting to do, there would be a trap turning the LEDs off.
So I added a wipe property that is used to turn the LED off.

Swings and roundabouts. ¯_(ツ)_/¯

Oh..... Ok. Now I see what you were meaning.

Yeah. I guess I could send.,,,,,

Ah. That's not going to work either.
I guess I could put a condition where if msg.wipe is set make it && where as if msg.wipe isn't set it is ||.

That should work.

But when I am at that.... stage, I am looking at all the alarms and the idea is there shouldn't be squillions of them. I step through the list and get to the point where all are cleared.

Thanks for pointing that out to me.
I'm not sure that what you said is going to be applied how I am doing it. But thanks for mentioning it.

Oh!
As I am stepping through the list, the RGB values are sent again to the LED, so the respective LED is turned off and when the next message in the queue is displayed it's respective message sets the LED as needed.

The LED input is from two places. The real time signal and a queue node output which also gets it's input from the real time signal too.

Maybe some thing like this
If msg.as_is is set to true then the rgb will be set to the payload , so you can wipe or set to what ever you need.

[{"id":"347781de.90bebe","type":"inject","z":"88fadd65b9040724","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,60,0,0","payloadType":"str","x":140,"y":520,"wires":[["374fa350.54c28c"]]},{"id":"374fa350.54c28c","type":"function","z":"88fadd65b9040724","name":"","func":"let rgb = msg.payload.split(\",\");\nif(!msg.as_is){\n    let stored = flow.get(\"rgb.led\" + rgb[1] ) || `${rgb[0]},${rgb[1]},0,0,0`;\n    stored = stored.split(\",\");\n    msg.payload = `${rgb[0]},${rgb[1]},${Number(rgb[2]) || stored[2]},${Number(rgb[3]) || stored[3]},${Number(rgb[4]) || stored[4]}`;\n}\nflow.set(\"rgb.led\" + rgb[1], msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":620,"wires":[["33710796.b87a7"]]},{"id":"3243f1f3.f1c8b6","type":"inject","z":"88fadd65b9040724","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,30,0,0","payloadType":"str","x":120,"y":580,"wires":[["374fa350.54c28c"]]},{"id":"b060fa5b.23b808","type":"inject","z":"88fadd65b9040724","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,0,30,0","payloadType":"str","x":120,"y":620,"wires":[["374fa350.54c28c"]]},{"id":"b7c16e41.4af62","type":"inject","z":"88fadd65b9040724","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,30,30,0","payloadType":"str","x":120,"y":660,"wires":[["374fa350.54c28c"]]},{"id":"33710796.b87a7","type":"debug","z":"88fadd65b9040724","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":620,"wires":[]},{"id":"297b4f95.b933f8","type":"inject","z":"88fadd65b9040724","name":"set as  in payload","props":[{"p":"payload"},{"p":"as_is","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"rgb,5,0,0,0","payloadType":"str","x":160,"y":700,"wires":[["374fa350.54c28c"]]}]

Thanks @E1cid .... Just now there are a few other worms in that area.

I'll have a buther's hook and see if I can get my head around it and how much work would be entailed applying it to what I already have.

You could send null as the value for colours that were not to be changed.

I've just had a look.... Mind blown.

Thanks. But the programming is above my skill/understanding.

I don't understand how the rgb[1]) works to allow an array of LEDs. because the 1 is fixed.

and something is/was lost with the msg.as_is SORRY! Just found it. Hidden.

Yeah, I fully appreciate how good what you wrote is, but it is magic to me and I can't parse it.

My bad, I know. I need to learn more, but that's a given. :wink:

rgb[1] is the led id number , it is used in the flow context to store each led in it's own property, all in one object. Rather than a seperate context var for each led. This way you can delete all led context in one go. Have a look at how it is stored in context object rgb

That is an idea - I guess.

But there is a lot of stuff already written.

I am just trying to make it that if an alarm message is received, it sets the notification and colours the LED as needed.

Then if/when another alarm happens it adds the colour to the LED. As in (literally) the colour. The brightness isn't/doesn't change.

Some alarms show as RED, some BLUE and some GREEN.
This signal is split and one sent directly to the LED and the other is sent into a queue node.
I press a button and it steps the queue to the next message.
That message sends the LED message and so resets the colour as needed for THAT alarm.
(That isn't crucial at this point) I am looking at the screen and going through the list of what has happened.