node-red-contrib-dmx-for-ha 0.1.4 → 0.1.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/nodes/ha-mqtt-button.html +9 -22
- package/nodes/ha-mqtt-button.js +22 -15
- package/nodes/ha-mqtt-dmx-group.html +9 -32
- package/nodes/ha-mqtt-dmx-group.js +30 -16
- package/nodes/ha-mqtt-dmx.html +7 -22
- package/nodes/ha-mqtt-dmx.js +30 -16
- package/nodes/ha-mqtt-pir.html +9 -22
- package/nodes/ha-mqtt-pir.js +21 -14
- package/nodes/ha-mqtt-relay.html +9 -22
- package/nodes/ha-mqtt-relay.js +30 -16
- package/package.json +1 -1
|
@@ -14,28 +14,13 @@
|
|
|
14
14
|
outputs: 0,
|
|
15
15
|
inputLabels: ['Input'],
|
|
16
16
|
button: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
success: function() { RED.notify('device:remove sent', 'success'); },
|
|
25
|
-
error: function() { RED.notify('Error sending remove', 'error'); }
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
confirm: {
|
|
30
|
-
label: 'Add',
|
|
31
|
-
onclick: function() {
|
|
32
|
-
$.ajax({
|
|
33
|
-
url: 'ha-mqtt-button/' + this.id + '/add',
|
|
34
|
-
type: 'POST',
|
|
35
|
-
success: function() { RED.notify('device:add sent', 'success'); },
|
|
36
|
-
error: function() { RED.notify('Error sending add', 'error'); }
|
|
37
|
-
});
|
|
38
|
-
}
|
|
17
|
+
onclick: function() {
|
|
18
|
+
$.ajax({
|
|
19
|
+
url: 'ha-mqtt-button/' + this.id + '/add',
|
|
20
|
+
type: 'POST',
|
|
21
|
+
success: function() { RED.notify('device:add sent','success'); },
|
|
22
|
+
error: function() { RED.notify('Error — check NR log','error'); }
|
|
23
|
+
});
|
|
39
24
|
}
|
|
40
25
|
},
|
|
41
26
|
paletteLabel: 'Button',
|
|
@@ -232,6 +217,8 @@
|
|
|
232
217
|
</span>
|
|
233
218
|
</div>
|
|
234
219
|
|
|
220
|
+
<div class="form-row">
|
|
221
|
+
|
|
235
222
|
<div class="form-row">
|
|
236
223
|
<div class="form-row">
|
|
237
224
|
<label for="node-input-config">
|
package/nodes/ha-mqtt-button.js
CHANGED
|
@@ -30,25 +30,18 @@ module.exports = function (RED) {
|
|
|
30
30
|
// Small delay to allow broker connection to stabilise
|
|
31
31
|
setTimeout(function () {
|
|
32
32
|
handleDeviceAdd();
|
|
33
|
-
},
|
|
33
|
+
}, 1500);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// Auto-discover if broker already connected on deploy
|
|
37
|
+
if (broker.connected) {
|
|
38
|
+
autoDiscover();
|
|
39
|
+
}
|
|
40
|
+
// Or wait for broker to connect
|
|
36
41
|
broker.on('connect', function () {
|
|
37
42
|
autoDiscover();
|
|
38
43
|
});
|
|
39
44
|
|
|
40
|
-
// ── HTTP endpoints for canvas buttons ─────────────────────────
|
|
41
|
-
RED.httpAdmin.post('/ha-mqtt-button/:id/add', RED.auth.needsPermission('ha-mqtt-button.write'), function(req, res) {
|
|
42
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
43
|
-
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
44
|
-
else res.sendStatus(404);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
RED.httpAdmin.post('/ha-mqtt-button/:id/remove', RED.auth.needsPermission('ha-mqtt-button.write'), function(req, res) {
|
|
48
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
49
|
-
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
50
|
-
else res.sendStatus(404);
|
|
51
|
-
});
|
|
52
45
|
|
|
53
46
|
|
|
54
47
|
|
|
@@ -108,7 +101,7 @@ module.exports = function (RED) {
|
|
|
108
101
|
name: `${S.buttonPosition} button ${S.situation} the ${cfg.zone} ${S.area} ${S.subLocation}`,
|
|
109
102
|
stat_t: statTopic,
|
|
110
103
|
off_delay: S.holdTime,
|
|
111
|
-
enabled_by_default:
|
|
104
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
112
105
|
icon: S.haIcon,
|
|
113
106
|
device: {
|
|
114
107
|
identifiers: `binary_sensor-${fixtureId}`,
|
|
@@ -130,7 +123,7 @@ module.exports = function (RED) {
|
|
|
130
123
|
name: `${S.buttonPosition} (UI) ${S.situation} the ${cfg.zone} ${S.area} ${S.subLocation}`,
|
|
131
124
|
cmd_t: uiBtnCmdTopic,
|
|
132
125
|
payload_press: 'PRESS',
|
|
133
|
-
enabled_by_default:
|
|
126
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
134
127
|
icon: S.haIcon,
|
|
135
128
|
device: { identifiers: `binary_sensor-${fixtureId}` },
|
|
136
129
|
};
|
|
@@ -189,5 +182,19 @@ module.exports = function (RED) {
|
|
|
189
182
|
});
|
|
190
183
|
}
|
|
191
184
|
|
|
185
|
+
|
|
186
|
+
// ── HTTP endpoints for canvas buttons — registered once at module level ──
|
|
187
|
+
RED.httpAdmin.post('/ha-mqtt-button/:id/add', RED.auth.needsPermission('ha-mqtt-button.write'), function(req, res) {
|
|
188
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
189
|
+
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
190
|
+
else res.sendStatus(404);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
RED.httpAdmin.post('/ha-mqtt-button/:id/remove', RED.auth.needsPermission('ha-mqtt-button.write'), function(req, res) {
|
|
194
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
195
|
+
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
196
|
+
else res.sendStatus(404);
|
|
197
|
+
});
|
|
198
|
+
|
|
192
199
|
RED.nodes.registerType('ha-mqtt-button', HaMqttButtonNode);
|
|
193
200
|
};
|
|
@@ -15,28 +15,13 @@
|
|
|
15
15
|
outputLabels: ['Link'],
|
|
16
16
|
inputLabels: ['Input'],
|
|
17
17
|
button: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
success: function() { RED.notify('device:remove sent', 'success'); },
|
|
26
|
-
error: function() { RED.notify('Error sending remove', 'error'); }
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
confirm: {
|
|
31
|
-
label: 'Add',
|
|
32
|
-
onclick: function() {
|
|
33
|
-
$.ajax({
|
|
34
|
-
url: 'ha-mqtt-dmx-group/' + this.id + '/add',
|
|
35
|
-
type: 'POST',
|
|
36
|
-
success: function() { RED.notify('device:add sent', 'success'); },
|
|
37
|
-
error: function() { RED.notify('Error sending add', 'error'); }
|
|
38
|
-
});
|
|
39
|
-
}
|
|
18
|
+
onclick: function() {
|
|
19
|
+
$.ajax({
|
|
20
|
+
url: 'ha-mqtt-dmx-group/' + this.id + '/add',
|
|
21
|
+
type: 'POST',
|
|
22
|
+
success: function() { RED.notify('device:add sent','success'); },
|
|
23
|
+
error: function() { RED.notify('Error — check NR log','error'); }
|
|
24
|
+
});
|
|
40
25
|
}
|
|
41
26
|
},
|
|
42
27
|
paletteLabel: 'DMX Group',
|
|
@@ -178,14 +163,7 @@
|
|
|
178
163
|
</div>
|
|
179
164
|
|
|
180
165
|
<!-- CONFIG -->
|
|
181
|
-
|
|
182
|
-
<label for="node-input-config">
|
|
183
|
-
<i class="fa fa-cog"></i> Config
|
|
184
|
-
</label>
|
|
185
|
-
<input type="text" id="node-input-config" />
|
|
186
|
-
</div>
|
|
187
|
-
|
|
188
|
-
<!-- Discovery Mode -->
|
|
166
|
+
<!-- Discovery Mode -->
|
|
189
167
|
<div class="form-row">
|
|
190
168
|
<label for="node-input-discoveryMode">
|
|
191
169
|
<i class="fa fa-toggle-on"></i> Discovery Mode
|
|
@@ -201,7 +179,6 @@
|
|
|
201
179
|
</div>
|
|
202
180
|
</div>
|
|
203
181
|
|
|
204
|
-
|
|
205
182
|
<hr/>
|
|
206
183
|
|
|
207
184
|
<!-- ── GROUP (* Required) ────────────────────────────────── -->
|
|
@@ -292,6 +269,7 @@
|
|
|
292
269
|
</div>
|
|
293
270
|
|
|
294
271
|
<!-- CONFIG -->
|
|
272
|
+
<!-- Area -->
|
|
295
273
|
<div class="form-row">
|
|
296
274
|
<label for="node-input-config">
|
|
297
275
|
<i class="fa fa-cog"></i> Config
|
|
@@ -299,7 +277,6 @@
|
|
|
299
277
|
<input type="text" id="node-input-config" />
|
|
300
278
|
</div>
|
|
301
279
|
|
|
302
|
-
<!-- Area -->
|
|
303
280
|
<div class="form-row">
|
|
304
281
|
<label for="node-input-area">
|
|
305
282
|
<i class="fa fa-map-marker"></i> Area
|
|
@@ -33,25 +33,18 @@ module.exports = function (RED) {
|
|
|
33
33
|
// Small delay to allow broker connection to stabilise
|
|
34
34
|
setTimeout(function () {
|
|
35
35
|
handleDeviceAdd();
|
|
36
|
-
},
|
|
36
|
+
}, 1500);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// Auto-discover if broker already connected on deploy
|
|
40
|
+
if (broker.connected) {
|
|
41
|
+
autoDiscover();
|
|
42
|
+
}
|
|
43
|
+
// Or wait for broker to connect
|
|
39
44
|
broker.on('connect', function () {
|
|
40
45
|
autoDiscover();
|
|
41
46
|
});
|
|
42
47
|
|
|
43
|
-
// ── HTTP endpoints for canvas buttons ─────────────────────────
|
|
44
|
-
RED.httpAdmin.post('/ha-mqtt-dmx-group/:id/add', RED.auth.needsPermission('ha-mqtt-dmx-group.write'), function(req, res) {
|
|
45
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
46
|
-
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
47
|
-
else res.sendStatus(404);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
RED.httpAdmin.post('/ha-mqtt-dmx-group/:id/remove', RED.auth.needsPermission('ha-mqtt-dmx-group.write'), function(req, res) {
|
|
51
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
52
|
-
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
53
|
-
else res.sendStatus(404);
|
|
54
|
-
});
|
|
55
48
|
|
|
56
49
|
|
|
57
50
|
|
|
@@ -85,12 +78,19 @@ module.exports = function (RED) {
|
|
|
85
78
|
const cmdTopic = `${groupTopic}/${cfg.commandTopic}`;
|
|
86
79
|
|
|
87
80
|
// ── Context helpers ───────────────────────────────────────
|
|
81
|
+
// Check disk store available once on startup
|
|
82
|
+
let diskAvailable = false;
|
|
83
|
+
try { node.context().get('__test', 'disk'); diskAvailable = true; }
|
|
84
|
+
catch(e) { diskAvailable = false; }
|
|
85
|
+
|
|
88
86
|
function ctxGet(key, store) {
|
|
89
|
-
|
|
87
|
+
if (store === 'disk' && !diskAvailable) return node.context().get(key);
|
|
88
|
+
try { return node.context().get(key, store || undefined); }
|
|
90
89
|
catch(e) { return node.context().get(key); }
|
|
91
90
|
}
|
|
92
91
|
function ctxSet(key, val, store) {
|
|
93
|
-
|
|
92
|
+
if (store === 'disk' && !diskAvailable) { node.context().set(key, val); return; }
|
|
93
|
+
try { node.context().set(key, val, store || undefined); }
|
|
94
94
|
catch(e) { node.context().set(key, val); }
|
|
95
95
|
}
|
|
96
96
|
function recall(ramKey, diskKey, fallback) {
|
|
@@ -185,7 +185,7 @@ module.exports = function (RED) {
|
|
|
185
185
|
schema: 'json',
|
|
186
186
|
object_id: objectId,
|
|
187
187
|
optimistic: false,
|
|
188
|
-
enabled_by_default:
|
|
188
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
189
189
|
icon: S.haIcon,
|
|
190
190
|
supported_color_modes: [S.colorMode],
|
|
191
191
|
brightness: true,
|
|
@@ -296,5 +296,19 @@ module.exports = function (RED) {
|
|
|
296
296
|
});
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
|
|
300
|
+
// ── HTTP endpoints for canvas buttons — registered once at module level ──
|
|
301
|
+
RED.httpAdmin.post('/ha-mqtt-dmx-group/:id/add', RED.auth.needsPermission('ha-mqtt-dmx-group.write'), function(req, res) {
|
|
302
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
303
|
+
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
304
|
+
else res.sendStatus(404);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
RED.httpAdmin.post('/ha-mqtt-dmx-group/:id/remove', RED.auth.needsPermission('ha-mqtt-dmx-group.write'), function(req, res) {
|
|
308
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
309
|
+
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
310
|
+
else res.sendStatus(404);
|
|
311
|
+
});
|
|
312
|
+
|
|
299
313
|
RED.nodes.registerType('ha-mqtt-dmx-group', HaMqttDmxGroupNode);
|
|
300
314
|
};
|
package/nodes/ha-mqtt-dmx.html
CHANGED
|
@@ -123,28 +123,13 @@
|
|
|
123
123
|
inputs: 1,
|
|
124
124
|
outputs: 0,
|
|
125
125
|
button: {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
success: function() { RED.notify('device:remove sent', 'success'); },
|
|
134
|
-
error: function() { RED.notify('Error sending remove', 'error'); }
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
confirm: {
|
|
139
|
-
label: 'Add',
|
|
140
|
-
onclick: function() {
|
|
141
|
-
$.ajax({
|
|
142
|
-
url: 'ha-mqtt-dmx/' + this.id + '/add',
|
|
143
|
-
type: 'POST',
|
|
144
|
-
success: function() { RED.notify('device:add sent', 'success'); },
|
|
145
|
-
error: function() { RED.notify('Error sending add', 'error'); }
|
|
146
|
-
});
|
|
147
|
-
}
|
|
126
|
+
onclick: function() {
|
|
127
|
+
$.ajax({
|
|
128
|
+
url: 'ha-mqtt-dmx/' + this.id + '/add',
|
|
129
|
+
type: 'POST',
|
|
130
|
+
success: function() { RED.notify('device:add sent','success'); },
|
|
131
|
+
error: function() { RED.notify('Error — check NR log','error'); }
|
|
132
|
+
});
|
|
148
133
|
}
|
|
149
134
|
},
|
|
150
135
|
paletteLabel: 'DMX',
|
package/nodes/ha-mqtt-dmx.js
CHANGED
|
@@ -40,25 +40,18 @@ module.exports = function (RED) {
|
|
|
40
40
|
// Small delay to allow broker connection to stabilise
|
|
41
41
|
setTimeout(function () {
|
|
42
42
|
handleDeviceAdd();
|
|
43
|
-
},
|
|
43
|
+
}, 1500);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// Auto-discover if broker already connected on deploy
|
|
47
|
+
if (broker.connected) {
|
|
48
|
+
autoDiscover();
|
|
49
|
+
}
|
|
50
|
+
// Or wait for broker to connect
|
|
46
51
|
broker.on('connect', function () {
|
|
47
52
|
autoDiscover();
|
|
48
53
|
});
|
|
49
54
|
|
|
50
|
-
// ── HTTP endpoints for canvas buttons ─────────────────────────
|
|
51
|
-
RED.httpAdmin.post('/ha-mqtt-dmx/:id/add', RED.auth.needsPermission('ha-mqtt-dmx.write'), function(req, res) {
|
|
52
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
53
|
-
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
54
|
-
else res.sendStatus(404);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
RED.httpAdmin.post('/ha-mqtt-dmx/:id/remove', RED.auth.needsPermission('ha-mqtt-dmx.write'), function(req, res) {
|
|
58
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
59
|
-
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
60
|
-
else res.sendStatus(404);
|
|
61
|
-
});
|
|
62
55
|
|
|
63
56
|
|
|
64
57
|
|
|
@@ -106,12 +99,19 @@ module.exports = function (RED) {
|
|
|
106
99
|
const dmxTopic = `${cfg.siteId}/${cfg.zone}/dmx/${S.universe}`;
|
|
107
100
|
|
|
108
101
|
// ── Context helpers ───────────────────────────────────────
|
|
102
|
+
// Check disk store available once on startup
|
|
103
|
+
let diskAvailable = false;
|
|
104
|
+
try { node.context().get('__test', 'disk'); diskAvailable = true; }
|
|
105
|
+
catch(e) { diskAvailable = false; }
|
|
106
|
+
|
|
109
107
|
function ctxGet(key, store) {
|
|
110
|
-
|
|
108
|
+
if (store === 'disk' && !diskAvailable) return node.context().get(key);
|
|
109
|
+
try { return node.context().get(key, store || undefined); }
|
|
111
110
|
catch(e) { return node.context().get(key); }
|
|
112
111
|
}
|
|
113
112
|
function ctxSet(key, val, store) {
|
|
114
|
-
|
|
113
|
+
if (store === 'disk' && !diskAvailable) { node.context().set(key, val); return; }
|
|
114
|
+
try { node.context().set(key, val, store || undefined); }
|
|
115
115
|
catch(e) { node.context().set(key, val); }
|
|
116
116
|
}
|
|
117
117
|
function recall(ramKey, diskKey, fallback) {
|
|
@@ -443,7 +443,7 @@ module.exports = function (RED) {
|
|
|
443
443
|
schema: 'json',
|
|
444
444
|
object_id: objectId,
|
|
445
445
|
optimistic: false,
|
|
446
|
-
enabled_by_default:
|
|
446
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
447
447
|
icon: S.haIcon,
|
|
448
448
|
supported_color_modes: [S.colorMode],
|
|
449
449
|
brightness: true,
|
|
@@ -568,5 +568,19 @@ module.exports = function (RED) {
|
|
|
568
568
|
});
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
+
|
|
572
|
+
// ── HTTP endpoints for canvas buttons — registered once at module level ──
|
|
573
|
+
RED.httpAdmin.post('/ha-mqtt-dmx/:id/add', RED.auth.needsPermission('ha-mqtt-dmx.write'), function(req, res) {
|
|
574
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
575
|
+
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
576
|
+
else res.sendStatus(404);
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
RED.httpAdmin.post('/ha-mqtt-dmx/:id/remove', RED.auth.needsPermission('ha-mqtt-dmx.write'), function(req, res) {
|
|
580
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
581
|
+
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
582
|
+
else res.sendStatus(404);
|
|
583
|
+
});
|
|
584
|
+
|
|
571
585
|
RED.nodes.registerType('ha-mqtt-dmx', HaMqttDmxNode);
|
|
572
586
|
};
|
package/nodes/ha-mqtt-pir.html
CHANGED
|
@@ -14,28 +14,13 @@
|
|
|
14
14
|
outputs: 0,
|
|
15
15
|
inputLabels: ['Input'],
|
|
16
16
|
button: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
success: function() { RED.notify('device:remove sent', 'success'); },
|
|
25
|
-
error: function() { RED.notify('Error sending remove', 'error'); }
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
confirm: {
|
|
30
|
-
label: 'Add',
|
|
31
|
-
onclick: function() {
|
|
32
|
-
$.ajax({
|
|
33
|
-
url: 'ha-mqtt-pir/' + this.id + '/add',
|
|
34
|
-
type: 'POST',
|
|
35
|
-
success: function() { RED.notify('device:add sent', 'success'); },
|
|
36
|
-
error: function() { RED.notify('Error sending add', 'error'); }
|
|
37
|
-
});
|
|
38
|
-
}
|
|
17
|
+
onclick: function() {
|
|
18
|
+
$.ajax({
|
|
19
|
+
url: 'ha-mqtt-pir/' + this.id + '/add',
|
|
20
|
+
type: 'POST',
|
|
21
|
+
success: function() { RED.notify('device:add sent','success'); },
|
|
22
|
+
error: function() { RED.notify('Error — check NR log','error'); }
|
|
23
|
+
});
|
|
39
24
|
}
|
|
40
25
|
},
|
|
41
26
|
paletteLabel: 'PIR',
|
|
@@ -246,6 +231,8 @@
|
|
|
246
231
|
</select>
|
|
247
232
|
</div>
|
|
248
233
|
|
|
234
|
+
<div class="form-row">
|
|
235
|
+
|
|
249
236
|
<div class="form-row">
|
|
250
237
|
<div class="form-row">
|
|
251
238
|
<label for="node-input-config">
|
package/nodes/ha-mqtt-pir.js
CHANGED
|
@@ -30,25 +30,18 @@ module.exports = function (RED) {
|
|
|
30
30
|
// Small delay to allow broker connection to stabilise
|
|
31
31
|
setTimeout(function () {
|
|
32
32
|
handleDeviceAdd();
|
|
33
|
-
},
|
|
33
|
+
}, 1500);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// Auto-discover if broker already connected on deploy
|
|
37
|
+
if (broker.connected) {
|
|
38
|
+
autoDiscover();
|
|
39
|
+
}
|
|
40
|
+
// Or wait for broker to connect
|
|
36
41
|
broker.on('connect', function () {
|
|
37
42
|
autoDiscover();
|
|
38
43
|
});
|
|
39
44
|
|
|
40
|
-
// ── HTTP endpoints for canvas buttons ─────────────────────────
|
|
41
|
-
RED.httpAdmin.post('/ha-mqtt-pir/:id/add', RED.auth.needsPermission('ha-mqtt-pir.write'), function(req, res) {
|
|
42
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
43
|
-
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
44
|
-
else res.sendStatus(404);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
RED.httpAdmin.post('/ha-mqtt-pir/:id/remove', RED.auth.needsPermission('ha-mqtt-pir.write'), function(req, res) {
|
|
48
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
49
|
-
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
50
|
-
else res.sendStatus(404);
|
|
51
|
-
});
|
|
52
45
|
|
|
53
46
|
|
|
54
47
|
|
|
@@ -149,7 +142,7 @@ module.exports = function (RED) {
|
|
|
149
142
|
payload_not_available: 'offline',
|
|
150
143
|
off_delay: S.holdTime,
|
|
151
144
|
device_class: 'motion',
|
|
152
|
-
enabled_by_default:
|
|
145
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
153
146
|
icon: S.haIcon,
|
|
154
147
|
device: {
|
|
155
148
|
identifiers: `binary_sensor-${fixtureId}`,
|
|
@@ -214,5 +207,19 @@ module.exports = function (RED) {
|
|
|
214
207
|
});
|
|
215
208
|
}
|
|
216
209
|
|
|
210
|
+
|
|
211
|
+
// ── HTTP endpoints for canvas buttons — registered once at module level ──
|
|
212
|
+
RED.httpAdmin.post('/ha-mqtt-pir/:id/add', RED.auth.needsPermission('ha-mqtt-pir.write'), function(req, res) {
|
|
213
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
214
|
+
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
215
|
+
else res.sendStatus(404);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
RED.httpAdmin.post('/ha-mqtt-pir/:id/remove', RED.auth.needsPermission('ha-mqtt-pir.write'), function(req, res) {
|
|
219
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
220
|
+
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
221
|
+
else res.sendStatus(404);
|
|
222
|
+
});
|
|
223
|
+
|
|
217
224
|
RED.nodes.registerType('ha-mqtt-pir', HaMqttPirNode);
|
|
218
225
|
};
|
package/nodes/ha-mqtt-relay.html
CHANGED
|
@@ -14,28 +14,13 @@
|
|
|
14
14
|
outputs: 0,
|
|
15
15
|
inputLabels: ['Input'],
|
|
16
16
|
button: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
success: function() { RED.notify('device:remove sent', 'success'); },
|
|
25
|
-
error: function() { RED.notify('Error sending remove', 'error'); }
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
confirm: {
|
|
30
|
-
label: 'Add',
|
|
31
|
-
onclick: function() {
|
|
32
|
-
$.ajax({
|
|
33
|
-
url: 'ha-mqtt-relay/' + this.id + '/add',
|
|
34
|
-
type: 'POST',
|
|
35
|
-
success: function() { RED.notify('device:add sent', 'success'); },
|
|
36
|
-
error: function() { RED.notify('Error sending add', 'error'); }
|
|
37
|
-
});
|
|
38
|
-
}
|
|
17
|
+
onclick: function() {
|
|
18
|
+
$.ajax({
|
|
19
|
+
url: 'ha-mqtt-relay/' + this.id + '/add',
|
|
20
|
+
type: 'POST',
|
|
21
|
+
success: function() { RED.notify('device:add sent','success'); },
|
|
22
|
+
error: function() { RED.notify('Error — check NR log','error'); }
|
|
23
|
+
});
|
|
39
24
|
}
|
|
40
25
|
},
|
|
41
26
|
paletteLabel: 'Relay',
|
|
@@ -248,6 +233,8 @@
|
|
|
248
233
|
</span>
|
|
249
234
|
</div>
|
|
250
235
|
|
|
236
|
+
<div class="form-row">
|
|
237
|
+
|
|
251
238
|
<div class="form-row">
|
|
252
239
|
<div class="form-row">
|
|
253
240
|
<label for="node-input-config">
|
package/nodes/ha-mqtt-relay.js
CHANGED
|
@@ -33,25 +33,18 @@ module.exports = function (RED) {
|
|
|
33
33
|
// Small delay to allow broker connection to stabilise
|
|
34
34
|
setTimeout(function () {
|
|
35
35
|
handleDeviceAdd();
|
|
36
|
-
},
|
|
36
|
+
}, 1500);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// Auto-discover if broker already connected on deploy
|
|
40
|
+
if (broker.connected) {
|
|
41
|
+
autoDiscover();
|
|
42
|
+
}
|
|
43
|
+
// Or wait for broker to connect
|
|
39
44
|
broker.on('connect', function () {
|
|
40
45
|
autoDiscover();
|
|
41
46
|
});
|
|
42
47
|
|
|
43
|
-
// ── HTTP endpoints for canvas buttons ─────────────────────────
|
|
44
|
-
RED.httpAdmin.post('/ha-mqtt-relay/:id/add', RED.auth.needsPermission('ha-mqtt-relay.write'), function(req, res) {
|
|
45
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
46
|
-
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
47
|
-
else res.sendStatus(404);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
RED.httpAdmin.post('/ha-mqtt-relay/:id/remove', RED.auth.needsPermission('ha-mqtt-relay.write'), function(req, res) {
|
|
51
|
-
const n = RED.nodes.getNode(req.params.id);
|
|
52
|
-
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
53
|
-
else res.sendStatus(404);
|
|
54
|
-
});
|
|
55
48
|
|
|
56
49
|
|
|
57
50
|
|
|
@@ -86,12 +79,19 @@ module.exports = function (RED) {
|
|
|
86
79
|
const relayTopic = `${cfg.siteId}/${cfg.zone}/${S.controllerNum}/${S.mqttSegment}/${S.relayNum}`;
|
|
87
80
|
|
|
88
81
|
// ── Context helpers ───────────────────────────────────────
|
|
82
|
+
// Check disk store available once on startup
|
|
83
|
+
let diskAvailable = false;
|
|
84
|
+
try { node.context().get('__test', 'disk'); diskAvailable = true; }
|
|
85
|
+
catch(e) { diskAvailable = false; }
|
|
86
|
+
|
|
89
87
|
function ctxGet(key, store) {
|
|
90
|
-
|
|
88
|
+
if (store === 'disk' && !diskAvailable) return node.context().get(key);
|
|
89
|
+
try { return node.context().get(key, store || undefined); }
|
|
91
90
|
catch(e) { return node.context().get(key); }
|
|
92
91
|
}
|
|
93
92
|
function ctxSet(key, val, store) {
|
|
94
|
-
|
|
93
|
+
if (store === 'disk' && !diskAvailable) { node.context().set(key, val); return; }
|
|
94
|
+
try { node.context().set(key, val, store || undefined); }
|
|
95
95
|
catch(e) { node.context().set(key, val); }
|
|
96
96
|
}
|
|
97
97
|
function recall(ramKey, diskKey, fallback) {
|
|
@@ -216,7 +216,7 @@ module.exports = function (RED) {
|
|
|
216
216
|
cmd_t: cmdTopic,
|
|
217
217
|
stat_t: statTopic,
|
|
218
218
|
optimistic: false,
|
|
219
|
-
enabled_by_default:
|
|
219
|
+
enabled_by_default: (discoveryMode !== 'hidden'),
|
|
220
220
|
icon: S.haIcon,
|
|
221
221
|
supported_color_modes: ['onoff'],
|
|
222
222
|
brightness: false,
|
|
@@ -320,5 +320,19 @@ module.exports = function (RED) {
|
|
|
320
320
|
});
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
|
|
324
|
+
// ── HTTP endpoints for canvas buttons — registered once at module level ──
|
|
325
|
+
RED.httpAdmin.post('/ha-mqtt-relay/:id/add', RED.auth.needsPermission('ha-mqtt-relay.write'), function(req, res) {
|
|
326
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
327
|
+
if (n) { n.receive({ device: 'add' }); res.sendStatus(200); }
|
|
328
|
+
else res.sendStatus(404);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
RED.httpAdmin.post('/ha-mqtt-relay/:id/remove', RED.auth.needsPermission('ha-mqtt-relay.write'), function(req, res) {
|
|
332
|
+
const n = RED.nodes.getNode(req.params.id);
|
|
333
|
+
if (n) { n.receive({ device: 'remove' }); res.sendStatus(200); }
|
|
334
|
+
else res.sendStatus(404);
|
|
335
|
+
});
|
|
336
|
+
|
|
323
337
|
RED.nodes.registerType('ha-mqtt-relay', HaMqttRelayNode);
|
|
324
338
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-dmx-for-ha",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.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",
|