node-red-contrib-dmx-for-ha 0.3.0 → 0.3.4

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.
@@ -284,7 +284,7 @@
284
284
  Debug output to NR debug tab
285
285
  </label>
286
286
  <div style="margin-left:106px; margin-top:4px; color:#e74c3c; font-size:0.8em;">
287
- ⚠ Disable in production — logs every MQTT publish
287
+ ⚠ Disable in production — logs every MQTT publish. Auto-disables after 12hrs.
288
288
  </div>
289
289
  </div>
290
290
 
@@ -37,14 +37,32 @@ module.exports = function (RED) {
37
37
  }, 1500);
38
38
  }
39
39
 
40
- // Track if already discovered to prevent double-fire
40
+ // Track discovery state prevents double-fire and allows reconnect re-discovery
41
41
  let _discovered = false;
42
+ let _lastDiscoveryTime = 0;
43
+ const _DISCOVERY_COOLDOWN_MS = 5000; // 5 second cooldown between discoveries
44
+
42
45
  function _tryDiscover() {
43
46
  if (_discovered) return;
47
+ const now = Date.now();
48
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) return;
44
49
  _discovered = true;
50
+ _lastDiscoveryTime = now;
45
51
  autoDiscover();
46
52
  }
47
53
 
54
+ function _manualDiscover() {
55
+ // Manual trigger (canvas button or input msg) — bypass _discovered flag
56
+ // but still respect cooldown to prevent accidental rapid-fire
57
+ const now = Date.now();
58
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) {
59
+ node.warn('Discovery cooldown active — please wait 5 seconds between manual triggers');
60
+ return;
61
+ }
62
+ _lastDiscoveryTime = now;
63
+ handleDeviceAdd();
64
+ }
65
+
48
66
  // Auto-discover if broker already connected on deploy
49
67
  if (broker.connected) {
50
68
  _tryDiscover();
@@ -54,12 +72,30 @@ module.exports = function (RED) {
54
72
  _tryDiscover();
55
73
  });
56
74
  broker.on('close', function () {
75
+ _discovered = false; // Allow re-discovery on reconnect
57
76
  setStatus('red', 'ring', 'Broker disconnected');
58
77
  });
59
78
  broker.on('error', function (err) {
60
79
  node.warn('MQTT broker error: ' + (err.message || err));
61
80
  setStatus('red', 'dot', 'Broker error — check config');
62
81
  });
82
+ // ── Debug mode safeguards ─────────────────────────────────────────
83
+ if (S.debugMode) {
84
+ // Permanent canvas warning so debug mode is obvious
85
+ setStatus('red', 'dot', `ha-mqtt-button "${fixtureId}" ⚠ DEBUG MODE ON`);
86
+ node.warn(`[DEBUG] ha-mqtt-button "${fixtureId}" — debug mode is enabled. Disable in production.`);
87
+
88
+ // Auto-disable after 12 hours — safety net for forgotten debug sessions
89
+ setTimeout(function () {
90
+ if (S.debugMode) {
91
+ S.debugMode = false;
92
+ node.warn(`[DEBUG] ha-mqtt-button "${fixtureId}" — debug mode auto-disabled after 12 hours`);
93
+ setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
94
+ }
95
+ }, 12 * 60 * 60 * 1000);
96
+ }
97
+
98
+
63
99
  // Fallback — if connect event already fired before listener registered
