# A little tip for fellow Node Developers

**URL:** <https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964>\
**Category:** Developing Nodes\
**Tags:** comms-api\
**Created:** [4 July 2025 19:05 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964 "2025-07-04T19:05:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [4 July 2025 19:05 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/1 "2025-07-04T19:05:41Z")

</div>

My Zwave Node is going through a massive cleanse (v10), and in doing so optimising A LOT.  
My node subscribes to 20+ comm API messages from the runtime counterparts, to facilitate the UI

I needed a way to shrink this and make it more manageable

- Subscribing
- Unsubscribing (Yes!!! I clean things up 😉)

I present a little snippet for you all to benefit from - for me it works really well!

Enjoy

```js
const setSubscription = (subscribe) => {
		const Hooks = [
			{ address: `zwave-js/ui/${networkId}/status`, method: commsStatus },
			{ address: `zwave-js/ui/${networkId}/s2/grant`, method: commsGrant },
			{ address: `zwave-js/ui/${networkId}/s2/dsk`, method: commsDSK },
			{ Another },
			{ Another },
			{ Another * 20 more }
		];

		switch (subscribe) {
			case true:
				Hooks.forEach((H) => {
					RED.comms.subscribe(H.address, H.method);
				});
				break;

			case false:
				Hooks.forEach((H) => {
					RED.comms.unsubscribe(H.address, H.method);
				});
                break;
		}
}

/* Example */
setSubscription(true | false)

/* Example responder */
const commsDSK = (topic, data) =>{
   // do stuff
}

```

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [4 July 2025 19:25 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/2 "2025-07-04T19:25:18Z")

</div>

Full example:

```js
const setSubscription = (subscribe) => {
		const Hooks = [
			{ address: `zwave-js/ui/${networkId}/status`, method: commsStatus },
			{ address: `zwave-js/ui/${networkId}/s2/grant`, method: commsGrant },
			{ address: `zwave-js/ui/${networkId}/s2/dsk`, method: commsDSK },
			{ address: `zwave-js/ui/${networkId}/nodes/added`, method: commsNodeAdded },
			{ address: `zwave-js/ui/${networkId}/nodes/removed`, method: commsNodeRemoved },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewstarted`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewfailed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/ready`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/sleep`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/awake`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/dead`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/controller/slave/dsk`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/joined`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/left`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/nodes/valueadded`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/nodes/valueupdate`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/backupprogress`, method: commsNVMBackupProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/restoreprogress`, method: commsNVMRestoreProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/progress`, method: commsCFirmwareReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/finished`, method: commsCFirmwareReport }
		];

		switch (subscribe) {
			case true:
				Hooks.forEach((H) => {
					RED.comms.subscribe(H.address, H.method);
				});
				break;
			case false:
				Hooks.forEach((H) => {
					RED.comms.unsubscribe(H.address, H.method);
				});
                break;
		}
};

```

Usage

```auto
setSubscription(true | false)

```

again - enjoy

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [4 July 2025 20:00 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/3 "2025-07-04T20:00:39Z")

</div>

> [@marcus-j-davies](#):
>
> ```auto
> const setSubscription = (subscribe) => {
> const Hooks = [
> { address: `zwave-js/ui/${networkId}/status`, method: commsStatus },
> { address: `zwave-js/ui/${networkId}/s2/grant`, method: commsGrant },
> { address: `zwave-js/ui/${networkId}/s2/dsk`, method: commsDSK },
> { address: `zwave-js/ui/${networkId}/nodes/added`, method: commsNodeAdded },
> { address: `zwave-js/ui/${networkId}/nodes/removed`, method: commsNodeRemoved },
> { address: `zwave-js/ui/${networkId}/nodes/interviewstarted`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/interviewfailed`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/interviewed`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/ready`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/sleep`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/awake`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/nodes/dead`, method: commsNodeState },
> { address: `zwave-js/ui/${networkId}/controller/slave/dsk`, method: commsHandleSlaveOps },
> { address: `zwave-js/ui/${networkId}/controller/slave/joined`, method: commsHandleSlaveOps },
> { address: `zwave-js/ui/${networkId}/controller/slave/left`, method: commsHandleSlaveOps },
> { address: `zwave-js/ui/${networkId}/nodes/valueadded`, method: commsHandleValueUpdate },
> { address: `zwave-js/ui/${networkId}/nodes/valueupdate`, method: commsHandleValueUpdate },
> { address: `zwave-js/ui/${networkId}/controller/nvm/backupprogress`, method: commsNVMBackupProgressReport },
> { address: `zwave-js/ui/${networkId}/controller/nvm/restoreprogress`, method: commsNVMRestoreProgressReport },
> { address: `zwave-js/ui/${networkId}/controller/firmwareupdate/progress`, method: commsCFirmwareReport },
> { address
> 
> ```

You could remove the switch

```js
const setSubscription = (subscribe) => {
		const Hooks = [
			{ address: `zwave-js/ui/${networkId}/status`, method: commsStatus },
			{ address: `zwave-js/ui/${networkId}/s2/grant`, method: commsGrant },
			{ address: `zwave-js/ui/${networkId}/s2/dsk`, method: commsDSK },
			{ address: `zwave-js/ui/${networkId}/nodes/added`, method: commsNodeAdded },
			{ address: `zwave-js/ui/${networkId}/nodes/removed`, method: commsNodeRemoved },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewstarted`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewfailed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/ready`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/sleep`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/awake`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/dead`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/controller/slave/dsk`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/joined`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/left`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/nodes/valueadded`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/nodes/valueupdate`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/backupprogress`, method: commsNVMBackupProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/restoreprogress`, method: commsNVMRestoreProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/progress`, method: commsCFirmwareReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/finished`, method: commsCFirmwareReport }
		];
        const op = RED.comms[subscribe ? "subscribe" : "unsubscribe"];

	Hooks.forEach((H) => op(H.address, H.method));
				
		}
};

```

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [4 July 2025 20:01 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/4 "2025-07-04T20:01:28Z")

</div>

Evan smaller - Thanks @AllanOricil

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [4 July 2025 20:08 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/5 "2025-07-04T20:08:17Z")

</div>

> [@AllanOricil](#):
>
> `const op = RED.comms[subscribe ? "subscribe" : "unsubscribe"];`

"and this... is... to go... even further beyond" (ssj3 ref)

```js
const op = RED.comms[(subscribe ? "" : "un") + "subscribe"];

```

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [4 July 2025 21:22 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/6 "2025-07-04T21:22:31Z")

</div>

@AllanOricil

Went with your 1st.

For all - makes managing your comm subscriptions easier to manage.

```js
const setSubscription = (subscribe) => {
		const Hooks = [
			{ address: `zwave-js/ui/${networkId}/status`, method: commsStatus },
			{ address: `zwave-js/ui/${networkId}/s2/grant`, method: commsGrant },
			{ address: `zwave-js/ui/${networkId}/s2/dsk`, method: commsDSK },
			{ address: `zwave-js/ui/${networkId}/nodes/added`, method: commsNodeAdded },
			{ address: `zwave-js/ui/${networkId}/nodes/removed`, method: commsNodeRemoved },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewstarted`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewfailed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/interviewed`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/ready`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/sleep`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/awake`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/nodes/dead`, method: commsNodeState },
			{ address: `zwave-js/ui/${networkId}/controller/slave/dsk`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/joined`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/controller/slave/left`, method: commsHandleSlaveOps },
			{ address: `zwave-js/ui/${networkId}/nodes/valueadded`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/nodes/valueupdate`, method: commsHandleValueUpdate },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/backupprogress`, method: commsNVMBackupProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/nvm/restoreprogress`, method: commsNVMRestoreProgressReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/progress`, method: commsCFirmwareReport },
			{ address: `zwave-js/ui/${networkId}/controller/firmwareupdate/finished`, method: commsCFirmwareReport }
		];

		const op = RED.comms[subscribe ? 'subscribe' : 'unsubscribe'];
		Hooks.forEach((H) => op(H.address, H.method));
};

```

Example

```auto
setSubscription(true | false)

```

Just add all your mappings

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [4 July 2025 21:27 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/7 "2025-07-04T21:27:32Z")

</div>

If you named your functions `comms_s2_grant`, `comms_s2_dsk`, `comms_nodes_added` you could have done this in a maintenace free way:

```auto
const setSubscription = (subscribe) => {
	const op = RED.comms[subscribe ? 'subscribe' : 'unsubscribe'];
	Object.entries(this)
		.filter(([key, val]) => typeof val === 'function' && key.startsWith('comms_'))
		.forEach(([key, handler]) => {
			const path = key.split("_").slice(1).join('/') // eg controller/slave/dsk
			op(`zwave-js/ui/${networkId}/${path}`, handler)
		})
}

```

Any future method you add that needs hooking up, just name it `comms_this_that()`

_assumptions about functions being iin `this` scope were made - but hopefully you get the idea_

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [4 July 2025 21:35 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/8 "2025-07-04T21:35:46Z")

</div>

I thought we were alright @Steve-Mcl, then you come in and undermime my work, and clever thinking!

😜

Nice! - I do play with the approaches you wrote every so often, I saw low hanging fruit, and went for it.

But Nice! maybe I could optimise it further later with that - thank you 🙏

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [5 July 2025 08:10 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/9 "2025-07-05T08:10:16Z")

</div>

> [@marcus-j-davies](#):
>
> then you come in and undermime my work, and clever thinking!

You do know that anytime now, someone's gonna post a 1 line jsonata solution for you....

> [@marcus-j-davies](#):
>
> I do play with the approaches you wrote

We all do. I learn so much from guys like @Steve-Mcl who make nice forum contributions.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [5 July 2025 10:06 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/10 "2025-07-05T10:06:17Z")

</div>

> [@Paul-Reed](#):
>
> We all do. I learn so much from guys like @Steve-Mcl who make nice forum contributions.

The joys of working full-time with node.js/JavaScript. 😃 The rest of us plod along, slowly learning over the years. But then, that's a major part of the joy for me at least! 🧙

---

<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:** [3 September 2025 10:07 UTC](https://discourse.nodered.org/t/a-little-tip-for-fellow-node-developers/97964/11 "2025-09-03T10:07:01Z")

</div>

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