node-red-contrib-dmx-for-ha 0.6.21 → 0.6.22

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.
@@ -313,7 +313,7 @@
313
313
  </div>
314
314
 
315
315
  <div style="margin-top:16px; padding-top:8px; border-top:1px solid #444; color:#666; font-size:0.8em; text-align:right;">
316
- node-red-contrib-dmx-for-ha &nbsp;v0.6.21
316
+ node-red-contrib-dmx-for-ha &nbsp;v0.6.1
317
317
  </div>
318
318
 
319
319
  </script>
@@ -22,7 +22,6 @@ module.exports = function (RED) {
22
22
  if (!broker) { node.error('Button: no MQTT broker in config'); return; }
23
23
 
24
24
  broker.register(node);
25
- if (broker.client && broker.client.setMaxListeners) broker.client.setMaxListeners(0);
26
25
 
27
26
  // ── Auto-discovery based on Discovery Mode ────────────────────
28
27
  const discoveryMode = config.discoveryMode || 'enabled';
@@ -316,7 +315,6 @@ module.exports = function (RED) {
316
315
 
317
316
  // ── Cleanup ───────────────────────────────────────────────
318
317
  node.on('close', function (done) {
319
- unregisterFixtureId();
320
318
  broker.unsubscribe(S._activeBtnTopic || S.subscribeTopic, node.id);
321
319
  broker.unsubscribe(uiBtnCmdTopic, node.id);
322
320
  broker.deregister(node, done);
@@ -24,6 +24,7 @@
24
24
  diskDelay: { value: '10' },
25
25
  transitionRateLimit: { value: '1' },
26
26
  transitionHaUiTime: { value: '1' },
27
+ offTransition: { value: '1' },
27
28
  flashShort: { value: '1' },
28
29
  flashLong: { value: '10' },
29
30
  dmxFloor: { value: '3' },
@@ -205,6 +206,17 @@
205
206
  min="1" style="width:70px" />
206
207
  </div>
207
208
 
209
+ <div class="form-row">
210
+ <label for="node-config-input-offTransition">
211
+ <i class="fa fa-clock-o"></i> Default OFF transition
212
+ </label>
213
+ <input type="number" id="node-config-input-offTransition"
214
+ min="0" max="10" step="0.1" style="width:70px" />
215
+ <span style="margin-left:8px; color:#999; font-size:0.85em;">
216
+ Seconds. Applied when HA sends OFF without a transition time. 0 = snap off. Default: 1
217
+ </span>
218
+ </div>
219
+
208
220
  <div class="form-row">
209
221
  <label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
210
222
  <i class="fa fa-sliders"></i> DMX Channel Limits
@@ -63,7 +63,8 @@ module.exports = function (RED) {
63
63
  this.transitionHaUiTime = parseFloat(config.transitionHaUiTime) || 1;
64
64
 
65
65
  // DMX channel limits
66
- this.dmxFloor = parseInt(config.dmxFloor) >= 0 ? parseInt(config.dmxFloor) : 3;
66
+ this.dmxFloor = parseInt(config.dmxFloor) >= 0 ? parseInt(config.dmxFloor) : 3;
67
+ this.offTransition = parseFloat(config.offTransition) >= 0 ? parseFloat(config.offTransition) : 1;
67
68
 
68
69
  // ── Topic builder — omits empty zone segment ─────────────────────────
69
70
  this.buildTopic = function() {
@@ -92,6 +93,7 @@ module.exports = function (RED) {
92
93
  transitionRateLimit: this.transitionRateLimit,
93
94
  transitionHaUiTime: this.transitionHaUiTime,
94
95
  dmxFloor: this.dmxFloor,
96
+ offTransition: this.offTransition,
95
97
  };
96
98
  }
97
99
 
@@ -317,7 +317,7 @@
317
317
  </div>
318
318
 
319
319
  <div style="margin-top:16px; padding-top:8px; border-top:1px solid #444; color:#666; font-size:0.8em; text-align:right;">
320
- node-red-contrib-dmx-for-ha &nbsp;v0.6.21
320
+ node-red-contrib-dmx-for-ha &nbsp;v0.6.1
321
321
  </div>
322
322
 
323
323
  </script>
@@ -25,7 +25,6 @@ module.exports = function (RED) {
25
25
  if (!broker) { node.error('DMX Group: no MQTT broker in config'); return; }
26
26
 
27
27
  broker.register(node);
28
- if (broker.client && broker.client.setMaxListeners) broker.client.setMaxListeners(0);
29
28
 
30
29
  // ── Auto-discovery based on Discovery Mode ────────────────────
31
30
  const discoveryMode = config.discoveryMode || 'enabled';
@@ -418,7 +417,6 @@ module.exports = function (RED) {
418
417
 
419
418
  // ── Cleanup ───────────────────────────────────────────────
420
419
  node.on('close', function (done) {
421
- unregisterFixtureId();
422
420
  if (diskTimer) clearTimeout(diskTimer);
423
421
  broker.unsubscribe(cmdTopic, node.id);
424
422
  broker.deregister(node, done);
@@ -584,7 +584,7 @@
584
584
  </div>
585
585
 
586
586
  <div style="margin-top:16px; padding-top:8px; border-top:1px solid #444; color:#666; font-size:0.8em; text-align:right;">
587
- node-red-contrib-dmx-for-ha &nbsp;v0.6.21
587
+ node-red-contrib-dmx-for-ha &nbsp;v0.6.1
588
588
  </div>
589
589
 
590
590
  </script>
@@ -32,7 +32,6 @@ module.exports = function (RED) {
32
32
  if (!broker) { node.error('DMX: no MQTT broker in config'); return; }
33
33
 
34
34
  broker.register(node);
35
- if (broker.client && broker.client.setMaxListeners) broker.client.setMaxListeners(0);
36
35
 
37
36
  // ── Auto-discovery based on Discovery Mode ────────────────────
38
37
  const discoveryMode = config.discoveryMode || 'enabled';
@@ -226,8 +225,6 @@ module.exports = function (RED) {
226
225
  // ── DMX helpers ───────────────────────────────────────────
227
226
  function scaleToDmx(colorValue, brightness) {
228
227
  brightness = brightness !== undefined ? brightness : 255;
229
- // Hard zero — never apply any floor when brightness is 0 (OFF)
230
- if (brightness === 0) return 0;
231
228
  const limited = Math.round((colorValue / 255) * (brightness / 255) * S.dmxLimiter);
232
229
  const gamma = GAMMA_TABLE[Math.max(0, Math.min(255, limited))];
233
230
  // Min output floor — only apply when both inputs are non-zero (intentionally on)
@@ -422,7 +419,13 @@ module.exports = function (RED) {
422
419
  const progress = Math.min(1, tick / totalTicks);
423
420
  const channels = fromChannels.map(function ([ch, from], i) {
424
421
  const to = toChannels[i] ? toChannels[i][1] : 0;
425
- return [ch, Math.round(from + (to - from) * progress)];
422
+ const raw = Math.round(from + (to - from) * progress);
423
+ // Floor: if target is ON, snap low values up to floor
424
+ // if target is OFF, jump from floor directly to 0
425
+ const floored = raw <= 0 ? 0
426
+ : raw < S.dmxFloor ? (to <= 0 ? 0 : S.dmxFloor)
427
+ : raw;
428
+ return [ch, floored];
426
429
  });
427
430
  sendDmxChannels(channels);
428
431
  if (tick >= totalTicks) {
@@ -501,9 +504,13 @@ module.exports = function (RED) {
501
504
 
502
505
  const toChannels = buildColorChannels(0, r, g, b, w, ww);
503
506
 
504
- if (S.transitions && payload && payload.transition && payload.transition > 0) {
507
+ // OFF transition: use HA payload time, or config offTransition default
508
+ const offDuration = (payload && payload.transition && payload.transition > 0)
509
+ ? payload.transition
510
+ : (cfg.offTransition || 0);
511
+ if (S.transitions && offDuration > 0) {
505
512
  const fromChannels = buildColorChannels(brightness, r, g, b, w, ww);
506
- runTransition(fromChannels, toChannels, transitionDuration);
513
+ runTransition(fromChannels, toChannels, offDuration);
507
514
  } else {
508
515
  sendDmxChannels(toChannels);
509
516
  }
@@ -867,7 +874,6 @@ module.exports = function (RED) {
867
874
 
868
875
  // ── Cleanup ───────────────────────────────────────────────
869
876
  node.on('close', function (done) {
870
- unregisterFixtureId();
871
877
  clearChannelRegistry();
872
878
  stopEffect();
873
879
  if (diskTimer) clearTimeout(diskTimer);
@@ -318,7 +318,7 @@
318
318
  </div>
319
319
 
320
320
  <div style="margin-top:16px; padding-top:8px; border-top:1px solid #444; color:#666; font-size:0.8em; text-align:right;">
321
- node-red-contrib-dmx-for-ha &nbsp;v0.6.21
321
+ node-red-contrib-dmx-for-ha &nbsp;v0.6.1
322
322
  </div>
323
323
 
324
324
  </script>
@@ -22,7 +22,6 @@ module.exports = function (RED) {
22
22
  if (!broker) { node.error('PIR: no MQTT broker in config'); return; }
23
23
 
24
24
  broker.register(node);
25
- if (broker.client && broker.client.setMaxListeners) broker.client.setMaxListeners(0);
26
25
 
27
26
  // ── Auto-discovery based on Discovery Mode ────────────────────
28
27
  const discoveryMode = config.discoveryMode || 'enabled';
@@ -350,7 +349,6 @@ module.exports = function (RED) {
350
349
 
351
350
  // ── Cleanup ───────────────────────────────────────────────
352
351
  node.on('close', function (done) {
353
- unregisterFixtureId();
354
352
  cancelWarmup();
355
353
  broker.unsubscribe(S._activePirTopic || S.subscribeTopic, node.id);
356
354
  broker.deregister(node, done);
@@ -301,7 +301,7 @@
301
301
  </div>
302
302
 
303
303
  <div style="margin-top:16px; padding-top:8px; border-top:1px solid #444; color:#666; font-size:0.8em; text-align:right;">
304
- node-red-contrib-dmx-for-ha &nbsp;v0.6.21
304
+ node-red-contrib-dmx-for-ha &nbsp;v0.6.1
305
305
  </div>
306
306
 
307
307
  </script>
@@ -25,7 +25,6 @@ module.exports = function (RED) {
25
25
  if (!broker) { node.error('Relay: no MQTT broker in config'); return; }
26
26
 
27
27
  broker.register(node);
28
- if (broker.client && broker.client.setMaxListeners) broker.client.setMaxListeners(0);
29
28
 
30
29
  // ── Auto-discovery based on Discovery Mode ────────────────────
31
30
  const discoveryMode = config.discoveryMode || 'enabled';
@@ -454,7 +453,6 @@ module.exports = function (RED) {
454
453
 
455
454
  // ── Cleanup ───────────────────────────────────────────────
456
455
  node.on('close', function (done) {
457
- unregisterFixtureId();
458
456
  stopEffect();
459
457
  if (diskTimer) clearTimeout(diskTimer);
460
458
  broker.unsubscribe(cmdTopic, node.id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-dmx-for-ha",
3
- "version": "0.6.21",
3
+ "version": "0.6.22",
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",