node-red-contrib-dmx-for-ha 0.6.13 → 0.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -226,6 +226,37 @@ Typical workflow: Remove → update node settings → Deploy → node auto-disco
226
226
 
227
227
  ---
228
228
 
229
+ ## System control topic
230
+
231
+ All nodes subscribe to a system control topic for **bulk add/remove during commissioning**. No wiring needed — publish one MQTT message and all matching nodes respond.
232
+
233
+ **Topic:** `{siteId}/system/control` (e.g. `MW3D/system/control`)
234
+
235
+ **Payload:**
236
+ ```json
237
+ {"cmd": "remove", "zone": "all", "type": "all"}
238
+ {"cmd": "add", "zone": "Master", "type": "dmx"}
239
+ {"cmd": "remove", "zone": "BnB", "type": "button"}
240
+ ```
241
+
242
+ | Field | Values | Description |
243
+ |---|---|---|
244
+ | `cmd` | `add`, `remove` | Add or remove HA discovery |
245
+ | `zone` | `all`, `Master`, `BnB` | Matches config node zone |
246
+ | `type` | `all`, `dmx`, `button`, `pir`, `relay` | Node type filter |
247
+
248
+ **Commissioning workflow:**
249
+ ```
250
+ 1. ADD Master DMX → test all lights
251
+ 2. REMOVE Master DMX → fix wrong names/channels
252
+ 3. ADD Master DMX → verify clean
253
+ 4. Move to next type: Button → PIR → Relay
254
+ ```
255
+
256
+ A **System Control flow** ships with the package (`system_control_flow.json`). Import it into Node-RED, connect the MQTT out node to your broker, and you have one-click bulk control per zone and type.
257
+
258
+ ---
259
+
229
260
  ## DMX Group Node
230
261
 
231
262
  Appears as a single light entity in HA. Commands fan out to all nodes on its **Link** output.
@@ -70,6 +70,23 @@ module.exports = function (RED) {
70
70
  handleDeviceAdd();
71
71
  }
72
72
 
73
+ // ── System control topic ─────────────────────────────────
74
+ const systemTopic = `${cfg.siteId}/system/control`;
75
+ broker.subscribe(systemTopic, 0, function (topic, rawPayload) {
76
+ let msg;
77
+ try { msg = JSON.parse(rawPayload.toString()); } catch(e) { return; }
78
+ if (!msg.cmd) return;
79
+ const zone = (msg.zone || 'all').toLowerCase();
80
+ if (zone !== 'all' && zone !== cfg.zone.toLowerCase()) return;
81
+ const type = (msg.type || 'all').toLowerCase();
82
+ if (type !== 'all' && type !== 'button') return;
83
+ if (msg.cmd === 'remove') {
84
+ handleDeviceRemove();
85
+ } else if (msg.cmd === 'add') {
86
+ _tryDiscover();
87
+ }
88
+ }, node.id + '_sys');
89
+
73
90
  // Auto-discover if broker already connected on deploy
