Not understanding what's going on with the code

Folks, this is a problem which has been hiding for a while.
I just found/noticed it now.

code:

//  get existing states
const alarm = flow.get("alarm") || null
const error = flow.get("error") || null
const ip = flow.get("ip") || null
const ntp = flow.get("ntp") || null
const reboot = flow.get("reboot") || null
const wap = flow.get("wap") || null

const count = msg.count

const led = "6"

let wipe = context.get("wipe") || 0
let part = ""

switch(count)
{
    case 0:
        //
        msg.payload = alarm
        part = "alarm"
        break
    case 1:
        //
        msg.payload = error
        part = "error"
        break
    case 2:
        //
        msg.payload = ip
        part = "ip"
        break
    case 3:
        //
        msg.payload = ntp
        part = "ntp"
        break
    case 4:
        //
        msg.payload = reboot
        part = "reboot"
        break
    case 5:
        //
        msg.payload = wap
        part = "wap"
        break
    default:
        return
}

if (msg.payload.includes("0,0,0"))
{
    if (wipe == 1)
    {
        //
        context.set("wipe",0)
        msg.wipe = "WIPE"
    }
}
else
{
    //
    node.warn("message detected")
    context.set("wipe",1)
}

let text = count + "  " + part + "  " + wipe + "  " + msg.payload
node.status({ text: text })


return msg;

If any of the *OTHER& 4 are set, it works.
But if the reboot is active, it doesn't work.

Here is a cut down version of the flow.

