Skip to content

Commit d05dcb9

Browse files
committed
add option to send whole universe or changes only
1 parent 03aa9db commit d05dcb9

File tree

6 files changed

+125
-45
lines changed

6 files changed

+125
-45
lines changed

src/sacn/locales/de/sacn-in.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
"mode_htp": "HTP",
88
"mode_ltp": "LTP",
99
"port": "Port",
10-
"universe": "Universum"
10+
"universe": "Universum",
11+
"output": "Ausgabe",
12+
"output_full": "Vollständiges Universum",
13+
"output_changes": "Änderungen"
1114
}
1215
}
1316
}

src/sacn/locales/en-US/sacn-in.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
"mode_htp": "HTP",
88
"mode_ltp": "LTP",
99
"port": "port",
10-
"universe": "universe"
10+
"universe": "universe",
11+
"output": "output",
12+
"output_full": "whole universe",
13+
"output_changes": "changes"
1114
}
1215
}
1316
}

src/sacn/sacn-in.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@
2020
<div class="form-row">
2121
<label for="node-input-mode"><i class="fa fa-compress"></i> <span data-i18n="sacn-in.label.mode"></span></label>
2222
<select id="node-input-mode" style="width:70%;">
23-
<option value="direct" selected data-i18n="sacn-in.label.mode_direct"></option>
23+
<option value="passthrough" selected data-i18n="sacn-in.label.mode_direct"></option>
2424
<option value="htp" data-i18n="sacn-in.label.mode_htp"></option>
2525
<option value="ltp" data-i18n="sacn-in.label.mode_ltp"></option>
2626
</select>
2727
</div>
28+
<div class="form-row">
29+
<label for="node-input-output"><i class="fa fa-compress"></i> <span data-i18n="sacn-in.label.output"></span></label>
30+
<select id="node-input-output" style="width:70%;">
31+
<option value="full" selected data-i18n="sacn-in.label.output_full"></option>
32+
<option value="changes" data-i18n="sacn-in.label.output_changes"></option>
33+
</select>
34+
</div>
2835
<div class="form-row">
2936
<label for="node-input-interface"
3037
><i class="fa fa-plug"></i> <span data-i18n="sacn-in.label.interface"></span
@@ -62,6 +69,10 @@
6269
value: "htp",
6370
required: true,
6471
},
72+
output: {
73+
value: "full",
74+
required: true,
75+
},
6576
outputs: {
6677
value: 1,
6778
},

src/sacn/sacn-in.js

Lines changed: 46 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/sacn/sacn-in.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ts/sacn/sacn-in.ts

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface SacnInOptions extends NodeDef {
88
interface?: string;
99
port?: number;
1010
mode: "htp" | "ltp" | "passthrough";
11+
output: "full" | "changes";
1112
}
1213

1314
export interface SacnInMessage extends NodeMessage {
@@ -29,6 +30,10 @@ const nodeInit: NodeInitializer = (RED): void => {
2930
function SacnInNodeConstructor(this: Node, config: SacnInOptions): void {
3031
RED.nodes.createNode(this, config);
3132

33+
// initialize universe data
34+
let data: Map<number, DMXValues> | undefined = new Map();
35+
36+
// parse options for receiver instance
3237
const options: Receiver.Props | MergingReceiver.Props = {
3338
universes: [config.universe],
3439
reuseAddr: config.reuseAddress !== undefined ? config.reuseAddress : true,
@@ -40,26 +45,69 @@ const nodeInit: NodeInitializer = (RED): void => {
4045
options.port = config.port;
4146
}
4247

48+
// internal functions
49+
const getNulledUniverse = (): DMXValues => {
50+
const universe: DMXValues = {};
51+
52+
for (let ch = 1; ch <= 512; ch++) {
53+
universe[ch] = 0;
54+
}
55+
56+
return universe;
57+
};
58+
59+
const getReference = (universe: number): DMXValues => {
60+
if (config.output === "changes") {
61+
return {} as DMXValues;
62+
}
63+
64+
return data?.get(universe) ?? getNulledUniverse();
65+
};
66+
67+
const parsePayload = (payload: DMXValues, universe: number): DMXValues => {
68+
const processedPayload: DMXValues = getReference(universe);
69+
70+
Object.keys(payload).forEach((key) => {
71+
const ch = parseInt(key, 10);
72+
processedPayload[ch + 1] = payload[ch];
73+
});
74+
75+
if (config.output !== "changes") {
76+
data?.set(universe, processedPayload);
77+
}
78+
79+
return processedPayload;
80+
};
81+
82+
// init sacn receiver
4383
let sACN: Receiver;
44-
if (config.mode === "passthrough") {
45-
sACN = new Receiver(options);
46-
} else if (config.mode === "ltp" || config.mode === "htp") {
47-
(options as MergingReceiver.Props).mode = config.mode.toUpperCase() as "HTP" | "LTP";
48-
sACN = new MergingReceiver(options);
49-
} else {
50-
throw new Error("[node-red-sacn] None or invalid mode selected.");
84+
switch (config.mode) {
85+
case "passthrough":
86+
sACN = new Receiver(options);
87+
break;
88+
case "htp":
89+
case "ltp":
90+
(options as MergingReceiver.Props).mode = config.mode.toUpperCase() as "HTP" | "LTP";
91+
sACN = new MergingReceiver(options);
92+
break;
93+
default:
94+
throw new Error("[node-red-sacn] None or invalid mode selected.");
5195
}
5296

97+
// run cleanup when node is closed
5398
this.on("close", () => {
5499
// close all connections; terminate the receiver
55100
sACN.close();
101+
102+
data = new Map();
56103
});
57104

105+
// handle sacn packets
58106
if (config.mode === "passthrough") {
59107
sACN.on("packet", (packet) => {
60108
this.send({
61109
universe: packet.universe,
62-
payload: incrementPayload(packet.payload),
110+
payload: parsePayload(packet.payload, packet.universe),
63111
sequence: packet.sequence,
64112
source: packet.sourceAddress,
65113
priority: packet.priority,
@@ -72,7 +120,7 @@ const nodeInit: NodeInitializer = (RED): void => {
72120
// @ts-expect-error // TODO https://github.com/k-yle/sACN/pull/63
73121
universe: data.universe,
74122
// @ts-expect-error // TODO https://github.com/k-yle/sACN/pull/63
75-
payload: incrementPayload(data.payload),
123+
payload: parsePayload(data.payload, data.universe),
76124
} as SacnInMessage);
77125
});
78126
} else if (config.mode === "htp") {
@@ -82,23 +130,12 @@ const nodeInit: NodeInitializer = (RED): void => {
82130
// @ts-expect-error // TODO https://github.com/k-yle/sACN/pull/63
83131
universe: data.universe,
84132
// @ts-expect-error // TODO https://github.com/k-yle/sACN/pull/63
85-
payload: incrementPayload(data.payload),
133+
payload: parsePayload(data.payload, data.universe),
86134
} as SacnInMessage);
87135
});
88136
}
89137
}
90138

91-
function incrementPayload(payload: DMXValues): DMXValues {
92-
const result: DMXValues = {};
93-
94-
Object.keys(payload).forEach((key) => {
95-
const ch = parseInt(key, 10);
96-
result[ch + 1] = payload[ch];
97-
});
98-
99-
return result;
100-
}
101-
102139
RED.nodes.registerType("sacn_in", SacnInNodeConstructor);
103140
};
104141

0 commit comments

Comments
 (0)