node-red-contrib-dmx-for-ha 0.3.0 → 0.3.5
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 +1 -1
- package/nodes/ha-mqtt-button.js +36 -11
- package/nodes/ha-mqtt-dmx-group.html +1 -1
- package/nodes/ha-mqtt-dmx-group.js +36 -9
- package/nodes/ha-mqtt-dmx.html +1 -1
- package/nodes/ha-mqtt-dmx.js +38 -12
- package/nodes/ha-mqtt-pir.html +1 -1
- package/nodes/ha-mqtt-pir.js +35 -9
- package/nodes/ha-mqtt-relay.html +1 -1
- package/nodes/ha-mqtt-relay.js +36 -10
- package/package.json +1 -1
|
@@ -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
|
|
package/nodes/ha-mqtt-button.js
CHANGED
|
@@ -37,14 +37,32 @@ module.exports = function (RED) {
|
|
|
37
37
|
}, 1500);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// Track
|
|
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,15 @@ 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
|
+
|
|
83
|
+
|
|
63
84
|
// Fallback — if connect event already fired before listener registered
|
|
64
85
|
setTimeout(function () {
|
|
65
86
|
_tryDiscover();
|
|
@@ -86,14 +107,18 @@ module.exports = function (RED) {
|
|
|
86
107
|
debugMode: config.debugMode === true,
|
|
87
108
|
};
|
|
88
109
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
111
|
+
if (S.debugMode) {
|
|
112
|
+
setStatus('red', 'dot', `ha-mqtt-button "${fixtureId}" ⚠ DEBUG MODE ON`);
|
|
113
|
+
node.warn(`[DEBUG] ha-mqtt-button "${fixtureId}" — debug mode is enabled. Disable in production.`);
|
|
114
|
+
setTimeout(function () {
|
|
115
|
+
if (S.debugMode) {
|
|
116
|
+
S.debugMode = false;
|
|
117
|
+
node.warn(`[DEBUG] ha-mqtt-button "${fixtureId}" — debug mode auto-disabled after 12 hours`);
|
|
118
|
+
setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
|
|
119
|
+
}
|
|
120
|
+
}, 12 * 60 * 60 * 1000);
|
|
121
|
+
}
|
|
97
122
|
|
|
98
123
|
// ── Helpers ───────────────────────────────────────────────
|
|
99
124
|
function pub(topic, payload, retain) {
|
|
@@ -104,7 +129,7 @@ module.exports = function (RED) {
|
|
|
104
129
|
qos: cfg.qos,
|
|
105
130
|
retain: retain !== undefined ? retain : cfg.retain,
|
|
106
131
|
});
|
|
107
|
-
if (S.debugMode) node.
|
|
132
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
|
|
108
133
|
}
|
|
109
134
|
|
|
110
135
|
function setStatus(fill, shape, text) {
|
|
@@ -190,7 +215,7 @@ module.exports = function (RED) {
|
|
|
190
215
|
|
|
191
216
|
if (devReq) {
|
|
192
217
|
switch (devReq) {
|
|
193
|
-
case 'add':
|
|
218
|
+
case 'add': _manualDiscover(); break;
|
|
194
219
|
case 'remove': handleDeviceRemove(); break;
|
|
195
220
|
default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
|
|
196
221
|
}
|
|
@@ -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
|
|
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,15 @@ 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
|
+
|
|
86
|
+
|
|
66
87
|
// Fallback — if connect event already fired before listener registered
|
|
67
88
|
setTimeout(function () {
|
|
68
89
|
_tryDiscover();
|
|
@@ -93,12 +114,18 @@ module.exports = function (RED) {
|
|
|
93
114
|
diskDelay: cfg.diskDelay,
|
|
94
115
|
};
|
|
95
116
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
118
|
+
if (S.debugMode) {
|
|
119
|
+
setStatus('red', 'dot', `ha-mqtt-dmx-group "${groupId}" ⚠ DEBUG MODE ON`);
|
|
120
|
+
node.warn(`[DEBUG] ha-mqtt-dmx-group "${groupId}" — debug mode is enabled. Disable in production.`);
|
|
121
|
+
setTimeout(function () {
|
|
122
|
+
if (S.debugMode) {
|
|
123
|
+
S.debugMode = false;
|
|
124
|
+
node.warn(`[DEBUG] ha-mqtt-dmx-group "${groupId}" — debug mode auto-disabled after 12 hours`);
|
|
125
|
+
setStatus('yellow', 'ring', `${groupId} ready — awaiting HA`);
|
|
126
|
+
}
|
|
127
|
+
}, 12 * 60 * 60 * 1000);
|
|
128
|
+
}
|
|
102
129
|
|
|
103
130
|
// ── Context helpers ───────────────────────────────────────
|
|
104
131
|
// Check disk store available once on startup
|
|
@@ -136,7 +163,7 @@ module.exports = function (RED) {
|
|
|
136
163
|
qos: cfg.qos,
|
|
137
164
|
retain: retain !== undefined ? retain : cfg.retain,
|
|
138
165
|
});
|
|
139
|
-
if (S.debugMode) node.
|
|
166
|
+
if (S.debugMode) node.warn(`[DEBUG] ${groupId} → ${topic} ${strPayload.substring(0, 120)}`);
|
|
140
167
|
}
|
|
141
168
|
|
|
142
169
|
function pubState(payload) {
|
|
@@ -303,7 +330,7 @@ module.exports = function (RED) {
|
|
|
303
330
|
|
|
304
331
|
if (devReq) {
|
|
305
332
|
switch (devReq) {
|
|
306
|
-
case 'add':
|
|
333
|
+
case 'add': _manualDiscover(); break;
|
|
307
334
|
case 'remove': handleDeviceRemove(null); break;
|
|
308
335
|
default: node.warn(`${groupId} — unknown device.request: "${devReq}"`);
|
|
309
336
|
}
|
package/nodes/ha-mqtt-dmx.html
CHANGED
|
@@ -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
|
|
package/nodes/ha-mqtt-dmx.js
CHANGED
|
@@ -47,14 +47,32 @@ module.exports = function (RED) {
|
|
|
47
47
|
}, 1500);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// Track
|
|
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,15 @@ 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
|
+
|
|
93
|
+
|
|
73
94
|
// Fallback — if connect event already fired before listener registered
|
|
74
95
|
setTimeout(function () {
|
|
75
96
|
_tryDiscover();
|
|
@@ -117,13 +138,18 @@ module.exports = function (RED) {
|
|
|
117
138
|
diskDelay: cfg.diskDelay,
|
|
118
139
|
};
|
|
119
140
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
141
|
+
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
142
|
+
if (S.debugMode) {
|
|
143
|
+
setStatus('red', 'dot', `ha-mqtt-dmx "${fixtureId}" ⚠ DEBUG MODE ON`);
|
|
144
|
+
node.warn(`[DEBUG] ha-mqtt-dmx "${fixtureId}" — debug mode is enabled. Disable in production.`);
|
|
145
|
+
setTimeout(function () {
|
|
146
|
+
if (S.debugMode) {
|
|
147
|
+
S.debugMode = false;
|
|
148
|
+
node.warn(`[DEBUG] ha-mqtt-dmx "${fixtureId}" — debug mode auto-disabled after 12 hours`);
|
|
149
|
+
setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
|
|
150
|
+
}
|
|
151
|
+
}, 12 * 60 * 60 * 1000);
|
|
152
|
+
}
|
|
127
153
|
|
|
128
154
|
// ── Context helpers ───────────────────────────────────────
|
|
129
155
|
// Check disk store available once on startup
|
|
@@ -180,12 +206,12 @@ module.exports = function (RED) {
|
|
|
180
206
|
if (payload === null) return;
|
|
181
207
|
// Skip if value unchanged since last publish
|
|
182
208
|
if (_lastSent[ch] === val) {
|
|
183
|
-
if (S.debugMode) node.
|
|
209
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → SKIP ch${ch}=${val} (unchanged)`);
|
|
184
210
|
return;
|
|
185
211
|
}
|
|
186
212
|
_lastSent[ch] = val;
|
|
187
213
|
broker.publish({ topic: dmxTopic, payload, qos: cfg.qos, retain: false });
|
|
188
|
-
if (S.debugMode) node.
|
|
214
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${dmxTopic} "${payload}"`);
|
|
189
215
|
});
|
|
190
216
|
}
|
|
191
217
|
|
|
@@ -204,7 +230,7 @@ module.exports = function (RED) {
|
|
|
204
230
|
qos: cfg.qos,
|
|
205
231
|
retain: retain !== undefined ? retain : cfg.retain,
|
|
206
232
|
});
|
|
207
|
-
if (S.debugMode) node.
|
|
233
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
|
|
208
234
|
}
|
|
209
235
|
|
|
210
236
|
function pubState(payload) {
|
|
@@ -617,7 +643,7 @@ module.exports = function (RED) {
|
|
|
617
643
|
|
|
618
644
|
if (devReq) {
|
|
619
645
|
switch (devReq) {
|
|
620
|
-
case 'add':
|
|
646
|
+
case 'add': _manualDiscover(); break;
|
|
621
647
|
case 'remove': handleDeviceRemove(); break;
|
|
622
648
|
default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
|
|
623
649
|
}
|
package/nodes/ha-mqtt-pir.html
CHANGED
|
@@ -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
|
|
package/nodes/ha-mqtt-pir.js
CHANGED
|
@@ -37,14 +37,32 @@ module.exports = function (RED) {
|
|
|
37
37
|
}, 1500);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// Track
|
|
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,15 @@ 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
|
+
|
|
83
|
+
|
|
63
84
|
// Fallback — if connect event already fired before listener registered
|
|
64
85
|
setTimeout(function () {
|
|
65
86
|
_tryDiscover();
|
|
@@ -87,13 +108,18 @@ module.exports = function (RED) {
|
|
|
87
108
|
debugMode: config.debugMode === true,
|
|
88
109
|
};
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
112
|
+
if (S.debugMode) {
|
|
113
|
+
setStatus('red', 'dot', `ha-mqtt-pir "${fixtureId}" ⚠ DEBUG MODE ON`);
|
|
114
|
+
node.warn(`[DEBUG] ha-mqtt-pir "${fixtureId}" — debug mode is enabled. Disable in production.`);
|
|
115
|
+
setTimeout(function () {
|
|
116
|
+
if (S.debugMode) {
|
|
117
|
+
S.debugMode = false;
|
|
118
|
+
node.warn(`[DEBUG] ha-mqtt-pir "${fixtureId}" — debug mode auto-disabled after 12 hours`);
|
|
119
|
+
setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
|
|
120
|
+
}
|
|
121
|
+
}, 12 * 60 * 60 * 1000);
|
|
122
|
+
}
|
|
97
123
|
|
|
98
124
|
// ── Helpers ───────────────────────────────────────────────
|
|
99
125
|
function pub(topic, payload, retain) {
|
|
@@ -104,7 +130,7 @@ module.exports = function (RED) {
|
|
|
104
130
|
qos: cfg.qos,
|
|
105
131
|
retain: retain !== undefined ? retain : cfg.retain,
|
|
106
132
|
});
|
|
107
|
-
if (S.debugMode) node.
|
|
133
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
|
|
108
134
|
}
|
|
109
135
|
|
|
110
136
|
function setStatus(fill, shape, text) {
|
package/nodes/ha-mqtt-relay.html
CHANGED
|
@@ -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
|
|
package/nodes/ha-mqtt-relay.js
CHANGED
|
@@ -40,14 +40,32 @@ module.exports = function (RED) {
|
|
|
40
40
|
}, 1500);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Track
|
|
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,15 @@ 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
|
+
|
|
86
|
+
|
|
66
87
|
// Fallback — if connect event already fired before listener registered
|
|
67
88
|
setTimeout(function () {
|
|
68
89
|
_tryDiscover();
|
|
@@ -93,13 +114,18 @@ module.exports = function (RED) {
|
|
|
93
114
|
diskDelay: cfg.diskDelay,
|
|
94
115
|
};
|
|
95
116
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
// ── Debug mode safeguards ─────────────────────────────────────────
|
|
118
|
+
if (S.debugMode) {
|
|
119
|
+
setStatus('red', 'dot', `ha-mqtt-relay "${fixtureId}" ⚠ DEBUG MODE ON`);
|
|
120
|
+
node.warn(`[DEBUG] ha-mqtt-relay "${fixtureId}" — debug mode is enabled. Disable in production.`);
|
|
121
|
+
setTimeout(function () {
|
|
122
|
+
if (S.debugMode) {
|
|
123
|
+
S.debugMode = false;
|
|
124
|
+
node.warn(`[DEBUG] ha-mqtt-relay "${fixtureId}" — debug mode auto-disabled after 12 hours`);
|
|
125
|
+
setStatus('yellow', 'ring', `${fixtureId} ready — awaiting HA`);
|
|
126
|
+
}
|
|
127
|
+
}, 12 * 60 * 60 * 1000);
|
|
128
|
+
}
|
|
103
129
|
|
|
104
130
|
// ── Context helpers ───────────────────────────────────────
|
|
105
131
|
// Check disk store available once on startup
|
|
@@ -140,7 +166,7 @@ module.exports = function (RED) {
|
|
|
140
166
|
qos: cfg.qos,
|
|
141
167
|
retain: retain !== undefined ? retain : cfg.retain,
|
|
142
168
|
});
|
|
143
|
-
if (S.debugMode) node.
|
|
169
|
+
if (S.debugMode) node.warn(`[DEBUG] ${fixtureId} → ${topic} ${strPayload.substring(0, 120)}`);
|
|
144
170
|
}
|
|
145
171
|
|
|
146
172
|
function pubRelay(value) {
|
|
@@ -325,7 +351,7 @@ module.exports = function (RED) {
|
|
|
325
351
|
|
|
326
352
|
if (devReq) {
|
|
327
353
|
switch (devReq) {
|
|
328
|
-
case 'add':
|
|
354
|
+
case 'add': _manualDiscover(); break;
|
|
329
355
|
case 'remove': handleDeviceRemove(); break;
|
|
330
356
|
default: node.warn(`${fixtureId} — unknown device.request: "${devReq}"`);
|
|
331
357
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-dmx-for-ha",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
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",
|