From 008420653fcec2a7aa81ead924c0ad686f91984b Mon Sep 17 00:00:00 2001 From: Florian Gail Date: Fri, 10 Jul 2026 15:59:51 +0200 Subject: [PATCH 1/2] Switch observed universe at runtime via msg.universe Add an input to the sacn-in node so the observed universe can be changed at runtime. On an incoming msg.universe (integer 1-63999) the node stops listening on the current universe (removeUniverse) and starts listening on the new one (addUniverse), drops the stale cache and updates the node status. Invalid values warn and are ignored; an unchanged value is a no-op. Document the new input in docs.html and rebuild dist. --- dist/nodes/sacn-in/sacn-in.html | 11 ++++++- dist/nodes/sacn-in/sacn-in.js | 35 ++++++++++++++++++++++ src/nodes/sacn-in/docs.html | 10 +++++++ src/nodes/sacn-in/init.ts | 2 +- src/nodes/sacn-in/sacn-in.ts | 53 +++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 2 deletions(-) diff --git a/dist/nodes/sacn-in/sacn-in.html b/dist/nodes/sacn-in/sacn-in.html index 22cd7ee..192f3ce 100644 --- a/dist/nodes/sacn-in/sacn-in.html +++ b/dist/nodes/sacn-in/sacn-in.html @@ -75,6 +75,15 @@

Configuration

Port number
Network port to listen on. Defaults to 5568.
+

Inputs

+
+
universe number
+
+ Switches the observed universe at runtime, 1 to 63999. The node stops + listening on the previous universe and starts listening on the new one. Invalid values are + ignored and produce a warning. +
+

Outputs

The properties emitted depend on the selected mode.

Passthrough mode

@@ -132,7 +141,7 @@

References