74
91
  if (broker.connected) {
75
92
  _tryDiscover();
@@ -78,6 +78,28 @@ module.exports = function (RED) {
78
78
  handleDeviceAdd();
79
79
  }
80
80
 
81
+ // ── System control topic ─────────────────────────────────
82
+ // Subscribes to: {siteId}/system/control
83
+ // Payload: {"cmd":"remove","zone":"all"} or {"cmd":"add","zone":"Master"}
84
+ const systemTopic = `${cfg.siteId}/system/control`;
85
+ broker.subscribe(systemTopic, 0, function (topic, rawPayload) {
86
+ let msg;
87
+ try { msg = JSON.parse(rawPayload.toString()); } catch(e) { return; }
88
+ if (!msg.cmd) return;
89
+ // Zone filter — "all" or match config zone
90
+ const zone = (msg.zone || 'all').toLowerCase();
91
+ if (zone !== 'all' && zone !== cfg.zone.toLowerCase()) return;
92
+ // Type filter — "all" or match node type
93
+ const type = (msg.type || 'all').toLowerCase();
94
+ if (type !== 'all' && type !== 'dmx') return;
95
+ // Execute command
96
+ if (msg.cmd === 'remove') {
97
+ handleDeviceRemove();
98
+ } else if (msg.cmd === 'add') {
99
+ _tryDiscover();
100
+ }
101
+ }, node.id + '_sys');
102
+
81
103
  // Auto-discover if broker already connected on deploy
82
104
  if (broker.connected) {
83
105
  _tryDiscover();
@@ -210,7 +232,7 @@ module.exports = function (RED) {
210
232
  return S.minOutput;
211
233
  }
212
234
  // DMX floor — snap up if above 0 but below hardware stable threshold
213
- if (gamma > 0 && gamma < S.dmxFloor) return S.dmxFloor;
235
+ if (colorValue > 0 && gamma < S.dmxFloor) return S.dmxFloor;
214
236
  // Note: ceiling is handled by S.dmxLimiter in scaleToDmx above
215
237
  return gamma;
216
238
  }
@@ -67,6 +67,23 @@ module.exports = function (RED) {
67
67
  handleDeviceAdd();
68
68
  }
69
69
 
70
+ // ── System control topic ─────────────────────────────────
71
+ const systemTopic = `${cfg.siteId}/system/control`;
72
+ broker.subscribe(systemTopic, 0, function (topic, rawPayload) {
73
+ let msg;
74
+ try { msg = JSON.parse(rawPayload.toString()); } catch(e) { return; }
75
+ if (!msg.cmd) return;
76
+ const zone = (msg.zone || 'all').toLowerCase();
77
+ if (zone !== 'all' && zone !== cfg.zone.toLowerCase()) return;
78
+ const type = (msg.type || 'all').toLowerCase();
79
+ if (type !== 'all' && type !== 'pir') return;
80
+ if (msg.cmd === 'remove') {
81
+ handleDeviceRemove();
82
+ } else if (msg.cmd === 'add') {
83
+ _tryDiscover();
84
+ }
85
+ }, node.id + '_sys');
86
+
70
87
  // Auto-discover if broker already connected on deploy
71
88
  if (broker.connected) {
72
89
  _tryDiscover();
@@ -70,6 +70,23 @@ module.exports = function (RED) {
70
70
  handleDeviceAdd();
71
71
  }
72
72
 
73
+ // ── System control topic ─────────────────────────────────
74
+ const systemTopic = `${cfg.siteId}/system/control`;
75
+ broker.subscribe(systemTopic, 0, function (topic, rawPayload) {
76
+ let msg;
77
+ try { msg = JSON.parse(rawPayload.toString()); } catch(e) { return; }
78
+ if (!msg.cmd) return;
79
+ const zone = (msg.zone || 'all').toLowerCase();
80
+ if (zone !== 'all' && zone !== cfg.zone.toLowerCase()) return;
81
+ const type = (msg.type || 'all').toLowerCase();
82
+ if (type !== 'all' && type !== 'relay') return;
83
+ if (msg.cmd === 'remove') {
84
+ handleDeviceRemove();
85
+ } else if (msg.cmd === 'add') {
86
+ _tryDiscover();
87
+ }
88
+ }, node.id + '_sys');
89
+
73
90
  // Auto-discover if broker already connected on deploy
74
91
  if (broker.connected) {
75
92
  _tryDiscover();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-dmx-for-ha",
3
- "version": "0.6.13",
3
+ "version": "0.6.15",
4
4
  "description": "DMX lighting control for Home Assistant via Node-RED and MQTT. Place a node, fill in the settings, deploy. Full HA device registry integration with RGBW/RGBWW/CCT/brightness colour modes, transitions, effects, and group control.",
5
5
  "keywords": [
6
6
  "node-red",