[{"id":"6c644fb52af9437a","type":"inject","z":"d622397fb0e54309","name":"Test OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"X","payloadType":"str","x":120,"y":880,"wires":[["004b052c72742461"]]},{"id":"adfb96554e03f95e","type":"inject","z":"d622397fb0e54309","name":"Test ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":920,"wires":[["004b052c72742461"]]},{"id":"a0454de4be3f0dca","type":"inject","z":"d622397fb0e54309","name":"Test OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"X","payloadType":"str","x":120,"y":1010,"wires":[["7f7bbb7a67565916"]]},{"id":"8b0c3ffcde3482ae","type":"inject","z":"d622397fb0e54309","name":"Test ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":1050,"wires":[["7f7bbb7a67565916"]]},{"id":"7f7bbb7a67565916","type":"junction","z":"d622397fb0e54309","x":210,"y":1030,"wires":[["0e5f69d208054b61"]]},{"id":"004b052c72742461","type":"junction","z":"d622397fb0e54309","x":210,"y":900,"wires":[["98f004ae12845fbf"]]},{"id":"98f004ae12845fbf","type":"function","z":"d622397fb0e54309","name":"Set error  Orange","func":"const led = 6;\n//node.warn(\"Message received\");\nconst ic = msg.payload;\nif (ic == \"X\")\n{\n    //  Clear.\n    flow.set(\"error\",\"rgb,\" + led + \",0,0,0\")\n    msg.payload = \"OFF\"\n    return msg\n}\nelse\n{\n    //  Set.\n    flow.set(\"error\",\"rgb,\" + led + \",42,4,1\")\n    msg.payload = \"ON\"\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":260,"wires":[[]]},{"id":"0e5f69d208054b61","type":"function","z":"d622397fb0e54309","name":"Set reboot Red","func":"const led = 6;\nconst ic = msg.payload;\nif (ic == \"X\")\n{\n    //  Clear.\n    flow.set(\"reboot\", \"rgb,\" + led + \",0,0,0\");\n    msg.payload = \"OFF\";\n    return msg;\n}\nelse\n{\n    //  Set.\n    flow.set(\"reboot\", \"rgb,\" + led +\",40,0,0\");\n    msg.payload = \"ON\";\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":360,"wires":[[]]},{"id":"7e140af4599b3259","type":"function","z":"d622397fb0e54309","name":"New attempt","func":"//  get existing states\nconst alarm = flow.get(\"alarm\") || null\nconst error = flow.get(\"error\") || null\nconst ip = flow.get(\"ip\") || null\nconst ntp = flow.get(\"ntp\") || null\nconst reboot = flow.get(\"reboot\") || null\nconst wap = flow.get(\"wap\") || null\n\nconst count = msg.count\n\nconst led = \"6\"\n\nlet wipe = context.get(\"wipe\") || 0\nlet part = \"\"\n\nswitch(count)\n{\n    case 0:\n        //\n        msg.payload = alarm\n        part = \"alarm\"\n        break\n    case 1:\n        //\n        msg.payload = error\n        part = \"error\"\n        break\n    case 2:\n        //\n        msg.payload = ip\n        part = \"ip\"\n        break\n    case 3:\n        //\n        msg.payload = ntp\n        part = \"ntp\"\n        break\n    case 4:\n        //\n        msg.payload = reboot\n        part = \"reboot\"\n        break\n    case 5:\n        //\n        msg.payload = wap\n        part = \"wap\"\n        break\n    default:\n        return\n}\n\nif (msg.payload.includes(\"0,0,0\"))\n{\n    if (wipe == 1)\n    {\n        //\n        context.set(\"wipe\",0)\n        msg.wipe = \"WIPE\"\n    }\n}\nelse\n{\n    //\n    node.warn(\"message detected\")\n    context.set(\"wipe\",1)\n}\n\nlet text = count + \"  \" + part + \"  \" + wipe + \"  \" + msg.payload\nnode.status({ text: text })\n\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1280,"y":890,"wires":[["7dd9c3cc63903cd9","324b56bd7ba0d8b1"]]},{"id":"67e4989f1980e536","type":"link in","z":"d622397fb0e54309","name":"link in 23","links":["7b81ef3a34ef3473"],"x":1155,"y":890,"wires":[["7e140af4599b3259"]]},{"id":"7b81ef3a34ef3473","type":"link out","z":"d622397fb0e54309","g":"2c3e298e36a52bde","name":"link out 17","mode":"link","links":["67e4989f1980e536"],"x":985,"y":1300,"wires":[]},{"id":"5d523e1e97e92b14","type":"change","z":"d622397fb0e54309","g":"2c3e298e36a52bde","name":"","rules":[{"t":"delete","p":"reset","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":915,"y":1380,"wires":[["7b81ef3a34ef3473","8738884cb4ae17a5"]],"l":false},{"id":"eb6045154ed7906c","type":"counter","z":"d622397fb0e54309","g":"2c3e298e36a52bde","name":"","init":"0","step":"1","lower":null,"upper":null,"mode":"increment","outputs":1,"x":810,"y":1380,"wires":[["5f0f59d5300191ee","5d523e1e97e92b14"]]},{"id":"253a01d8ca28c862","type":"inject","z":"d622397fb0e54309","g":"2c3e298e36a52bde","name":"Step","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":660,"y":1330,"wires":[["eb6045154ed7906c"]]}]

node-red-contrib-counte is used.

overview:
5 conditions exist.
alarm
error
ip
ntp
wap

Every second the count is incremented and that condition is reflected in the message sent out.

0,0,0 is turning the LED off.
But it doesn't quite work that way and a msg.wipe needs to be set also.

But having it constantly set has its own set of problems.

Which is where:

if (msg.payload.includes("0,0,0"))
{
    if (wipe == 1)
    {
        //
        context.set("wipe",0)
        msg.wipe = "WIPE"
    }
}
else
{
    //
    node.warn("message detected")
    context.set("wipe",1)
}

Comes into play.
(there is a bit more, but.....)
So if a real message is sent through it sets the wipe flag.
then if the message contains 0,0,0 AND the wipe flag is set, it adds the msg.wipe part.

THIS WORKS ON ALL EXCEPT the reboot part - and I don't know why.

Yes, the structure may need refining. Two tests and ONE else.

But if it was a problem: why are the other 4 working?

Someone - please.

Have you tried running it through an AI engine like ChatGPT or Claude?

I have and got this response... there’s one likely runtime issue and a couple of logic improvements.

This is the revised, cleaned-up version that ChatGPT gave me...

// get existing states
const alarm  = flow.get("alarm")  || null
const error  = flow.get("error")  || null
const ip     = flow.get("ip")     || null
const ntp    = flow.get("ntp")    || null
const reboot = flow.get("reboot") || null
const wap    = flow.get("wap")    || null

const count = msg.count
const led = "6"

let wipe = context.get("wipe") || 0
let part = ""

switch(count)
{
    case 0:
        msg.payload = alarm
        part = "alarm"
        break

    case 1:
        msg.payload = error
        part = "error"
        break

    case 2:
        msg.payload = ip
        part = "ip"
        break

    case 3:
        msg.payload = ntp
        part = "ntp"
        break

    case 4:
        msg.payload = reboot
        part = "reboot"
        break

    case 5:
        msg.payload = wap
        part = "wap"
        break

    default:
        return null
}

// Safe check
if (typeof msg.payload === "string" && msg.payload.includes("0,0,0"))
{
    if (wipe === 1)
    {
        wipe = 0
        context.set("wipe", wipe)
        msg.wipe = "WIPE"
    }
}
else
{
    node.warn("message detected")
    wipe = 1
    context.set("wipe", wipe)
}

let text = count + "  " + part + "  " + wipe + "  " + msg.payload
node.status({ text })

return msg

This variable is unused:

const led = "6"

You can remove it unless you plan to use it later.

Can you explain exactly what that line is supposed to do?

In particular what would be the result if flow.get returned 0?

I suspect it is a problem.

the null is probably not the correct thing to assign if not set.

This is what the variables should be by default

the null snuck into the code by default as I am trying to tidy up my coding and not leaving thing undefined: though null isn't exactly a defined value.

It should prbably be rgb,6,0,0,0

But I'm still not smart enough to know how to do that.

Just a quick reminder to watch out when using || because it won't work as expected if your variable contains boolean content. Using ?? instead tightens up the logic.

Not to dismiss the offers, this is the code now:

(Slight adjustments made)

//  get existing states
const alarm = flow.get("alarm") ?? "rgb,6,0,0,0,"
const error = flow.get("error") ?? "rgb,6,0,0,0,"
const ip = flow.get("ip") ?? "rgb,6,0,0,0,"
const ntp = flow.get("ntp") ?? "rgb,6,0,0,0,"
const reboot = flow.get("reboot") ?? "rgb,6,0,0,0,"
const wap = flow.get("wap") ?? "rgb,6,0,0,0,"

const count = msg.count

let wipe = context.get("wipe") || 0
let part = ""

switch(count)
{
    case 0:
        //
        msg.payload = alarm
        part = "alarm"
        break
    case 1:
        //
        msg.payload = error
        part = "error"
        break
    case 2:
        //
        msg.payload = ip
        part = "ip"
        break
    case 3:
        //
        msg.payload = ntp
        part = "ntp"
        break
    case 4:
        //
        msg.payload = reboot
        part = "reboot"
        break
    case 5:
        //
        msg.payload = wap
        part = "wap"
        break
    default:
        return
}

//node.warn(part + " " + msg.payload)

if (msg.payload.includes("0,0,0") && wipe ==1)
{
    //node.warn("HERE")
    context.set("wipe",0)
    msg.wipe = "WIPE"
}
let parts = msg.payload.split(",")
let lastThree = parts.slice(-3) // get last 3 elements
if (!(lastThree.join(",") === "0,0,0")) {
    //node.warn("** message detected " + part + " " + msg.payload);
    context.set("wipe", 1)
    msg.wipe = "OVERWRITE"
}

let text = count + "  " + part + "  " + wipe + "  " + msg.payload
node.status({ text: text })
msg.topic = part

return msg;

Other bits were added (like part) were included for debugging.
I could watch the messages being sent and see what was happening.

But just for clarity too:
There are 6 function nodes else where on this flow.
An extract from them:

flow.set("error","rgb," + led + ",42,4,1")
flow.set("reboot", "rgb," + led +",40,0,0");
flow.set("ip", "rgb," + led +",40,40,0");
flow.set("ntp", "rgb," + led + ",15,0,15");
flow.set("alarm", "rgb," + led +",10,40,0");
flow.set("wap", "rgb," + led +",0,34,34");

And Weirdly it was ONLY the alarm one that did NOT work.

In the meantime, I was told that my way of checking the message NOT containing the 0,0,0 was WRONG.
Thus the new bit of code.

Better?

Other AI's are available. :wink:

So thoughts on the updated code I posted?

:slight_smile:

You should probably change that || to ?? as well since you are using something that could look like a "truthy"/"falsey" value. Also, since you aren't changing the wipe variable, it should be const, not let - in fact, I don't think you are using that variable at all so you can probably get rid of it.

Personally, I would avoid data like "xxxx,0,0,0,0,0" or whatever. If you are using structured data, I would keep it as an array or object, not a string and only convert to a string if/when it has to be.

Check post #7. (oops)

I did that.

Didn't I?

Ok, what's going on.

As posted/shown in post 6:

The messages are received and the flow context is set. (now shown)
Those messages are the ORIGINAL ones sent to the LED but because of lack of LEDs.....
Some have to do multiple duty.

Sow hat happens if there are multiple messages for one led?
Answer: Timed showing.

So over a 6 second time the LED shows the state of the 5 conditions. (Sorry, was 5 - changed to 6 when I realised it is actually 6)
If the condition is CLEAR the LED is turned off.

The wipe is a bit complicated and from a long time ago.
The exact workings are now vague to me.

If set to WIPE the values don't matter. The LED is turned off.
OVERWRITE overwrites the existing value.
(There are problems if it is showing a value and another one comes in.)

So, if a value for a condition changes, I need to reset the RBE. That's where the overwrite comes in. (External detection with nodes also done)

Then it makes the next message - if clear - to WIPE the existing value.

Just saw your reply.
I'll stop here and read it.

You missed one - which is what I quoted.

Um.... I'm looking.

I got the old code and did a search/replace of || null to ?? "rgb,6,0,0,0" and said all/no ckeck.

So, I'm not understanding.
Sorry.

The code - again - for clarity.

//  get existing states
const alarm = flow.get("alarm") ?? "rgb,6,0,0,0,"
const error = flow.get("error") ?? "rgb,6,0,0,0,"
const ip = flow.get("ip") ?? "rgb,6,0,0,0,"
const ntp = flow.get("ntp") ?? "rgb,6,0,0,0,"
const reboot = flow.get("reboot") ?? "rgb,6,0,0,0,"
const wap = flow.get("wap") ?? "rgb,6,0,0,0,"

const count = msg.count

let wipe = context.get("wipe") || 0
let part = ""

switch(count)
{
    case 0:
        //
        msg.payload = alarm
        part = "alarm"
        break
    case 1:
        //
        msg.payload = error
        part = "error"
        break
    case 2:
        //
        msg.payload = ip
        part = "ip"
        break
    case 3:
        //
        msg.payload = ntp
        part = "ntp"
        break
    case 4:
        //
        msg.payload = reboot
        part = "reboot"
        break
    case 5:
        //
        msg.payload = wap
        part = "wap"
        break
    default:
        return
}

//node.warn(part + " " + msg.payload)

if (msg.payload.includes("0,0,0") && wipe ==1)
{
    //node.warn("HERE")
    context.set("wipe",0)
    msg.wipe = "WIPE"
}
let parts = msg.payload.split(",")
let lastThree = parts.slice(-3) // get last 3 elements
if (!(lastThree.join(",") === "0,0,0")) {
    //node.warn("** message detected " + part + " " + msg.payload);
    context.set("wipe", 1)
    msg.wipe = "OVERWRITE"
}

let text = count + "  " + part + "  " + wipe + "  " + msg.payload
node.status({ text: text })
msg.topic = part

return msg;

Still there.

Ah. I was fixated on the rgb message part.

My bad.

But if that can only ever be 0 or 1.....

Just looked at wipe.

I am changing it.

if (msg.payload.includes("0,0,0") && wipe ==1)
{
    //node.warn("HERE")
    context.set("wipe",0)          //  <---- here
    msg.wipe = "WIPE"
}
let parts = msg.payload.split(",")
let lastThree = parts.slice(-3) // get last 3 elements
if (!(lastThree.join(",") === "0,0,0")) {
    //node.warn("** message detected " + part + " " + msg.payload);
    context.set("wipe", 1)        //  <--- here
    msg.wipe = "OVERWRITE"
}

Or am I still missing something?

(Dunno why, but.....)

Here's a big picture of the flow.

Top left, messages arrive and set their respective flow context values.

Directly below: test injections to simulate problems.

To the right of that (bottom middle) is the clock/cycle/counter that cycles 0 - 5.

Middle of the screen is the new block that then sends the message/s to the LEDs.
(Helps if I actually add the picture.)
(Sorry)

Closer view.

Some funky tricks happening.

Yes, I maybe could do it all in the function node.
But I guess at this point, I will K.I.S.S it.

In that case you don't need the check it at all.

Ok. Thanks.

Ok, I'm not sure where/when/if it is really fixed.

The code I posted works WAY better than the original stuff I had.

So as to not drag this on, I'll mark it as solved.

Alas it will be on this post as a lot of stuff has gone on in this thread.
No offence to helpers. I don't want to show bias.

To save having to have to make moderation decisions on long standing contributors can EVERYONE on this thread please just remove/delete ANY off-topic comments - thanks :slight_smile: