node-red-contrib-dmx-for-ha 0.4.3 → 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 +218 -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 +26 -5
- package/nodes/ha-mqtt-relay.js +6 -1
- 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
|
|
|
@@ -270,6 +352,127 @@ Set to `0` to make all un-timed commands instant.
|
|
|
270
352
|
|
|
271
353
|
---
|
|
272
354
|
|
|
355
|
+
## Context store — finding your files
|
|
356
|
+
|
|
357
|
+
This is one of the most common questions with Node-RED on Home Assistant. The context store files are **not** where you expect them.
|
|
358
|
+
|
|
359
|
+
### Where are the files?
|
|
360
|
+
|
|
361
|
+
The NR add-on runs in its own Docker container with an isolated config directory. This is **separate** from the main HA config you see via Samba.
|
|
362
|
+
|
|
363
|
+
| What you see | Actual path on host |
|
|
364
|
+
|---|---|
|
|
365
|
+
| Samba `\\{haip}\config\` | HA config — flows, automations etc. |
|
|
366
|
+
| NR add-on config | `/addon_configs/a0d7b954_nodered/` |
|
|
367
|
+
| Context store files | `/addon_configs/a0d7b954_nodered/nodeRED/context_stores/context/` |
|
|
368
|
+
|
|
369
|
+
The NR add-on config directory is **not accessible via Samba** — this trips everyone up.
|
|
370
|
+
|
|
371
|
+
### How to find your context files
|
|
372
|
+
|
|
373
|
+
Use the **Studio Code Server** add-on (VS Code in HA):
|
|
374
|
+
|
|
375
|
+
1. Install Studio Code Server from the add-on store if not already installed
|
|
376
|
+
2. Open it: Settings → Add-ons → Studio Code Server → Open Web UI
|
|
377
|
+
3. Open a terminal: Terminal → New Terminal
|
|
378
|
+
4. Run:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
find / -name "*.json" -path "*context*" 2>/dev/null | grep -v proc
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
You should see something like:
|
|
385
|
+
```
|
|
386
|
+
/addon_configs/a0d7b954_nodered/nodeRED/context_stores/context/7e2467f26a0693a0/dd6582b967f0314a.json
|
|
387
|
+
/addon_configs/a0d7b954_nodered/nodeRED/context_stores/context/7e2467f26a0693a0/75b10249fcbfd224.json
|
|
388
|
+
...
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
One `.json` file per node, named by node ID.
|
|
392
|
+
|
|
393
|
+
### Reading a context file
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
cat "/addon_configs/a0d7b954_nodered/nodeRED/context_stores/context/{flowId}/{nodeId}.json"
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
A healthy file looks like:
|
|
400
|
+
```json
|
|
401
|
+
{
|
|
402
|
+
"state": "ON",
|
|
403
|
+
"brightness": 255,
|
|
404
|
+
"red": 255,
|
|
405
|
+
"green": 255,
|
|
406
|
+
"blue": 255,
|
|
407
|
+
"white": 255,
|
|
408
|
+
"warmWhite": 0
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Important: NR adds a `/context/` subfolder
|
|
413
|
+
|
|
414
|
+
When you set `dir` in your context store config, NR automatically appends `/context/` to it. So:
|
|
415
|
+
|
|
416
|
+
```javascript
|
|
417
|
+
// You set:
|
|
418
|
+
config: { dir: '/config/nodeRED/context_stores' }
|
|
419
|
+
|
|
420
|
+
// NR actually writes to:
|
|
421
|
+
// /config/nodeRED/context_stores/context/
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Recommended config.js settings
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
contextStorage: {
|
|
428
|
+
memory: { module: 'memory' },
|
|
429
|
+
disk_values: {
|
|
430
|
+
module: 'localfilesystem',
|
|
431
|
+
config: {
|
|
432
|
+
dir: '/config/nodeRED/context_stores',
|
|
433
|
+
flushInterval: 5 // Write to disk every 5 seconds (default is 30)
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
disk_meta: {
|
|
437
|
+
module: 'localfilesystem',
|
|
438
|
+
config: {
|
|
439
|
+
dir: '/config/nodeRED/context_stores',
|
|
440
|
+
flushInterval: 5
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
default: { module: 'memory' },
|
|
444
|
+
},
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Important:** Use an **absolute path** starting with `/config/`. A relative path will silently resolve to the wrong location and nothing will be saved.
|
|
448
|
+
|
|
449
|
+
`flushInterval: 5` means NR writes to disk every 5 seconds instead of the default 30. This reduces the window of data loss on unexpected shutdown — after turning a light on, wait 5 seconds before restarting.
|
|
450
|
+
|
|
451
|
+
### Verifying context store is working
|
|
452
|
+
|
|
453
|
+
After saving a state and waiting 5+ seconds, check your files appeared:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
ls "/addon_configs/a0d7b954_nodered/nodeRED/context_stores/context/"
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
If the directory is empty or doesn't exist — check your `config.js` path is absolute and restart NR.
|
|
460
|
+
|
|
461
|
+
### NR startup log confirmation
|
|
462
|
+
|
|
463
|
+
On every startup NR logs which context stores loaded:
|
|
464
|
+
|
|
465
|
+
```
|
|
466
|
+
Context store : 'memory' [module=memory]
|
|
467
|
+
Context store : 'disk_values' [module=localfilesystem]
|
|
468
|
+
Context store : 'disk_meta' [module=localfilesystem]
|
|
469
|
+
Context store : 'default' [module=memory]
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
If `disk_values` shows `[module=memory]` — your config.js change didn't take effect.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
273
476
|
## Troubleshooting
|
|
274
477
|
|
|
275
478
|
**Nodes don't appear in palette** — Restart Node-RED. Check log for errors.
|
|
@@ -290,7 +493,15 @@ Set to `0` to make all un-timed commands instant.
|
|
|
290
493
|
|
|
291
494
|
| Version | Changes |
|
|
292
495
|
|---|---|
|
|
293
|
-
| 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 |
|
|
294
505
|
| 0.3.5 | Fix debug mode block initialisation order (S before debug) |
|
|
295
506
|
| 0.3.4 | Debug hint text updated — notes 12hr auto-disable |
|
|
296
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) {
|
|
@@ -670,7 +687,11 @@ module.exports = function (RED) {
|
|
|
670
687
|
sendDmxChannels(buildColorChannels(0, r, g, b, w, ww));
|
|
671
688
|
}
|
|
672
689
|
pubState({ state, color_mode: S.colorMode, brightness, color: { r, g, b, w, ww } });
|
|
673
|
-
|
|
690
|
+
if (state === 'ON') {
|
|
691
|
+
setStatus('green', 'dot', `${fixtureId} ON bright:${brightness}`);
|
|
692
|
+
} else {
|
|
693
|
+
setStatus('grey', 'ring', `${fixtureId} OFF`);
|
|
694
|
+
}
|
|
674
695
|
node.log(`${fixtureId} recovery — state:${state}`);
|
|
675
696
|
}, 2000);
|
|
676
697
|
}
|
package/nodes/ha-mqtt-relay.js
CHANGED
|
@@ -112,6 +112,7 @@ module.exports = function (RED) {
|
|
|
112
112
|
flashShort: cfg.flashShort,
|
|
113
113
|
flashLong: cfg.flashLong,
|
|
114
114
|
diskDelay: cfg.diskDelay,
|
|
115
|
+
debugMode: config.debugMode === true,
|
|
115
116
|
};
|
|
116
117
|
|
|
117
118
|
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
@@ -323,7 +324,11 @@ module.exports = function (RED) {
|
|
|
323
324
|
const state = recall('state', 'state_disk', S.defaultState);
|
|
324
325
|
pubRelay(state === 'ON' ? 1 : 0);
|
|
325
326
|
pubState(state);
|
|
326
|
-
|
|
327
|
+
if (state === 'ON') {
|
|
328
|
+
setStatus('green', 'dot', `${fixtureId} ON`);
|
|
329
|
+
} else {
|
|
330
|
+
setStatus('grey', 'ring', `${fixtureId} OFF`);
|
|
331
|
+
}
|
|
327
332
|
node.log(`${fixtureId} recovery — state:${state}`);
|
|
328
333
|
}, 2000);
|
|
329
334
|
}
|
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",
|