node-red-contrib-dmx-for-ha 0.4.4 → 0.4.8
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 +97 -7
- package/nodes/ha-mqtt-config.html +16 -0
- package/nodes/ha-mqtt-config.js +4 -0
- package/nodes/ha-mqtt-dmx-group.js +1 -0
- package/nodes/ha-mqtt-dmx.js +21 -4
- package/nodes/ha-mqtt-relay.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# node-red-contrib-dmx-for-ha
|
|
2
2
|
|
|
3
|
-
DMX lighting control for Home Assistant via Node-RED and MQTT
|
|
3
|
+
**Professional DMX lighting control for Home Assistant via Node-RED and MQTT.**
|
|
4
|
+
|
|
5
|
+
Built by a lighting integrator, for lighting integrators — and anyone else who needs serious DMX control inside Home Assistant.
|
|
4
6
|
|
|
5
7
|
Place a node, fill in the settings, deploy. Your DMX fixture appears in Home Assistant automatically — ready to use in automations, dashboards, and scenes.
|
|
6
8
|
|
|
@@ -8,6 +10,43 @@ No YAML. No custom MQTT discovery config. No external wiring inside Node-RED.
|
|
|
8
10
|
|
|
9
11
|
---
|
|
10
12
|
|
|
13
|
+
## Who this is for
|
|
14
|
+
|
|
15
|
+
This package was designed for **professional AV and lighting integrators** working on large residential and commercial installations. If any of these sound familiar, this was built for you:
|
|
16
|
+
|
|
17
|
+
- You have hundreds of DMX fixtures that each need individual HA entity management
|
|
18
|
+
- You commission remotely — physically pressing every button on a large site is not practical
|
|
19
|
+
- Your client's lights must come back to the correct state after any power cycle, every time
|
|
20
|
+
- Your automation logic lives in HA, not hardcoded in the lighting controller
|
|
21
|
+
- You have multiple DMX universes and controllers in a single zone
|
|
22
|
+
- You've stood in a roof cavity at 11pm wondering why channel 47 isn't responding
|
|
23
|
+
|
|
24
|
+
It also works perfectly for advanced home users who want proper DMX integration rather than a workaround.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## The architecture
|
|
29
|
+
|
|
30
|
+
Node-RED acts as the **virtual lighting desk** — it owns the DMX channels, manages transitions, and handles hardware communication. Home Assistant is the **automation and UI layer** — it sees clean light entities and knows nothing about DMX channels, universes, or controllers.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Home Assistant Node-RED DMX Hardware
|
|
34
|
+
────────────── ──────── ────────────
|
|
35
|
+
Automations ←──→ ha-mqtt-dmx ──→ EtherTen /
|
|
36
|
+
Dashboards ha-mqtt-group DMX decoder /
|
|
37
|
+
Scenes ha-mqtt-relay MQTT bridge
|
|
38
|
+
Voice control ha-mqtt-button ←── Wall buttons
|
|
39
|
+
ha-mqtt-pir ←── PIR sensors
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This separation means:
|
|
43
|
+
- **HA stays clean** — light entities behave like any other HA light
|
|
44
|
+
- **NR handles complexity** — DMX addressing, gamma correction, transitions, effects
|
|
45
|
+
- **Hardware is abstracted** — swap controllers without touching HA config
|
|
46
|
+
- **Remote commissioning** — every physical device has a software mirror in HA, testable from anywhere
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
11
50
|
## What this package does
|
|
12
51
|
|
|
13
52
|
Bridges the gap between DMX lighting hardware and Home Assistant.
|
|
@@ -18,9 +57,12 @@ Most DMX implementations require either expensive proprietary hardware or comple
|
|
|
18
57
|
- RGBW, RGBWW, RGB, Colour Temperature, Brightness, and On/Off colour modes
|
|
19
58
|
- Gamma-corrected DMX output
|
|
20
59
|
- Transitions, effects, and group control
|
|
21
|
-
- State persistence across reboots
|
|
22
|
-
- Wall button and PIR motion sensor integration
|
|
60
|
+
- State persistence across reboots — survives power cycles and HA updates
|
|
61
|
+
- Wall button and PIR motion sensor integration with remote commissioning support
|
|
23
62
|
- 230V relay switching
|
|
63
|
+
- DMX channel conflict detection — warns on duplicate channel assignments
|
|
64
|
+
- Configurable DMX floor value — prevents low-value flicker on hardware that needs it
|
|
65
|
+
- Debug mode per node — 12hr auto-disable, safe to leave in production flows
|
|
24
66
|
|
|
25
67
|
> **Note:** This is building automation DMX — fixtures, decoders, dimmers, relay switching. Not entertainment industry DMX (no movers, gobos, or fixture profiles). DMX is an open standard and this package works with any DMX controller that accepts MQTT payloads.
|
|
26
68
|
|
|
@@ -120,7 +162,20 @@ Fill in the node editor:
|
|
|
120
162
|
1. **Fixture ID** — Prefix (`L`), Plan ID, optional channel letter e.g. `L` `992` `-A`
|
|
121
163
|
2. **Colour Mode** — RGBW, RGB, CCT etc.
|
|
122
164
|
3. **Device Type** — e.g. Downlight, Strip light
|
|
123
|
-
4. **Situation** —
|
|
165
|
+
4. **Situation** — describes where the fixture is relative to its area. Options:
|
|
166
|
+
|
|
167
|
+
| Situation | Example result |
|
|
168
|
+
|---|---|
|
|
169
|
+
| `in` | Downlight **in** Bedroom 1 |
|
|
170
|
+
| `at` | Spotlight **at** Entry Door |
|
|
171
|
+
| `near` | Strip light **near** Kitchen Bench |
|
|
172
|
+
| `above` | Flood **above** Garage Door |
|
|
173
|
+
| `below` | Step light **below** Handrail |
|
|
174
|
+
| `outside` | Rail light **outside** Media Room |
|
|
175
|
+
| `throughout` | Downlight **throughout** Living Area |
|
|
176
|
+
|
|
177
|
+
> **Tip:** Don't default to `in` for everything — `outside`, `near` and `above` are useful for fixtures in corridors, at thresholds, and above architectural features. On a large installation this makes fixture names immediately meaningful without opening a plan.
|
|
178
|
+
|
|
124
179
|
5. **Config** — select your config node
|
|
125
180
|
6. **Area** and **Sub-Area** — location on the property
|
|
126
181
|
7. **DMX Channels** — channel numbers matching your fixture's DMX start address
|
|
@@ -182,8 +237,35 @@ Naming: `L-992-A`, `L-992-B`, `L-992-C` group naturally under `LG-992`.
|
|
|
182
237
|
## Wall buttons
|
|
183
238
|
|
|
184
239
|
Creates two HA entities per button:
|
|
185
|
-
|
|
186
|
-
-
|
|
240
|
+
|
|
241
|
+
- **`binary_sensor.s_10_a`** — physical state. ON = pressed/held, OFF = released. Use this for automations and dashboard display.
|
|
242
|
+
- **`button.s_10_a_btn`** — momentary trigger. Simulates a physical press from the HA UI.
|
|
243
|
+
|
|
244
|
+
### Why two entities?
|
|
245
|
+
|
|
246
|
+
This package is designed for **professional installation** as well as home use. On large installations it is not practical to physically press every button every time you make a change — the building may be large, the button may be on the other side of the property, or you may be commissioning remotely.
|
|
247
|
+
|
|
248
|
+
The `button` entity gives you a **virtual commissioning panel** — every physical wall button has a software mirror in HA that you can trigger from a laptop anywhere in the world without being on site.
|
|
249
|
+
|
|
250
|
+
### Important — HA button entity behaviour
|
|
251
|
+
|
|
252
|
+
The `button` domain in HA is **intentionally stateless** — it will never light up or show an active state. This is a HA platform design decision, not a bug. The `button` entity triggers and immediately resets with no persistent state.
|
|
253
|
+
|
|
254
|
+
For visual feedback always use the `binary_sensor` entity.
|
|
255
|
+
|
|
256
|
+
### Recommended dashboard setup
|
|
257
|
+
|
|
258
|
+
Hide the `button` entity from the default dashboard to keep things clean — it remains fully accessible when needed:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Settings → Devices → (button device) → button entity → ⋮ → Hide from dashboard
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This gives you:
|
|
265
|
+
- **Dashboard** — clean, only `binary_sensor` shown
|
|
266
|
+
- **Device page** — both entities visible, Press button accessible for commissioning
|
|
267
|
+
- **Automations** — both entities fully available, nothing hidden from logic
|
|
268
|
+
- **Remote commissioning** — navigate to device page, simulate press from anywhere
|
|
187
269
|
|
|
188
270
|
Letters `I` and `O` are never used as suffixes — they look too similar to `1` and `0`.
|
|
189
271
|
|
|
@@ -411,7 +493,15 @@ If `disk_values` shows `[module=memory]` — your config.js change didn't take e
|
|
|
411
493
|
|
|
412
494
|
| Version | Changes |
|
|
413
495
|
|---|---|
|
|
414
|
-
| 0.
|
|
496
|
+
| 0.4.4 | Recovery status shows actual state on canvas instead of "ready — awaiting HA" |
|
|
497
|
+
| 0.4.3 | device:remove no longer clears disk state — state survives remove/add cycles |
|
|
498
|
+
| 0.4.2 | Group node pubState includes color — fixes color wheel jitter in HA |
|
|
499
|
+
| 0.4.1 | Group node status reflects ON/OFF correctly |
|
|
500
|
+
| 0.4.0 | Group recovery no longer forwards state to children — each node recovers independently |
|
|
501
|
+
| 0.3.9 | Four fixes: group device:add forward removed, cooldown warn suppressed, group status permanent, disk flush on close |
|
|
502
|
+
| 0.3.8 | Restored missing variable declarations wiped by debug block corruption |
|
|
503
|
+
| 0.3.7 | Fix _debugId computed from S (not fixtureId) to avoid ReferenceError on startup |
|
|
504
|
+
| 0.3.6 | DMX channel conflict detection, jitter timer tracked and cancellable |
|
|
415
505
|
| 0.3.5 | Fix debug mode block initialisation order (S before debug) |
|
|
416
506
|
| 0.3.4 | Debug hint text updated — notes 12hr auto-disable |
|
|
417
507
|
| 0.3.3 | Debug mode canvas warning + 12hr auto-disable safety net |
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
transitionHaUiTime: { value: '1' },
|
|
26
26
|
flashShort: { value: '1' },
|
|
27
27
|
flashLong: { value: '10' },
|
|
28
|
+
dmxFloor: { value: '3' },
|
|
28
29
|
},
|
|
29
30
|
label: function () {
|
|
30
31
|
return this.name || 'HA MQTT Config';
|
|
@@ -190,6 +191,21 @@
|
|
|
190
191
|
min="1" style="width:70px" />
|
|
191
192
|
</div>
|
|
192
193
|
|
|
194
|
+
<div class="form-row">
|
|
195
|
+
<label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
|
|
196
|
+
<i class="fa fa-sliders"></i> DMX Channel Limits
|
|
197
|
+
</label>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="form-row">
|
|
200
|
+
<label for="node-config-input-dmxFloor">
|
|
201
|
+
<i class="fa fa-arrow-down"></i> DMX Floor
|
|
202
|
+
</label>
|
|
203
|
+
<input type="number" id="node-config-input-dmxFloor"
|
|
204
|
+
min="0" max="20" step="1" style="width:70px" />
|
|
205
|
+
<span style="margin-left:8px; color:#999; font-size:0.85em;">
|
|
206
|
+
Min DMX value sent — below this snaps up (0=OFF always OFF). Default: 3
|
|
207
|
+
</span>
|
|
208
|
+
</div>
|
|
193
209
|
</script>
|
|
194
210
|
|
|
195
211
|
<!-- ============================================================
|
package/nodes/ha-mqtt-config.js
CHANGED
|
@@ -61,6 +61,9 @@ module.exports = function (RED) {
|
|
|
61
61
|
this.transitionRateLimit = parseFloat(config.transitionRateLimit) || 1;
|
|
62
62
|
this.transitionHaUiTime = parseFloat(config.transitionHaUiTime) || 1;
|
|
63
63
|
|
|
64
|
+
// DMX channel limits
|
|
65
|
+
this.dmxFloor = parseInt(config.dmxFloor) >= 0 ? parseInt(config.dmxFloor) : 3;
|
|
66
|
+
|
|
64
67
|
// ── Topic builder — omits empty zone segment ─────────────────────────
|
|
65
68
|
this.buildTopic = function() {
|
|
66
69
|
const segments = Array.from(arguments).filter(function(s) {
|
|
@@ -86,6 +89,7 @@ module.exports = function (RED) {
|
|
|
86
89
|
flashLong: this.flashLong,
|
|
87
90
|
transitionRateLimit: this.transitionRateLimit,
|
|
88
91
|
transitionHaUiTime: this.transitionHaUiTime,
|
|
92
|
+
dmxFloor: this.dmxFloor,
|
|
89
93
|
};
|
|
90
94
|
}
|
|
91
95
|
|
package/nodes/ha-mqtt-dmx.js
CHANGED
|
@@ -136,6 +136,7 @@ module.exports = function (RED) {
|
|
|
136
136
|
flashShort: cfg.flashShort,
|
|
137
137
|
flashLong: cfg.flashLong,
|
|
138
138
|
diskDelay: cfg.diskDelay,
|
|
139
|
+
dmxFloor: cfg.dmxFloor !== undefined ? cfg.dmxFloor : 3,
|
|
139
140
|
};
|
|
140
141
|
|
|
141
142
|
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
@@ -202,6 +203,9 @@ module.exports = function (RED) {
|
|
|
202
203
|
if (gamma === 0 && colorValue > 0 && brightness > 0 && S.minOutput > 0) {
|
|
203
204
|
return S.minOutput;
|
|
204
205
|
}
|
|
206
|
+
// DMX floor — snap up if above 0 but below hardware stable threshold
|
|
207
|
+
if (gamma > 0 && gamma < S.dmxFloor) return S.dmxFloor;
|
|
208
|
+
// Note: ceiling is handled by S.dmxLimiter in scaleToDmx above
|
|
205
209
|
return gamma;
|
|
206
210
|
}
|
|
207
211
|
|
|
@@ -285,12 +289,25 @@ module.exports = function (RED) {
|
|
|
285
289
|
const p = preEffectState;
|
|
286
290
|
preEffectState = null;
|
|
287
291
|
const channels = buildColorChannels(
|
|
288
|
-
p.brightness
|
|
289
|
-
p.
|
|
292
|
+
p.brightness !== undefined ? p.brightness : 255,
|
|
293
|
+
p.red !== undefined ? p.red : 255,
|
|
294
|
+
p.green !== undefined ? p.green : 255,
|
|
295
|
+
p.blue !== undefined ? p.blue : 255,
|
|
296
|
+
p.white !== undefined ? p.white : 255,
|
|
297
|
+
p.warmWhite !== undefined ? p.warmWhite : 0
|
|
290
298
|
);
|
|
291
299
|
sendDmxChannels(channels);
|
|
292
|
-
pubState({
|
|
293
|
-
|
|
300
|
+
pubState({
|
|
301
|
+
state: p.state || 'OFF',
|
|
302
|
+
color_mode: S.colorMode,
|
|
303
|
+
brightness: p.brightness,
|
|
304
|
+
color: { r: p.red, g: p.green, b: p.blue, w: p.white, ww: p.warmWhite }
|
|
305
|
+
});
|
|
306
|
+
if (p.state === 'ON') {
|
|
307
|
+
setStatus('green', 'dot', `${fixtureId} ON bright:${p.brightness}`);
|
|
308
|
+
} else {
|
|
309
|
+
setStatus('grey', 'ring', `${fixtureId} OFF`);
|
|
310
|
+
}
|
|
294
311
|
}
|
|
295
312
|
|
|
296
313
|
function startEffect(label, intervalMs, tickFn) {
|
package/nodes/ha-mqtt-relay.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-dmx-for-ha",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
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",
|