required: true, }, }, - inputs: 0, + inputs: 1, outputs: 1, paletteLabel: "sACN in", icon: "font-awesome/fa-lightbulb-o", diff --git a/dist/nodes/sacn-in/sacn-in.js b/dist/nodes/sacn-in/sacn-in.js index d4ecbbc..d8f5005 100644 --- a/dist/nodes/sacn-in/sacn-in.js +++ b/dist/nodes/sacn-in/sacn-in.js @@ -6,9 +6,11 @@ class NodeHandler { config; data = new Map(); sACN; + currentUniverse; constructor(node, config) { this.node = node; this.config = config; + this.currentUniverse = config.universe; const options = { universes: [config.universe], reuseAddr: config.reuseAddress !== undefined ? config.reuseAddress : true, @@ -65,6 +67,39 @@ class NodeHandler { }); }); } + this.node.on("input", (msg) => { + this.handleUniverseChange(msg); + }); + this.setStatus(); + } + setStatus() { + this.node.status({ + fill: "green", + shape: "dot", + text: `Universe ${this.currentUniverse}`, + }); + } + parseUniverse(value) { + const universe = typeof value === "string" ? parseInt(value, 10) : value; + if (typeof universe !== "number" || !Number.isInteger(universe) || universe < 1 || universe > 63999) { + return undefined; + } + return universe; + } + handleUniverseChange(msg) { + const universe = this.parseUniverse(msg.universe); + if (universe === undefined) { + this.node.warn(`The given "universe"-property "${msg.universe}" (${typeof msg.universe}) is invalid or not between 1 and 63999.`); + return; + } + if (universe === this.currentUniverse) { + return; + } + this.sACN.removeUniverse(this.currentUniverse); + this.sACN.addUniverse(universe); + this.data?.delete(this.currentUniverse); + this.currentUniverse = universe; + this.setStatus(); } getNulledUniverse() { const universe = {}; diff --git a/src/nodes/sacn-in/docs.html b/src/nodes/sacn-in/docs.html index f74b04c..ef414e3 100644 --- a/src/nodes/sacn-in/docs.html +++ b/src/nodes/sacn-in/docs.html @@ -27,6 +27,16 @@

Configuration

Network port to listen on. Defaults to 5568.
+

Inputs

+
+
universe number
+
+ Switches the observed universe at runtime, 1 to 63999. The node stops + listening on the previous universe and starts listening on the new one. Invalid values are + ignored and produce a warning. +
+
+

Outputs

The properties emitted depend on the selected mode.

diff --git a/src/nodes/sacn-in/init.ts b/src/nodes/sacn-in/init.ts index e5f5ce5..ca73efe 100644 --- a/src/nodes/sacn-in/init.ts +++ b/src/nodes/sacn-in/init.ts @@ -38,7 +38,7 @@ const def: EditorNodeDef = { required: true, }, }, - inputs: 0, + inputs: 1, outputs: 1, paletteLabel: "sACN in", icon: "font-awesome/fa-lightbulb-o", diff --git a/src/nodes/sacn-in/sacn-in.ts b/src/nodes/sacn-in/sacn-in.ts index 8c35416..0650593 100644 --- a/src/nodes/sacn-in/sacn-in.ts +++ b/src/nodes/sacn-in/sacn-in.ts @@ -35,9 +35,12 @@ class NodeHandler { protected sACN: Receiver; + protected currentUniverse: number; + constructor(node: Node, config: Config) { this.node = node; this.config = config; + this.currentUniverse = config.universe; // parse options for receiver instance const options: Receiver.Props | MergingReceiver.Props = { @@ -101,6 +104,56 @@ class NodeHandler { }); }); } + + // allow switching the observed universe at runtime via msg.universe + this.node.on("input", (msg) => { + this.handleUniverseChange(msg as MessageIn); + }); + + this.setStatus(); + } + + protected setStatus(): void { + this.node.status({ + fill: "green", + shape: "dot", + text: `Universe ${this.currentUniverse}`, + }); + } + + protected parseUniverse(value: unknown): number | undefined { + const universe = typeof value === "string" ? parseInt(value, 10) : value; + + if (typeof universe !== "number" || !Number.isInteger(universe) || universe < 1 || universe > 63999) { + return undefined; + } + + return universe; + } + + protected handleUniverseChange(msg: MessageIn): void { + const universe = this.parseUniverse(msg.universe); + + if (universe === undefined) { + this.node.warn( + `The given "universe"-property "${msg.universe}" (${typeof msg.universe}) is invalid or not between 1 and 63999.`, + ); + + return; + } + + if (universe === this.currentUniverse) { + return; + } + + this.sACN.removeUniverse(this.currentUniverse); + this.sACN.addUniverse(universe); + + // drop the cached state of the previously observed universe + this.data?.delete(this.currentUniverse); + + this.currentUniverse = universe; + this.setStatus(); } protected getNulledUniverse(): DMXValues { From 8c439c0f49ba606917525f0aaa4ff3509a0d8b21 Mon Sep 17 00:00:00 2001 From: Florian Gail Date: Sat, 11 Jul 2026 23:59:22 +0200 Subject: [PATCH 2/2] Add configurable output trigger and blank-on-universe-change to sacn-in Introduce an output trigger that is independent of the merge mode: - changes: emit only when values change - always: emit on every received sACN packet, even without a change - interval: emit on change and, as a keepalive, re-emit the full universe when no change arrives within a configurable interval (default 1000 ms) Existing nodes without the field keep their previous behaviour (passthrough=always, htp/ltp=changes). Add clearOnUniverseChange: on a runtime msg.universe switch, optionally emit a full zeroed universe for the new universe until real data arrives. The full universe state is now always cached internally (needed for the keepalive and the blanking), the keepalive timer is cleared on close, and the interval field is shown only for the interval trigger. Rebuild dist. --- dist/nodes/sacn-in/locales/de/sacn-in.json | 8 +- dist/nodes/sacn-in/locales/en-US/sacn-in.json | 8 +- dist/nodes/sacn-in/sacn-in.html | 67 +++++++++ dist/nodes/sacn-in/sacn-in.js | 113 ++++++++++---- src/nodes/sacn-in/docs.html | 20 +++ src/nodes/sacn-in/form.html | 25 ++++ src/nodes/sacn-in/init.ts | 27 ++++ src/nodes/sacn-in/locales/de.json | 8 +- src/nodes/sacn-in/locales/en-US.json | 8 +- src/nodes/sacn-in/sacn-in.ts | 141 ++++++++++++++---- 10 files changed, 365 insertions(+), 60 deletions(-) diff --git a/dist/nodes/sacn-in/locales/de/sacn-in.json b/dist/nodes/sacn-in/locales/de/sacn-in.json index 96ed9e8..d0aa154 100644 --- a/dist/nodes/sacn-in/locales/de/sacn-in.json +++ b/dist/nodes/sacn-in/locales/de/sacn-in.json @@ -10,7 +10,13 @@ "universe": "Universum", "output": "Ausgabe", "output_full": "Vollständiges Universum", - "output_changes": "Änderungen" + "output_changes": "Änderungen", + "trigger": "Ausgabe-Auslösung", + "trigger_changes": "Nur Änderungen", + "trigger_always": "Jedes Paket", + "trigger_interval": "Änderungen + zyklisch", + "interval": "Intervall (ms)", + "clearOnUniverseChange": "Bei Universumswechsel auf 0 setzen" } } } \ No newline at end of file diff --git a/dist/nodes/sacn-in/locales/en-US/sacn-in.json b/dist/nodes/sacn-in/locales/en-US/sacn-in.json index 7b5f4df..678c53a 100644 --- a/dist/nodes/sacn-in/locales/en-US/sacn-in.json +++ b/dist/nodes/sacn-in/locales/en-US/sacn-in.json @@ -10,7 +10,13 @@ "universe": "universe", "output": "output", "output_full": "whole universe", - "output_changes": "changes" + "output_changes": "changes", + "trigger": "output trigger", + "trigger_changes": "changes only", + "trigger_always": "every packet", + "trigger_interval": "changes + cyclic", + "interval": "interval (ms)", + "clearOnUniverseChange": "blank on universe change" } } } \ No newline at end of file diff --git a/dist/nodes/sacn-in/sacn-in.html b/dist/nodes/sacn-in/sacn-in.html index 192f3ce..5f684c4 100644 --- a/dist/nodes/sacn-in/sacn-in.html +++ b/dist/nodes/sacn-in/sacn-in.html @@ -34,6 +34,31 @@ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +