# Stuck with how to handle messages

**URL:** <https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635>\
**Category:** General\
**Created:** [10 November 2025 20:04 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635 "2025-11-10T20:04:15Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [10 November 2025 20:04 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/1 "2025-11-10T20:04:15Z")

</div>

I am sorry for the vague name in the SUBJECT field. I am kind of stuck just now.

_The story_  
I have 3 machines all checking 4 things:  
(in no particular order)  
Router  
Uplink  
Internet  
Modem

`Internet` - THE INTERNET. For the sake of an IP, I use 8.8.8.8  
`Uplink` - my PUBLIC IP address. (not static.)  
`Modem` - the ISP _modem_ (to give it a name. I'm not really sure what they're called nowadays, but....)  
`Router` - my router.

They all check these and create a message containing all 4 device names and their status.

So - as an example - this is a message:

```auto
{"topic":"STATUS/ADSL_Link_Status/","payload":{"Who":"TimePi","router":"online","pip":"online","modem":"online","internet":"online"},"qos":0,"retain":false,"_msgid":"d6861cb97bfa8a3e","delay":60000}

```

(and before you bite me for the name, ADSL is a legacy name and I'm not really going to change it just because it is a _wrong_ name.)

There are 3 of these messages sent around between all 3 devices and they ..... _come to a consensus_ of what's going on.

_(with me so far?)_

All well and good at this stage, but if one or two of them disagree with the _LOCAL_ one:  
what happens?

(Good question)

And this is where I'm at.

Alas today I just discovered that one of them wasn't actually sending it's message and I put that code it and now they ARE all sending the messages.

_Where I'm stuck_  
I have 3 machines. None _MORE IMPORTANT THAN THE OTHERS_ which is the first stumbling block.

Q1:  
Does the _LOCAL_ machine have a higher _weight_ than the other two, or do they have a higher weight than it?

Q2:  
(Trying to keep it modular)  
How/WHERE can I assign weights (priorities?) to the messages?  
Assigning them at the local machine fixes their weight throughout the whole triumvirate.

Q3:  
If all 3 ARE the same and things are all OK, `LIME` is the colour.  
If all 3 ARE the same and things are all BAD, `RED` is the colour.  
If all 3 ARE the same and the devices are `UNKNOWN`, `BLACK` is the colour.  
But if 2 don't agree with `LOCAL`...... `GREEN` is the colour.  
I may make it more resolved and if only 1 of the 3 is _GOOD_ then `SPRING GREEN` is the colour.  
That way I can see how things are sitting with the 3 devices and what they _SEE_.  
(Ok, I haven't asked the question yet - sorry.)

This arcs back to Q2. How would I do that?

I won't go any further as it may be a bit much to take on at this stage.

Thoughts?

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [10 November 2025 23:11 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/2 "2025-11-10T23:11:44Z")

</div>

I would have a couple of questions

1. Why would one machine have a different answer to the others?
2. Where is the decision on who is not agreeing being made?

`But if 2 don't agree with LOCAL .....` would appear to define LOCAL as the decision maker.

Why do you need to assign a priority order? If anyone of them disagrees with the others then presumably you have a problem  
What is going to happen (apart from the colour change) if they do not agree?

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [11 November 2025 02:06 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/3 "2025-11-11T02:06:27Z")

</div>

Very good questions.

🙂

I didn't explain it too good because I am not sure how it will a work.

In answer to your questions:  
1 - It has happened now a couple of times in the past few days where one of the three says the internet is not pingable.

2 - That's where I'm kinda stuck. Where.  
At the sending part or the receiving part?  
I think the receiving part would be better, but I'm not sure how to do it.

Why do I need to assign a _Priority_?

Again, I'm not sure.  
Maybe I could just _count_ who says what and act on the majority.  
(But again: I don't know how I would do that.)

What's going to happen:  
Well, in most cases all three will agree and the colour will be LIME or RED. (Maybe BLACK, but that's a whole other story)

If one of them _thinks differently_ then the colour changes so if I happen to be _passing my_ and notice it, I can look into what's happening.

Is that any easier to understand?  
(Thanks.)

The bigger picture of why this is all happening.  
It is just my curiosity to log things.  
Way back when...... I had only one RasPi. It sat there _Happily_ working, but no one was checking it was _Alive_.  
Then came a second one who's job it was to make sure the original one was ok.  
Then the question came on _Who's checking that machine?_  
So I had them checking each other.  
(long story - not important)  
A third machine got involved and so I expanded the system so all three watched one another.  
I then expanded that to check the router, modem, uplink and public IP address.  
For no other reason than it seemed like a good exercise to do at the time.  
And there have been some learning curves explored ITMT.

I hope (and I now see it is/was wrongly) it was working, but recent events have shown me that the things I thought checked one another weren't.

So I'm looking at a bit of a restructure.  
One machine was missing an entire _routine_ for broadcasting the checks to the others.  
(Shock/horror!)

Sorry, this is now getting too long.  
Hoping to hear back.  
Thanks again.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [11 November 2025 02:22 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/4 "2025-11-11T02:22:47Z")

</div>

Just to (maybe) help, here are some screen shots to show you what I'm seeing.

This is the annoying one.

See the two UPLINK messages.

1 yesterday.  
1 today.  
(relatively speaking)

 ![Screenshot from 2025-11-11 13-11-56](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/f/ef73374965f9e5cd84aa1789f0497e0c00b72369.jpeg)

So, what's the problem?

The other two machines.

You see today's but not yesterdays.

 ![Screenshot from 2025-11-11 13-12-20](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/c/ac4642a5911fdcec8380f00326635ef4ddf597ea.jpeg)

And lastly.

 ![Screenshot from 2025-11-11 13-12-45](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/a/bae20f25350e3b56441270fd637726509b6fe95c.jpeg)

You can again see _today's_ but not yesterday's.

Which - to me - means the first (shown) machine is somehow mucking up.

It is on WiFi. But before you blame WiFi dropouts, there is a system for detecting that.

 ![Screenshot from 2025-11-11 13-11-56](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/9/69c4caa8ac9d2a6332e98f9c2e9dbd9978d66add.jpeg)

(Also on the other machines.)

There have been no MQTT comms losses detected other than the one/s show here.

So they don't tally with WiFi drop outs.

To recap:  
~~YESTERDAY'S Uplink failure is the one in question.  
It only showed on one machine.  
(Though, this could be partly due to the fact that the coding wasn't sharing what it saw/sees if the uplink went down, the other two would have complained all the same)~~

The reports are confusing.  
Yesterday 2 machines said the uplink went down and their times concur.  
Today 2 machines said the uplink went down and their times concur, but they are a different two than yesterday's two. (Ok, one is common..... c'mon. There's only 3 machines.)

To me that is even more confusing.

(Just realised: It was NOT the first shown machine that wasn't broadcasting. It was the LAST ONE!)  
If it is confusing, tell me and I'll try to explain it again but in a different way.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [11 November 2025 08:34 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/5 "2025-11-11T08:34:57Z")

</div>

Just to _share_ progress.

This is a `function` node's code to do a better job than what I had to show the state of things.

```js
// 2025-11-11 1618 — Colour logic: local vs remote, with SPRINGGREEN when local offline, RED if all offline

function makeIcon(colour, icon = "fa-bullseye") {
    return `<font color="${colour}"><i class="fa ${icon} fa-2x"></i></font>`
}

// Determine colour for this subsystem based on all three Pis
function getColour(localState, remoteStates) {
    // Check if localState and remoteStates are valid, default to 'offline' if not
    localState = (localState && localState.toLowerCase()) || 'offline'
    remoteStates = remoteStates.map(state => (state && state.toLowerCase()) || 'offline')

    const allStates = [localState, ...remoteStates]

    // If ALL are offline → RED
    if (allStates.every(s => s === "offline")) return "red"

    // If THIS Pi is offline → SPRINGGREEN
    if (localState === "offline") return "springgreen"

    // THIS Pi is online, determine based on remotes
    const onlineCount = remoteStates.filter(s => s === "online").length
    if (onlineCount === 2) return "lime" // all 3 online
    if (onlineCount === 1) return "green" // one other offline

    return "springgreen" // both others offline
}

// --- get or create persistent state ---
let state = context.get("state") || {
    router: {}, pip: {}, modem: {}, uplink: {}
}

// --- parse message ---
const p = msg.payload
if (!p || !p.Who) return null

const who = p.Who // e.g. "TimePi"
const thisPi = global.get("ThisPiName") || "TimePi" // local device name

// rename "internet" → "uplink"
p.uplink = p.internet

// update stored state
for (let key of ["router", "pip", "modem", "uplink"]) {
    if (p[key]) state[key][who] = p[key]
}

// helper: determine colour for one subsystem
function colourFor(subsys) {
    const all = state[subsys]
    const local = all[thisPi]
    const remotes = Object.entries(all)
        .filter(([k]) => k !== thisPi)
        .map(([_, v]) => v)
    return getColour(local, remotes)
}

// compute colours
const routerColour = colourFor("router")
const pipColour = colourFor("pip")
const modemColour = colourFor("modem")
const uplinkColour = colourFor("uplink")

// build 4 outgoing messages
let msg1 = { payload: makeIcon(routerColour), colour: routerColour }
let msg2 = { payload: makeIcon(pipColour), colour: pipColour }
let msg3 = { payload: makeIcon(modemColour), colour: modemColour }
let msg4 = { payload: makeIcon(uplinkColour), colour: uplinkColour }

// save updated state
context.set("state", state)

// optional: show quick status
node.status({
    text: `r:${routerColour} p:${pipColour} m:${modemColour} u:${uplinkColour}`
})

// output
return [msg1, msg2, msg3, msg4]

```

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [11 November 2025 21:06 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/6 "2025-11-11T21:06:02Z")

</div>

Do all three Pi's interrogate the router etc. in the same way?  
If 1 of the Pi's gets a 'not connected' result how many times do they try again before moving on?  
If there is a 'not connected' result do the other Pi's try again?  
Are the UpLink (etc) messages logged with the name of the device that logged them? and is there a consolidated log? (I am going on the thought that since the two screen shots are from different Pi's that the logging is local)

You have a lot of checking going on there, I am going to have to think about my system.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [12 November 2025 02:39 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/7 "2025-11-12T02:39:45Z")

</div>

(Again: Good questions)

Every 20 seconds each pi goes through a routine that pings all 4 IP addresses and reports their ping times.

The 4 messages are then made into one and sent out via MQTT.  
(All 3 machines now do the same, with the same code - 90% the same.)

Anyway.

The message/s are received and then sent into the node posted.  
It then configures/sets the icon colour depending on what's happening.

This is an ongoing thing every 20 seconds.

Yes, all logging is local.

(3 screen shots I hope.) 😉

Nothing exciting really happens. Just me, logging useless stuff.

I am going to add code so that if the IP address starts with a specific number then the icon is also changed to the "WiFi" one indicating that the router has _fallen onto_ the mobile network.

But that is a bit of a side thing in the the scheme at this point.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [12 November 2025 18:25 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/8 "2025-11-12T18:25:38Z")

</div>

There definitely seems to be something happening as I am getting rogue messages the past few days.

To further help anyone interested understand what's going on and/or why here is a couple of bits of code:

This is the scanning code:

```auto
[{"id":"13abcd68.e79bfb","type":"inject","z":"f4651491.221e58","g":"28ee592794c503b8","name":"","repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"Go","payloadType":"str","x":600,"y":160,"wires":[["85c45048.3cbcf8"]]},{"id":"85c45048.3cbcf8","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"check list","func":"const uplinkip = global.get(\"uplink_IP\");\nlet checks = [\n { 'topic': 'modem', 'host': \"192.168.100.1\"},\n { 'topic': 'UpLink', 'host': uplinkip},\n { 'topic': 'router', 'host': \"192.168.17.1\"},\n { 'topic': 'internet', 'host': '8.8.8.8'}\n];\n\nmsg.payload = checks;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":200,"wires":[["53ba88cd.06d308"]]},{"id":"53ba88cd.06d308","type":"ping","z":"f4651491.221e58","g":"28ee592794c503b8","mode":"triggered","name":"Am I online?","host":"","timer":"20","inputs":1,"x":620,"y":240,"wires":[["0b4165813f698b57","42baddf2b729f12f"]]},{"id":"0b4165813f698b57","type":"change","z":"f4651491.221e58","g":"28ee592794c503b8","name":"**2024 109 21","rules":[{"t":"move","p":"ping.topic","pt":"msg","to":"device","tot":"msg"},{"t":"move","p":"ping.host","pt":"msg","to":"IP","tot":"msg"},{"t":"delete","p":"ping","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":725,"y":240,"wires":[["6642834ad4526b6a"]],"l":false,"info":"changed from `device` to `_topic`"},{"id":"6642834ad4526b6a","type":"junction","z":"f4651491.221e58","g":"28ee592794c503b8","x":760,"y":240,"wires":[["8975af459e32a828","ebb24c19.2c9048","5b4966d5a711779c"]]},{"id":"8975af459e32a828","type":"junction","z":"f4651491.221e58","g":"28ee592794c503b8","x":240,"y":320,"wires":[["4dd6d0b46d37ba0d","b4f1ee1d8d012603","6f4156c2.d6fc","aecd4e09.96f4b"]]},{"id":"6f4156c2.d6fc","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Router","func":"let msg1 = {};\nconst _topic = '192.168.17.1';\nif (msg.topic == _topic)\n{\n //node.warn(msg.payload);\n if (msg.payload > 0)\n {\n node.status({fill:\"green\",shape:\"dot\",text:\"Connected\"});\n// msg.link = \"router\";\n msg.payload = {\"device\":\"router\",\"Status\":\"online\"}\n msg1.payload = true;\n }\n else\n {\n node.status({fill:\"red\",shape:\"dot\",text:\"Dis-Connected\"});\n msg.link = \"router\";\n// msg.payload = false;\n msg.payload = {\"device\":\"router\",\"Status\":\"offline\"}\n msg1.payload = false;\n }\n return [msg,msg1];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":320,"wires":[["216ee71197f64362"],["4e60e974a200c626"]]},{"id":"aecd4e09.96f4b","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Uplink","func":"let msg1 = {};\nconst _topic = global.get(\"uplink_IP\");\nif (msg.topic == _topic)\n{\n //node.warn(msg.payload);\n if (msg.payload > 0)\n {\n node.status({fill:\"green\",shape:\"dot\",text:\"Connected\"});\n// msg.link = \"router\";\n msg.payload = {\"device\":\"pip\",\"Status\":\"online\"}\n msg1.payload = true\n }\n else\n {\n node.status({fill:\"red\",shape:\"dot\",text:\"Dis-Connected\"});\n msg.link = \"router\";\n// msg.payload = false;\n msg.payload = {\"device\":\"pip\",\"Status\":\"offline\"}\n msg1.payload = false\n }\n return [msg,msg1];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":370,"wires":[["216ee71197f64362"],["4e60e974a200c626"]]},{"id":"b4f1ee1d8d012603","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Modem","func":"const _topic = '192.168.100.1';\nif (msg.topic == _topic)\n{\n //node.warn(msg.payload);\n if (msg.payload > 0)\n {\n node.status({fill:\"green\",shape:\"dot\",text:\"Connected\"});\n// msg.link = \"router\";\n msg.payload = {\"device\":\"modem\",\"Status\":\"online\"}\n }\n else\n {\n node.status({fill:\"red\",shape:\"dot\",text:\"Dis-Connected\"});\n msg.link = \"router\";\n// msg.payload = false;\n msg.payload = {\"device\":\"modem\",\"Status\":\"offline\"}\n }\n return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":420,"wires":[["216ee71197f64362"]]},{"id":"4dd6d0b46d37ba0d","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Internet","func":"const _topic = '8.8.8.8';\nif (msg.topic == _topic)\n{\n //node.warn(msg.payload);\n if (msg.payload > 0)\n {\n node.status({fill:\"green\",shape:\"dot\",text:\"Connected\"});\n// msg.link = \"router\";\n msg.payload = {\"device\":\"internet\",\"Status\":\"online\"}\n }\n else\n {\n node.status({fill:\"red\",shape:\"dot\",text:\"Dis-Connected\"});\n msg.link = \"router\";\n// msg.payload = false;\n msg.payload = {\"device\":\"internet\",\"Status\":\"offline\"}\n }\n return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":470,"wires":[["216ee71197f64362"]]},{"id":"216ee71197f64362","type":"link out","z":"f4651491.221e58","g":"28ee592794c503b8","name":"link out 29","mode":"link","links":["4cc73847426b0839"],"x":445,"y":470,"wires":[]},{"id":"4cc73847426b0839","type":"link in","z":"f4651491.221e58","g":"28ee592794c503b8","name":"link in 36","links":["216ee71197f64362"],"x":575,"y":470,"wires":[["2bb3411b18df8237"]]},{"id":"2bb3411b18df8237","type":"delay","z":"f4651491.221e58","g":"28ee592794c503b8","name":"rate limit","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":645,"y":470,"wires":[["be218399df7f8c83","a35a186da6678f9b"]],"l":false},{"id":"a35a186da6678f9b","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Make ONE message *","func":"// Works in Node-RED 3.0+\n\n(async () => {\n\n let A\n let B\n let C\n let D\n let counter = context.get(\"counter\") || 0\n\n const device_name = global.get(\"myDeviceName\")\n\n if (msg.topic == \"NEWDAY\") {\n node.send(msg)\n return\n }\n\n if (msg.payload == \"RESET\") {\n context.set(\"counter\", 0)\n context.set(\"rounter_status\", \"unknown\")\n context.set(\"pip_status\", \"unknown\")\n context.set(\"modem_status\", \"unknown\")\n context.set(\"internet_status\", \"unknown\")\n node.status({ text: \"RESET\" })\n return\n }\n\n let device = msg.payload.device\n let status = msg.payload.Status\n\n if (device == \"router\") {\n context.set(\"router\", 1)\n context.set(\"router_status\", status)\n context.set(\"counter\", counter + 1)\n node.status({ fill: \"green\", text: \"router\" })\n }\n\n if (device == \"pip\") {\n context.set(\"pip\", 1)\n context.set(\"pip_status\", status)\n context.set(\"counter\", counter + 1)\n node.status({ fill: \"red\", text: \"Uplink\" })\n }\n\n if (device == \"modem\") {\n context.set(\"modem\", 1)\n context.set(\"modem_status\", status)\n context.set(\"counter\", counter + 1)\n node.status({ fill: \"yellow\", text: \"modem\" })\n }\n\n if (device == \"internet\") {\n context.set(\"internet\", 1)\n context.set(\"internet_status\", status)\n context.set(\"counter\", counter + 1)\n node.status({ fill: \"blue\", text: \"internet\" })\n }\n\n A = context.get(\"router_status\")\n B = context.get(\"pip_status\")\n C = context.get(\"modem_status\")\n D = context.get(\"internet_status\")\n counter = context.get(\"counter\")\n\n if (counter == 4) {\n\n msg.payload = {\n \"Who\": device_name,\n \"router\": A,\n \"pip\": B,\n \"modem\": C,\n \"internet\": D\n }\n\n context.set(\"counter\", 0)\n\n // I need a 1 second delay here.\n await new Promise(resolve => setTimeout(resolve, 1000))\n node.status({ fill: \"grey\", text: \"reset\" })\n\n node.send(msg)\n return\n }\n\n})()\nreturn\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":470,"wires":[["4b53eb7c1b6415fe","6579ac1985f5a613"]],"info":"2024 09 05\nchanged line 62\nfrom `msg.payload.device`\nto `msg.payload.Who`\n\n2024 09 21\n==\nBig rewrite."},{"id":"6579ac1985f5a613","type":"gate","z":"f4651491.221e58","g":"28ee592794c503b8","name":"B","controlTopic":"control","defaultState":"closed","openCmd":"B","closeCmd":"A","toggleCmd":"toggle","defaultCmd":"default","statusCmd":"","persist":false,"x":1035,"y":470,"wires":[["92590e333b73dc4e"]],"l":false},{"id":"92590e333b73dc4e","type":"mqtt out","z":"f4651491.221e58","g":"28ee592794c503b8","name":"","topic":"STATUS/ADSL_Link_Status/","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"1bbfcdd.2d24532","x":1230,"y":470,"wires":[]},{"id":"ebb24c19.2c9048","type":"function","z":"f4651491.221e58","g":"28ee592794c503b8","name":"Check","func":"const time_ = new Date().toLocaleString('en-AU', { hour12: false })\n\nlet Modem = context.get('Modem') || 0\nlet Uplink = context.get('UpLink') || 0\n//node.warn(msg.device)\nif (msg.device == \"router\") {\n //node.warn(\"Modem test\")\n //node.warn(\"Status is \" + msg.payload) // Number if pinged.\n //if (msg.payload == \"Line Good\")\n if (msg.payload > 0) {\n context.set('Modem', 1)\n if (Uplink === 0) {\n node.status({ fill: \"yellow\", shape: \"dot\", text: \"Modem Seen\" })\n }\n msg = { payload: 'Online', device: 'Modem', who: global.get(\"myDeviceName\"), time: time_ }\n\n // node.warn(*** modem good ***)\n\n //\n // Construct msg.payload to say modem seen and message from TelePi.\n //\n return msg\n }\n else {\n context.set('Modem', 0)\n node.status({ fill: \"black\", shape: \"dot\", text: \"Modem NOT Seen\" })\n msg = { payload: 'OffLine', device: 'Modem', who: global.get(\"myDeviceName\"), time: time_ }\n //\n // Construct msg.payload to say modem not seen and message from TelePi.\n //\n return msg\n }\n}\nif (msg.device == \"UpLink\") {\n if (Modem === 1) {\n if (msg.payload > 0) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"UpLink and router Ok\" })\n msg = { payload: 'Online', device: 'UpLink', who: global.get(\"myDeviceName\"), time: time_ }\n context.set(\"UpLink\", 1)\n\n // node.warn(**** uplink good **** )\n //\n // This needs modifying to say it is from TelePi.\n //\n return msg\n }\n else {\n node.status({ fill: \"red\", shape: \"dot\", text: \"UpLink Down\" })\n msg = { payload: 'Offline', device: 'UpLink', who: global.get(\"myDeviceName\"), time: time_ }\n context.set(\"UpLink\", 0)\n //\n // This needs modifying to say it is from TelePi.\n //\n return msg\n }\n }\n else {\n node.status({ fill: \"grey\", shape: \"dot\", text: \"Unknown\" })\n context.set('MODEM', 0)\n //\n // This needs modifying to say it is from TelePi.\n //\n msg = { payload: 'UNKNOWN', device: 'Uplink', who: global.get(\"myDeviceName\"), time: time_ }\n return msg\n }\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":830,"y":290,"wires":[["ca6954d2.d7de18","c14f8ba9.f016e8"]]},{"id":"1bbfcdd.2d24532","type":"mqtt-broker","name":"TIMEPI MQTT","broker":"192.168.17.39","port":"1883","clientid":"","autoConnect":true,"usetls":false,"compatmode":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"SOM","birthQos":"2","birthRetain":"false","birthPayload":"TelePi Comms UP","birthMsg":{},"closeTopic":"EOM","closeQos":"0","closeRetain":"false","closePayload":"TelePi shutting DOWN","closeMsg":{},"willTopic":"EOM","willQos":"0","willRetain":"false","willPayload":"TelePi Comms FAILURE","willMsg":{},"sessionExpiry":""}]

```

This is the main bit. As you may see there are other parts/branches going elsewhere doing their thing. I included the `function` node as it is handy to see as it too indicates the statuses of the devices.

Picture to help understand too.

 ![Screenshot from 2025-11-13 05-13-26](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/f/3fc8b8f4f5d27c2f5912bcee2d6f001e7cadb8fa.png)

This is the decoding code:

```auto
[{"id":"f7b1610d.876c5","type":"mqtt in","z":"f4651491.221e58","g":"0281319e741d201a","name":"Internet link status","topic":"STATUS/ADSL_Link_Status/#","qos":"2","datatype":"auto","broker":"1bbfcdd.2d24532","nl":false,"rap":false,"inputs":0,"x":310,"y":1460,"wires":[["d50b4d6.59dc73"]]},{"id":"d50b4d6.59dc73","type":"json","z":"f4651491.221e58","g":"0281319e741d201a","name":"Router/Uplink status","property":"payload","action":"","pretty":false,"x":295,"y":1400,"wires":[["b0db4ba59311ae7a"]],"l":false},{"id":"b0db4ba59311ae7a","type":"change","z":"f4651491.221e58","g":"0281319e741d201a","name":"get delay time","rules":[{"t":"set","p":"delay","pt":"msg","to":"$globalContext(\"SCAN_TIME\") * 3","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":355,"y":1400,"wires":[["5d04fddb689e7492"]],"l":false},{"id":"5d04fddb689e7492","type":"gate","z":"f4651491.221e58","g":"0281319e741d201a","name":"Master STOP","controlTopic":"CONTROL3","defaultState":"open","openCmd":"GO","closeCmd":"STOP","toggleCmd":"toggle","defaultCmd":"default","statusCmd":"status","persist":false,"storeName":"memory","x":415,"y":1400,"wires":[["ef4ffc8e4aa932d3"]],"l":false},{"id":"2d5448ed.f7eda","type":"switch","z":"f4651491.221e58","g":"0281319e741d201a","name":"Whic device's message","property":"payload.Who","propertyType":"msg","rules":[{"t":"eq","v":"BedPi","vt":"str"},{"t":"eq","v":"TelePi","vt":"str"},{"t":"eq","v":"TimePi","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":685,"y":1400,"wires":[["7c425021.22e4b8","76d8311c4b394f6b"],["8d6ff708.0509a8","76d8311c4b394f6b"],["a95028815942d0e0","e4f887a60fe797e5","76d8311c4b394f6b"]],"l":false},{"id":"7c425021.22e4b8","type":"trigger","z":"f4651491.221e58","g":"0281319e741d201a","name":"BedPi","op1":"","op2":"offline","op1type":"pay","op2type":"str","duration":"80","extend":true,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":810,"y":1330,"wires":[["2c25412de15859fd"]]},{"id":"8d6ff708.0509a8","type":"trigger","z":"f4651491.221e58","g":"0281319e741d201a","name":"TelePi","op1":"","op2":"offline","op1type":"pay","op2type":"str","duration":"80","extend":true,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":810,"y":1380,"wires":[["0cdf66dcfb1d2a84"]]},{"id":"e4f887a60fe797e5","type":"trigger","z":"f4651491.221e58","g":"0281319e741d201a","name":"TimePi","op1":"","op2":"offline","op1type":"pay","op2type":"str","duration":"80","extend":true,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":810,"y":1430,"wires":[["025688311b9ca9ed"]]},{"id":"025688311b9ca9ed","type":"function","z":"f4651491.221e58","g":"0281319e741d201a","name":"TimePi","func":"msg = { \"topic\": \"STATUS/ADSL_Link_Status\", \"payload\": { \"Who\": \"TimePi\", \"Modem\": \"Offline\", \"UpLink\": \"Offline\" } }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":905,"y":1430,"wires":[["6176f7af89e288f4"]],"l":false},{"id":"0cdf66dcfb1d2a84","type":"function","z":"f4651491.221e58","g":"0281319e741d201a","name":"TelePi","func":"msg = { \"topic\": \"STATUS/ADSL_Link_Status\", \"payload\": { \"Who\": \"TelePi\", \"Modem\": \"Offline\", \"UpLink\": \"Offline\" } }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":905,"y":1380,"wires":[["6176f7af89e288f4"]],"l":false},{"id":"2c25412de15859fd","type":"function","z":"f4651491.221e58","g":"0281319e741d201a","name":"BedPi","func":"msg = { \"topic\": \"STATUS/ADSL_Link_Status\", \"payload\": { \"Who\": \"BedPi\", \"Modem\": \"Offline\", \"UpLink\": \"Offline\" } }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":905,"y":1330,"wires":[["6176f7af89e288f4"]],"l":false},{"id":"6176f7af89e288f4","type":"junction","z":"f4651491.221e58","g":"0281319e741d201a","x":980,"y":1400,"wires":[["b7dfa060.6a4218"]]},{"id":"b7dfa060.6a4218","type":"link out","z":"f4651491.221e58","g":"0281319e741d201a","name":"","links":["9ed8578c5ce3be0b"],"x":1035,"y":1400,"wires":[]},{"id":"9ed8578c5ce3be0b","type":"link in","z":"f4651491.221e58","g":"625538364d766902","name":"","links":["b7dfa060.6a4218"],"x":1185,"y":1400,"wires":[["e990f055317a6d64","941bb21fce19482b"]]},{"id":"941bb21fce19482b","type":"function","z":"f4651491.221e58","g":"625538364d766902","name":"Modem/Uplink status Working 2025 11 11","func":"// 2025-11-11 2045 — Colour logic: local vs remote, with SPRINGGREEN when local offline, RED if all offline, and BLACK for unknown\n\nfunction makeIcon(colour, icon = \"fa-bullseye\") {\n return `<font color=\"${colour}\"><i class=\"fa ${icon} fa-2x\"></i></font>`\n}\n\n// Determine colour for this subsystem based on all three Pis\nfunction getColour(localState, remoteStates) {\n // Check if localState and remoteStates are valid, default to 'offline' or 'unknown' if not\n localState = (localState && localState.toLowerCase()) || 'offline'\n remoteStates = remoteStates.map(state => (state && state.toLowerCase()) || 'offline')\n\n // If ALL are 'unknown' → BLACK\n if ([localState, ...remoteStates].every(s => s === \"unknown\")) return \"black\"\n\n // If ALL are offline → RED\n if ([localState, ...remoteStates].every(s => s === \"offline\")) return \"red\"\n\n // If THIS Pi is offline → SPRINGGREEN\n if (localState === \"offline\") return \"springgreen\"\n\n // THIS Pi is online, determine based on remotes\n const onlineCount = remoteStates.filter(s => s === \"online\").length\n if (onlineCount === 2) return \"lime\" // all 3 online\n if (onlineCount === 1) return \"green\" // one other offline\n\n return \"springgreen\" // both others offline\n}\n\n// --- get or create persistent state ---\nlet state = context.get(\"state\") || {\n router: {}, pip: {}, modem: {}, uplink: {}\n}\n\n// --- parse message ---\nconst p = msg.payload\nif (!p || !p.Who) return null\n\nconst who = p.Who // e.g. \"TimePi\"\nconst thisPi = global.get(\"ThisPiName\") || \"TimePi\" // local device name\n\n// rename \"internet\" → \"uplink\"\np.uplink = p.internet\n\n// update stored state\nfor (let key of [\"router\", \"pip\", \"modem\", \"uplink\"]) {\n if (p[key]) state[key][who] = p[key]\n}\n\n// helper: determine colour for one subsystem\nfunction colourFor(subsys) {\n const all = state[subsys]\n const local = all[thisPi]\n const remotes = Object.entries(all)\n .filter(([k]) => k !== thisPi)\n .map(([_, v]) => v)\n return getColour(local, remotes)\n}\n\n// compute colours\nconst routerColour = colourFor(\"router\")\nconst pipColour = colourFor(\"pip\")\nconst modemColour = colourFor(\"modem\")\nconst uplinkColour = colourFor(\"uplink\")\n\n// build 4 outgoing messages\nlet msg1 = { payload: makeIcon(routerColour), colour: routerColour }\nlet msg2 = { payload: makeIcon(pipColour), colour: pipColour }\nlet msg3 = { payload: makeIcon(modemColour), colour: modemColour }\nlet msg4 = { payload: makeIcon(uplinkColour), colour: uplinkColour }\n\n// save updated state\ncontext.set(\"state\", state)\n\n// optional: show quick status\nnode.status({\n text: `r:${routerColour} p:${pipColour} m:${modemColour} u:${uplinkColour}`\n})\n\n// output\nreturn [msg1, msg2, msg3, msg4]\n","outputs":4,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1520,"y":1400,"wires":[["78bee52b04dedd1f","8729ed4697d99590"],["11e761b006a3855f","61107b78e705a231"],["1a80600afcc60d67"],["9cef804b9ddfc40a"]],"outputLabels":["router","pip","modem (Telstra)","internet"],"info":"2025 11 11\n==\n| This Pi | Remote 1 | Remote 2 | Colour | Meaning |\n| ------- | -------- | -------- | --------------- | ----------------------- |\n| online | online | online | **LIME** | All OK |\n| online | online | offline | **GREEN** | One other offline |\n| online | offline | offline | **SPRINGGREEN** | Only this Pi online |\n| offline | (any) | (any) | **SPRINGGREEN** | Local subsystem offline |\n| offline | offline | offline | **RED** | All Pis offline |\n\n\n\n2025 07 29\n==\nModified code.\nMade functions for colours.\nIf public_IP starts with 1.x icon is wifi\n\n\n2024 09 21\n==\n\nBig restructure\nadded startup code to wipe values\n"},{"id":"1bbfcdd.2d24532","type":"mqtt-broker","name":"TIMEPI MQTT","broker":"192.168.17.39","port":"1883","clientid":"","autoConnect":true,"usetls":false,"compatmode":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"SOM","birthQos":"2","birthRetain":"false","birthPayload":"TelePi Comms UP","birthMsg":{},"closeTopic":"EOM","closeQos":"0","closeRetain":"false","closePayload":"TelePi shutting DOWN","closeMsg":{},"willTopic":"EOM","willQos":"0","willRetain":"false","willPayload":"TelePi Comms FAILURE","willMsg":{},"sessionExpiry":""}]

```

I didn't include my `subflow` (advblocker) as it isn't really important and I don't want to pollute the code. Just wire round it.

 ![Screenshot from 2025-11-13 05-15-47](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/a/0aef6cb020761ceaccfe8d8c3ea413c8d3a11c26.png)

And again, there is more to the code, but for the sake of being as brief as possible, nothing else is really important. (AFAIK)

These are the parts that do the _Heavy lifting_.

_TODAY_ I got up and all three machines said the uplink was down.

Yet looking at the actual device: it wasn't.  
The IP address was ok, and it cleared when I resent the IP address to all machines.  
So something is happening there. But I'm not seeing anything to indicate a problem.  
(And ok: I may not - probably didn't post that part of the code. No worries. But just saying.)

Not wanting to go too far off topic, but from a previous day when this sort of happened but only 1 machine said the internet was down.

When I went to a terminal and tried to `ping` (sorry `traceroute`) the IP address it didn't go too far.  
I can't remember the exact IP addresses, but it got to the route (I think) and became 127.0.0.x I think.

Oh dear!  
I just saw that my IP address WAS changed.

 ![Screenshot from 2025-11-13 05-34-24](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/5/15e03dcce347b49b255d11ae1d8d4e36144a6df9.jpeg)

But this reflects when I rebroadcasted the nw IP address. NOT when it changed.  
Which was (Probably) at `03:46:31` when the uplink went offline.  
Ok, yeah. That's when it went off line, not when I got the new IP address.

I'll have to look into that part too.

 ![Screenshot from 2025-11-13 05-37-48](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/7/97cbadb7f90d16031a866b302898195bacbbb523.jpeg)

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [10 February 2026 18:26 UTC](https://discourse.nodered.org/t/stuck-with-how-to-handle-messages/99635/9 "2026-02-10T18:26:21Z")

</div>

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