64
100
  setTimeout(function () {
65
101
  _tryDiscover();
@@ -104,7 +140,7 @@ module.exports = function (RED) {
104
140
  qos: cfg.qos,
105
141
  retain: retain !== undefined ? retain : cfg.retain,
106
142
  });
107
- if (S.debugMode) node.debug(`${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
143
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
108
144
  }
109
145
 
110
146
  function setStatus(fill, shape, text) {
@@ -190,7 +226,7 @@ module.exports = function (RED) {
190
226
 
191
227
  if (devReq) {
192
228
  switch (devReq) {
193
- case 'add': handleDeviceAdd(); break;
229
+ case 'add': _manualDiscover(); break;
194
230
  case 'remove': handleDeviceRemove(); break;
195
231
  default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
196
232
  }
@@ -312,7 +312,7 @@
312
312
  Debug output to NR debug tab
313
313
  </label>
314
314
  <div style="margin-left:106px; margin-top:4px; color:#e74c3c; font-size:0.8em;">
315
- ⚠ Disable in production — logs every MQTT publish
315
+ ⚠ Disable in production — logs every MQTT publish. Auto-disables after 12hrs.
316
316
  </div>
317
317
  </div>
318
318
 
@@ -40,14 +40,32 @@ module.exports = function (RED) {
40
40
  }, 1500);
41
41
  }
42
42
 
43
- // Track if already discovered to prevent double-fire
43
+ // Track discovery state prevents double-fire and allows reconnect re-discovery
44
44
  let _discovered = false;
45
+ let _lastDiscoveryTime = 0;
46
+ const _DISCOVERY_COOLDOWN_MS = 5000; // 5 second cooldown between discoveries
47
+
45
48
  function _tryDiscover() {
46
49
  if (_discovered) return;
50
+ const now = Date.now();
51
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) return;
47
52
  _discovered = true;
53
+ _lastDiscoveryTime = now;
48
54
  autoDiscover();
49
55
  }
50
56
 
57
+ function _manualDiscover() {
58
+ // Manual trigger (canvas button or input msg) — bypass _discovered flag
59
+ // but still respect cooldown to prevent accidental rapid-fire
60
+ const now = Date.now();
61
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) {
62
+ node.warn('Discovery cooldown active — please wait 5 seconds between manual triggers');
63
+ return;
64
+ }
65
+ _lastDiscoveryTime = now;
66
+ handleDeviceAdd();
67
+ }
68
+
51
69
  // Auto-discover if broker already connected on deploy
52
70
  if (broker.connected) {
53
71
  _tryDiscover();
@@ -57,12 +75,30 @@ module.exports = function (RED) {
57
75
  _tryDiscover();
58
76
  });
59
77
  broker.on('close', function () {
78
+ _discovered = false; // Allow re-discovery on reconnect
60
79
  setStatus('red', 'ring', 'Broker disconnected');
61
80
  });
62
81
  broker.on('error', function (err) {
63
82
  node.warn('MQTT broker error: ' + (err.message || err));
64
83
  setStatus('red', 'dot', 'Broker error — check config');
65
84
  });
85
+ // ── Debug mode safeguards ─────────────────────────────────────────
86
+ if (S.debugMode) {
87
+ // Permanent canvas warning so debug mode is obvious
88
+ setStatus('red', 'dot', `ha-mqtt-dmx-group "${groupId}" ⚠ DEBUG MODE ON`);
89
+ node.warn(`[DEBUG] ha-mqtt-dmx-group "${groupId}" — debug mode is enabled. Disable in production.`);
90
+
91
+ // Auto-disable after 12 hours — safety net for forgotten debug sessions
92
+ setTimeout(function () {
93
+ if (S.debugMode) {
94
+ S.debugMode = false;
95
+ node.warn(`[DEBUG] ha-mqtt-dmx-group "${groupId}" — debug mode auto-disabled after 12 hours`);
96
+ setStatus('yellow', 'ring', `${groupId} ready — awaiting HA`);
97
+ }
98
+ }, 12 * 60 * 60 * 1000);
99
+ }
100
+
101
+
66
102
  // Fallback — if connect event already fired before listener registered
67
103
  setTimeout(function () {
68
104
  _tryDiscover();
@@ -136,7 +172,7 @@ module.exports = function (RED) {
136
172
  qos: cfg.qos,
137
173
  retain: retain !== undefined ? retain : cfg.retain,
138
174
  });
139
- if (S.debugMode) node.debug(`${groupId} → ${topic} ${strPayload.substring(0, 120)}`);
175
+ if (S.debugMode) node.warn(`[DEBUG] ${groupId} → ${topic} ${strPayload.substring(0, 120)}`);
140
176
  }
141
177
 
142
178
  function pubState(payload) {
@@ -303,7 +339,7 @@ module.exports = function (RED) {
303
339
 
304
340
  if (devReq) {
305
341
  switch (devReq) {
306
- case 'add': handleDeviceAdd(null); break;
342
+ case 'add': _manualDiscover(); break;
307
343
  case 'remove': handleDeviceRemove(null); break;
308
344
  default: node.warn(`${groupId} — unknown device.request: "${devReq}"`);
309
345
  }
@@ -548,7 +548,7 @@
548
548
  Debug output to NR debug tab
549
549
  </label>
550
550
  <div style="margin-left:106px; margin-top:4px; color:#e74c3c; font-size:0.8em;">
551
- ⚠ Disable in production — logs every MQTT publish
551
+ ⚠ Disable in production — logs every MQTT publish. Auto-disables after 12hrs.
552
552
  </div>
553
553
  </div>
554
554
 
@@ -47,14 +47,32 @@ module.exports = function (RED) {
47
47
  }, 1500);
48
48
  }
49
49
 
50
- // Track if already discovered to prevent double-fire
50
+ // Track discovery state prevents double-fire and allows reconnect re-discovery
51
51
  let _discovered = false;
52
+ let _lastDiscoveryTime = 0;
53
+ const _DISCOVERY_COOLDOWN_MS = 5000; // 5 second cooldown between discoveries
54
+
52
55
  function _tryDiscover() {
53
56
  if (_discovered) return;
57
+ const now = Date.now();
58
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) return;
54
59
  _discovered = true;
60
+ _lastDiscoveryTime = now;
55
61
  autoDiscover();
56
62
  }
57
63
 
64
+ function _manualDiscover() {
65
+ // Manual trigger (canvas button or input msg) — bypass _discovered flag
66
+ // but still respect cooldown to prevent accidental rapid-fire
67
+ const now = Date.now();
68
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) {
69
+ node.warn('Discovery cooldown active — please wait 5 seconds between manual triggers');
70
+ return;
71
+ }
72
+ _lastDiscoveryTime = now;
73
+ handleDeviceAdd();
74
+ }
75
+
58
76
  // Auto-discover if broker already connected on deploy
59
77
  if (broker.connected) {
60
78
  _tryDiscover();
@@ -64,12 +82,30 @@ module.exports = function (RED) {
64
82
  _tryDiscover();
65
83
  });
66
84
  broker.on('close', function () {
85
+ _discovered = false; // Allow re-discovery on reconnect
67
86
  setStatus('red', 'ring', 'Broker disconnected');
68
87
  });
69
88
  broker.on('error', function (err) {
70
89
  node.warn('MQTT broker error: ' + (err.message || err));
71
90
  setStatus('red', 'dot', 'Broker error — check config');
72
91
  });
92
+ // ── Debug mode safeguards ─────────────────────────────────────────
93
+ if (S.debugMode) {
94
+ // Permanent canvas warning so debug mode is obvious
95
+ setStatus('red', 'dot', `ha-mqtt-dmx "${fixtureId}" ⚠ DEBUG MODE ON`);
96
+ node.warn(`[DEBUG] ha-mqtt-dmx "${fixtureId}" — debug mode is enabled. Disable in production.`);
97
+
98
+ // Auto-disable after 12 hours — safety net for forgotten debug sessions
99
+ setTimeout(function () {
100
+ if (S.debugMode) {
101
+ S.debugMode = false;
102
+ node.warn(`[DEBUG] ha-mqtt-dmx "${fixtureId}" — debug mode auto-disabled after 12 hours`);
103
+ setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
104
+ }
105
+ }, 12 * 60 * 60 * 1000);
106
+ }
107
+
108
+
73
109
  // Fallback — if connect event already fired before listener registered
74
110
  setTimeout(function () {
75
111
  _tryDiscover();
@@ -180,12 +216,12 @@ module.exports = function (RED) {
180
216
  if (payload === null) return;
181
217
  // Skip if value unchanged since last publish
182
218
  if (_lastSent[ch] === val) {
183
- if (S.debugMode) node.debug(`${fixtureId} → SKIP ch${ch}=${val} (unchanged)`);
219
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → SKIP ch${ch}=${val} (unchanged)`);
184
220
  return;
185
221
  }
186
222
  _lastSent[ch] = val;
187
223
  broker.publish({ topic: dmxTopic, payload, qos: cfg.qos, retain: false });
188
- if (S.debugMode) node.debug(`${fixtureId} → ${dmxTopic} "${payload}"`);
224
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${dmxTopic} "${payload}"`);
189
225
  });
190
226
  }
191
227
 
@@ -204,7 +240,7 @@ module.exports = function (RED) {
204
240
  qos: cfg.qos,
205
241
  retain: retain !== undefined ? retain : cfg.retain,
206
242
  });
207
- if (S.debugMode) node.debug(`${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
243
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
208
244
  }
209
245
 
210
246
  function pubState(payload) {
@@ -617,7 +653,7 @@ module.exports = function (RED) {
617
653
 
618
654
  if (devReq) {
619
655
  switch (devReq) {
620
- case 'add': handleDeviceAdd(); break;
656
+ case 'add': _manualDiscover(); break;
621
657
  case 'remove': handleDeviceRemove(); break;
622
658
  default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
623
659
  }
@@ -289,7 +289,7 @@
289
289
  Debug output to NR debug tab
290
290
  </label>
291
291
  <div style="margin-left:106px; margin-top:4px; color:#e74c3c; font-size:0.8em;">
292
- ⚠ Disable in production — logs every MQTT publish
292
+ ⚠ Disable in production — logs every MQTT publish. Auto-disables after 12hrs.
293
293
  </div>
294
294
  </div>
295
295
 
@@ -37,14 +37,32 @@ module.exports = function (RED) {
37
37
  }, 1500);
38
38
  }
39
39
 
40
- // Track if already discovered to prevent double-fire
40
+ // Track discovery state prevents double-fire and allows reconnect re-discovery
41
41
  let _discovered = false;
42
+ let _lastDiscoveryTime = 0;
43
+ const _DISCOVERY_COOLDOWN_MS = 5000; // 5 second cooldown between discoveries
44
+
42
45
  function _tryDiscover() {
43
46
  if (_discovered) return;
47
+ const now = Date.now();
48
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) return;
44
49
  _discovered = true;
50
+ _lastDiscoveryTime = now;
45
51
  autoDiscover();
46
52
  }
47
53
 
54
+ function _manualDiscover() {
55
+ // Manual trigger (canvas button or input msg) — bypass _discovered flag
56
+ // but still respect cooldown to prevent accidental rapid-fire
57
+ const now = Date.now();
58
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) {
59
+ node.warn('Discovery cooldown active — please wait 5 seconds between manual triggers');
60
+ return;
61
+ }
62
+ _lastDiscoveryTime = now;
63
+ handleDeviceAdd();
64
+ }
65
+
48
66
  // Auto-discover if broker already connected on deploy
49
67
  if (broker.connected) {
50
68
  _tryDiscover();
@@ -54,12 +72,30 @@ module.exports = function (RED) {
54
72
  _tryDiscover();
55
73
  });
56
74
  broker.on('close', function () {
75
+ _discovered = false; // Allow re-discovery on reconnect
57
76
  setStatus('red', 'ring', 'Broker disconnected');
58
77
  });
59
78
  broker.on('error', function (err) {
60
79
  node.warn('MQTT broker error: ' + (err.message || err));
61
80
  setStatus('red', 'dot', 'Broker error — check config');
62
81
  });
82
+ // ── Debug mode safeguards ─────────────────────────────────────────
83
+ if (S.debugMode) {
84
+ // Permanent canvas warning so debug mode is obvious
85
+ setStatus('red', 'dot', `ha-mqtt-pir "${fixtureId}" ⚠ DEBUG MODE ON`);
86
+ node.warn(`[DEBUG] ha-mqtt-pir "${fixtureId}" — debug mode is enabled. Disable in production.`);
87
+
88
+ // Auto-disable after 12 hours — safety net for forgotten debug sessions
89
+ setTimeout(function () {
90
+ if (S.debugMode) {
91
+ S.debugMode = false;
92
+ node.warn(`[DEBUG] ha-mqtt-pir "${fixtureId}" — debug mode auto-disabled after 12 hours`);
93
+ setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
94
+ }
95
+ }, 12 * 60 * 60 * 1000);
96
+ }
97
+
98
+
63
99
  // Fallback — if connect event already fired before listener registered
64
100
  setTimeout(function () {
65
101
  _tryDiscover();
@@ -104,7 +140,7 @@ module.exports = function (RED) {
104
140
  qos: cfg.qos,
105
141
  retain: retain !== undefined ? retain : cfg.retain,
106
142
  });
107
- if (S.debugMode) node.debug(`${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
143
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
108
144
  }
109
145
 
110
146
  function setStatus(fill, shape, text) {
@@ -285,7 +285,7 @@
285
285
  Debug output to NR debug tab
286
286
  </label>
287
287
  <div style="margin-left:106px; margin-top:4px; color:#e74c3c; font-size:0.8em;">
288
- ⚠ Disable in production — logs every MQTT publish
288
+ ⚠ Disable in production — logs every MQTT publish. Auto-disables after 12hrs.
289
289
  </div>
290
290
  </div>
291
291
 
@@ -40,14 +40,32 @@ module.exports = function (RED) {
40
40
  }, 1500);
41
41
  }
42
42
 
43
- // Track if already discovered to prevent double-fire
43
+ // Track discovery state prevents double-fire and allows reconnect re-discovery
44
44
  let _discovered = false;
45
+ let _lastDiscoveryTime = 0;
46
+ const _DISCOVERY_COOLDOWN_MS = 5000; // 5 second cooldown between discoveries
47
+
45
48
  function _tryDiscover() {
46
49
  if (_discovered) return;
50
+ const now = Date.now();
51
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) return;
47
52
  _discovered = true;
53
+ _lastDiscoveryTime = now;
48
54
  autoDiscover();
49
55
  }
50
56
 
57
+ function _manualDiscover() {
58
+ // Manual trigger (canvas button or input msg) — bypass _discovered flag
59
+ // but still respect cooldown to prevent accidental rapid-fire
60
+ const now = Date.now();
61
+ if (now - _lastDiscoveryTime < _DISCOVERY_COOLDOWN_MS) {
62
+ node.warn('Discovery cooldown active — please wait 5 seconds between manual triggers');
63
+ return;
64
+ }
65
+ _lastDiscoveryTime = now;
66
+ handleDeviceAdd();
67
+ }
68
+
51
69
  // Auto-discover if broker already connected on deploy
52
70
  if (broker.connected) {
53
71
  _tryDiscover();
@@ -57,12 +75,30 @@ module.exports = function (RED) {
57
75
  _tryDiscover();
58
76
  });
59
77
  broker.on('close', function () {
78
+ _discovered = false; // Allow re-discovery on reconnect
60
79
  setStatus('red', 'ring', 'Broker disconnected');
61
80
  });
62
81
  broker.on('error', function (err) {
63
82
  node.warn('MQTT broker error: ' + (err.message || err));
64
83
  setStatus('red', 'dot', 'Broker error — check config');
65
84
  });
85
+ // ── Debug mode safeguards ─────────────────────────────────────────
86
+ if (S.debugMode) {
87
+ // Permanent canvas warning so debug mode is obvious
88
+ setStatus('red', 'dot', `ha-mqtt-relay "${fixtureId}" ⚠ DEBUG MODE ON`);
89
+ node.warn(`[DEBUG] ha-mqtt-relay "${fixtureId}" — debug mode is enabled. Disable in production.`);
90
+
91
+ // Auto-disable after 12 hours — safety net for forgotten debug sessions
92
+ setTimeout(function () {
93
+ if (S.debugMode) {
94
+ S.debugMode = false;
95
+ node.warn(`[DEBUG] ha-mqtt-relay "${fixtureId}" — debug mode auto-disabled after 12 hours`);
96
+ setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
97
+ }
98
+ }, 12 * 60 * 60 * 1000);
99
+ }
100
+
101
+
66
102
  // Fallback — if connect event already fired before listener registered
67
103
  setTimeout(function () {
68
104
  _tryDiscover();
@@ -140,7 +176,7 @@ module.exports = function (RED) {
140
176
  qos: cfg.qos,
141
177
  retain: retain !== undefined ? retain : cfg.retain,
142
178
  });
143
- if (S.debugMode) node.debug(`${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
179
+ if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
144
180
  }
145
181
 
146
182
  function pubRelay(value) {
@@ -325,7 +361,7 @@ module.exports = function (RED) {
325
361
 
326
362
  if (devReq) {
327
363
  switch (devReq) {
328
- case 'add': handleDeviceAdd(); break;
364
+ case 'add': _manualDiscover(); break;
329
365
  case 'remove': handleDeviceRemove(); break;
330
366
  default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
331
367
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-dmx-for-ha",
3
- "version": "0.3.0",
3
+ "version": "0.3.4",
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",