node-red-contrib-knx-ultimate 2.1.63 → 2.2.2
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/.eslintrc.json +12 -12
- package/CHANGELOG.md +17 -1
- package/KNXEngine/package.json +1 -1
- package/nodes/hue-config.html +2 -2
- package/nodes/hue-config.js +81 -39
- package/nodes/knxUltimate-config.js +158 -156
- package/nodes/knxUltimateHueBattery.html +2 -2
- package/nodes/knxUltimateHueButton.html +1 -1
- package/nodes/knxUltimateHueButton.js +152 -116
- package/nodes/knxUltimateHueLight.html +830 -781
- package/nodes/knxUltimateHueLight.js +145 -149
- package/nodes/knxUltimateHueLightSensor.html +1 -1
- package/nodes/knxUltimateHueLightSensor.js +2 -2
- package/nodes/knxUltimateHueMotion.html +3 -4
- package/nodes/knxUltimateHueMotion.js +73 -61
- package/nodes/knxUltimateHueScene.html +1 -1
- package/nodes/knxUltimateHueScene.js +1 -1
- package/nodes/knxUltimateHueTapDial.html +1 -1
- package/nodes/knxUltimateHueTapDial.js +1 -2
- package/nodes/knxUltimateHueTemperatureSensor.html +2 -2
- package/nodes/knxUltimateLoadControl.html +1 -1
- package/nodes/knxUltimateViewer.html +28 -0
- package/nodes/utils/hueEngine.js +5 -25
- package/package.json +26 -5
- package/nodes/utils/iro.js +0 -1835
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
/* eslint-disable camelcase */
|
|
1
3
|
/* eslint-disable max-len */
|
|
2
4
|
/* eslint-disable no-lonely-if */
|
|
3
5
|
module.exports = function (RED) {
|
|
@@ -32,7 +34,7 @@ module.exports = function (RED) {
|
|
|
32
34
|
node.currentKNXGALightState = false; // Stores the current KNX value for the GA
|
|
33
35
|
node.DayTime = true;
|
|
34
36
|
node.isGrouped_light = config.hueDevice.split("#")[1] === "grouped_light";
|
|
35
|
-
|
|
37
|
+
node.hueDevice = config.hueDevice.split("#")[0];
|
|
36
38
|
|
|
37
39
|
// Used to call the status update from the config node.
|
|
38
40
|
node.setNodeStatus = ({ fill, shape, text, payload }) => { };
|
|
@@ -48,7 +50,7 @@ module.exports = function (RED) {
|
|
|
48
50
|
fill: "grey",
|
|
49
51
|
shape: "ring",
|
|
50
52
|
text: "Connecting to the Bridge...",
|
|
51
|
-
payload: ""
|
|
53
|
+
payload: "",
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
// This function is called by the hue-config.js
|
|
@@ -58,7 +60,7 @@ module.exports = function (RED) {
|
|
|
58
60
|
fill: "red",
|
|
59
61
|
shape: "ring",
|
|
60
62
|
text: "Rejected KNX message. I'm connecting to the Bridge...",
|
|
61
|
-
payload: ""
|
|
63
|
+
payload: "",
|
|
62
64
|
});
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
@@ -87,9 +89,9 @@ module.exports = function (RED) {
|
|
|
87
89
|
if (jColorChoosen !== null) {
|
|
88
90
|
let gamut = null;
|
|
89
91
|
if (
|
|
90
|
-
node.currentHUEDevice !== undefined
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
node.currentHUEDevice !== undefined &&
|
|
93
|
+
node.currentHUEDevice.hasOwnProperty("color") &&
|
|
94
|
+
node.currentHUEDevice.color.hasOwnProperty("gamut_type")
|
|
93
95
|
) {
|
|
94
96
|
gamut = node.currentHUEDevice.color.gamut_type;
|
|
95
97
|
}
|
|
@@ -104,7 +106,7 @@ module.exports = function (RED) {
|
|
|
104
106
|
} else {
|
|
105
107
|
state = { on: { on: false } };
|
|
106
108
|
}
|
|
107
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
109
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
108
110
|
node.setNodeStatusHue({
|
|
109
111
|
fill: "green",
|
|
110
112
|
shape: "dot",
|
|
@@ -116,22 +118,8 @@ module.exports = function (RED) {
|
|
|
116
118
|
// { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
|
|
117
119
|
// { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
|
|
118
120
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM));
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// First, switch on the light if off
|
|
122
|
-
if (node.currentHUEDevice.hasOwnProperty('on') !== undefined && node.currentHUEDevice.on.on === false && dimDirection === "up") {
|
|
123
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: true } }, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
124
|
-
}
|
|
125
|
-
node.startDimStopper(dimDirection);
|
|
126
|
-
} else {
|
|
127
|
-
node.startDimStopper("stop");
|
|
128
|
-
}
|
|
129
|
-
node.setNodeStatusHue({
|
|
130
|
-
fill: "green",
|
|
131
|
-
shape: "dot",
|
|
132
|
-
text: "KNX->HUE",
|
|
133
|
-
payload: msg.payload,
|
|
134
|
-
});
|
|
121
|
+
node.hueDimming(msg.payload.decr_incr, msg.payload.data, config.dimSpeed);
|
|
122
|
+
node.setNodeStatusHue({ fill: "green", shape: "dot", text: "KNX->HUE", payload: JSON.stringify(msg.payload) });
|
|
135
123
|
break;
|
|
136
124
|
case config.GADaylightSensor:
|
|
137
125
|
if (config.enableDayNightLighting === "yes") {
|
|
@@ -153,19 +141,9 @@ module.exports = function (RED) {
|
|
|
153
141
|
// { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
|
|
154
142
|
// { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
|
|
155
143
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightHSV));
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
node.startDimStopperTunableWhite(dimDirectionTunableWhite);
|
|
159
|
-
} else {
|
|
160
|
-
node.startDimStopperTunableWhite("stop");
|
|
161
|
-
}
|
|
144
|
+
node.hueDimmingTunableWhite(msg.payload.decr_incr, msg.payload.data, config.dimSpeed);
|
|
145
|
+
node.setNodeStatusHue({ fill: "green", shape: "dot", text: "KNX->HUE", payload: JSON.stringify(msg.payload) });
|
|
162
146
|
}
|
|
163
|
-
node.setNodeStatusHue({
|
|
164
|
-
fill: "green",
|
|
165
|
-
shape: "dot",
|
|
166
|
-
text: "KNX->HUE",
|
|
167
|
-
payload: msg.payload,
|
|
168
|
-
});
|
|
169
147
|
break;
|
|
170
148
|
case config.GALightHSVPercentage:
|
|
171
149
|
if (config.dptLightHSVPercentage === "5.001") {
|
|
@@ -175,7 +153,7 @@ module.exports = function (RED) {
|
|
|
175
153
|
const retMirek = hueColorConverter.ColorConverter.scale(msg.payload, [0, 100], [153, 500]);
|
|
176
154
|
msg.payload = retMirek;
|
|
177
155
|
state = { color_temperature: { mirek: msg.payload } };
|
|
178
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
156
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
179
157
|
node.setNodeStatusHue({
|
|
180
158
|
fill: "green",
|
|
181
159
|
shape: "dot",
|
|
@@ -201,7 +179,7 @@ module.exports = function (RED) {
|
|
|
201
179
|
if (node.currentHUEDevice.on.on === false && msg.payload > 0) state.on = { on: true };
|
|
202
180
|
if (node.currentHUEDevice.on.on === true && msg.payload === 0) state.on = { on: false };
|
|
203
181
|
}
|
|
204
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
182
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
205
183
|
node.setNodeStatusHue({
|
|
206
184
|
fill: "green",
|
|
207
185
|
shape: "dot",
|
|
@@ -213,9 +191,9 @@ module.exports = function (RED) {
|
|
|
213
191
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColor));
|
|
214
192
|
let gamut = null;
|
|
215
193
|
if (
|
|
216
|
-
node.currentHUEDevice !== undefined
|
|
217
|
-
|
|
218
|
-
|
|
194
|
+
node.currentHUEDevice !== undefined &&
|
|
195
|
+
node.currentHUEDevice.hasOwnProperty("color") &&
|
|
196
|
+
node.currentHUEDevice.color.hasOwnProperty("gamut_type")
|
|
219
197
|
) {
|
|
220
198
|
gamut = node.currentHUEDevice.color.gamut_type;
|
|
221
199
|
}
|
|
@@ -231,7 +209,7 @@ module.exports = function (RED) {
|
|
|
231
209
|
if (node.currentHUEDevice.on.on === false && bright > 0) state.on = { on: true };
|
|
232
210
|
if (node.currentHUEDevice.on.on === true && bright === 0) state = { on: { on: false }, dimming: { brightness: bright } };
|
|
233
211
|
}
|
|
234
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
212
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
235
213
|
node.setNodeStatusHue({
|
|
236
214
|
fill: "green",
|
|
237
215
|
shape: "dot",
|
|
@@ -247,15 +225,16 @@ module.exports = function (RED) {
|
|
|
247
225
|
node.blinkValue = !node.blinkValue;
|
|
248
226
|
msg.payload = node.blinkValue;
|
|
249
227
|
// state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
|
|
250
|
-
state =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
228
|
+
state =
|
|
229
|
+
msg.payload === true
|
|
230
|
+
? { on: { on: true }, dimming: { brightness: 100 }, dynamics: { duration: 0 } }
|
|
231
|
+
: { on: { on: false }, dimming: { brightness: 0 }, dynamics: { duration: 0 } };
|
|
232
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
254
233
|
}, 1000);
|
|
255
234
|
} else {
|
|
256
235
|
if (node.timerBlink !== undefined) clearInterval(node.timerBlink);
|
|
257
236
|
node.serverHue.hueManager.writeHueQueueAdd(
|
|
258
|
-
|
|
237
|
+
node.hueDevice,
|
|
259
238
|
{ on: { on: false } },
|
|
260
239
|
node.isGrouped_light === false ? "setLight" : "setGroupedLight"
|
|
261
240
|
);
|
|
@@ -271,11 +250,7 @@ module.exports = function (RED) {
|
|
|
271
250
|
if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle);
|
|
272
251
|
const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColorCycle));
|
|
273
252
|
if (gaValColorCycle === true) {
|
|
274
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
275
|
-
config.hueDevice,
|
|
276
|
-
{ on: { on: true } },
|
|
277
|
-
node.isGrouped_light === false ? "setLight" : "setGroupedLight"
|
|
278
|
-
);
|
|
253
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, { on: { on: true } }, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
279
254
|
node.timerColorCycle = setInterval(() => {
|
|
280
255
|
try {
|
|
281
256
|
function getRandomIntInclusive(min, max) {
|
|
@@ -288,22 +263,22 @@ module.exports = function (RED) {
|
|
|
288
263
|
const blue = getRandomIntInclusive(0, 255);
|
|
289
264
|
let gamut = null;
|
|
290
265
|
if (
|
|
291
|
-
node.currentHUEDevice !== undefined
|
|
292
|
-
|
|
293
|
-
|
|
266
|
+
node.currentHUEDevice !== undefined &&
|
|
267
|
+
node.currentHUEDevice.hasOwnProperty("color") &&
|
|
268
|
+
node.currentHUEDevice.color.hasOwnProperty("gamut_type")
|
|
294
269
|
) {
|
|
295
270
|
gamut = node.currentHUEDevice.color.gamut_type;
|
|
296
271
|
}
|
|
297
272
|
const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut);
|
|
298
273
|
const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue);
|
|
299
274
|
state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } };
|
|
300
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
275
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
301
276
|
} catch (error) { }
|
|
302
277
|
}, 10000);
|
|
303
278
|
} else {
|
|
304
279
|
if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle);
|
|
305
280
|
node.serverHue.hueManager.writeHueQueueAdd(
|
|
306
|
-
|
|
281
|
+
node.hueDevice,
|
|
307
282
|
{ on: { on: false } },
|
|
308
283
|
node.isGrouped_light === false ? "setLight" : "setGroupedLight"
|
|
309
284
|
);
|
|
@@ -329,87 +304,106 @@ module.exports = function (RED) {
|
|
|
329
304
|
|
|
330
305
|
// Start dimming
|
|
331
306
|
// ***********************************************************
|
|
332
|
-
node.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
307
|
+
node.hueDimming = function hueDimming(_KNXaction, _KNXbrightness_delta, _dimSpeedInMillisecs = undefined) {
|
|
308
|
+
let dimDirection = "stop";
|
|
309
|
+
let hueTelegram = {};
|
|
310
|
+
let delta = 0;
|
|
311
|
+
_dimSpeedInMillisecs = _dimSpeedInMillisecs === undefined || _dimSpeedInMillisecs === "" ? 5000 : _dimSpeedInMillisecs;
|
|
312
|
+
|
|
313
|
+
// We have also minDimLevelLight and maxDimLevelLight to take care of.
|
|
314
|
+
let minDimLevelLight = config.minDimLevelLight === undefined ? 10 : config.minDimLevelLight;
|
|
315
|
+
if (config.minDimLevelLight === "useHueLightLevel" && node.currentHUEDevice.dimming.min_dim_level === undefined) minDimLevelLight = 10;
|
|
316
|
+
const maxDimLevelLight = config.maxDimLevelLight === undefined ? 100 : config.maxDimLevelLight;
|
|
317
|
+
|
|
318
|
+
if (_KNXbrightness_delta === 0 && _KNXaction === 0) {
|
|
319
|
+
dimDirection = "stop";
|
|
320
|
+
hueTelegram = { dimming_delta: { action: dimDirection } };
|
|
321
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
339
322
|
return;
|
|
340
323
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
break;
|
|
345
|
-
case "down":
|
|
346
|
-
node.dimDirection = { dimming_delta: { action: "down", brightness_delta: 10 } };
|
|
347
|
-
break;
|
|
348
|
-
default:
|
|
349
|
-
break;
|
|
324
|
+
if (_KNXbrightness_delta > 0 && _KNXaction === 1) {
|
|
325
|
+
delta = 100 - Math.round(node.currentHUEDevice.dimming.brightness, 0) - (100 - Number(maxDimLevelLight));
|
|
326
|
+
dimDirection = "up";
|
|
350
327
|
}
|
|
351
|
-
|
|
352
|
-
node.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
328
|
+
if (_KNXbrightness_delta > 0 && _KNXaction === 0) {
|
|
329
|
+
// Set the minumum delta, taking care of the minimum brightness specified either in the HUE lamp itself, or specified by the user (parameter node.minDimLevelLight)
|
|
330
|
+
delta = Math.round(node.currentHUEDevice.dimming.brightness, 0) - (minDimLevelLight === "useHueLightLevel" ? node.currentHUEDevice.dimming.min_dim_level : Number(minDimLevelLight));
|
|
331
|
+
dimDirection = "down";
|
|
332
|
+
}
|
|
333
|
+
// Calculate the dimming time based on delta
|
|
334
|
+
// 10000:x=100:delta
|
|
335
|
+
// x = (10000 * delta) / 100
|
|
336
|
+
_dimSpeedInMillisecs = Math.round((_dimSpeedInMillisecs * delta) / 100, 0);
|
|
337
|
+
|
|
338
|
+
hueTelegram = { dimming_delta: { action: dimDirection, brightness_delta: delta }, dynamics: { duration: _dimSpeedInMillisecs } };
|
|
339
|
+
// Switch on the light if off
|
|
340
|
+
if (node.currentHUEDevice.hasOwnProperty("on") !== undefined && node.currentHUEDevice.on.on === false && dimDirection === "up") {
|
|
341
|
+
hueTelegram.on = { on: true };
|
|
342
|
+
}
|
|
343
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
359
344
|
};
|
|
360
345
|
// ***********************************************************
|
|
361
346
|
|
|
362
347
|
// Start dimming tunable white
|
|
363
348
|
// mirek: required(integer minimum: 153, maximum: 500)
|
|
364
349
|
// ***********************************************************
|
|
365
|
-
node.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if (node.
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
default:
|
|
380
|
-
break;
|
|
350
|
+
node.hueDimmingTunableWhite = function hueDimming(_KNXaction, _KNXbrightness_delta, _dimSpeedInMillisecs = undefined) {
|
|
351
|
+
let dimDirection = "stop";
|
|
352
|
+
let hueTelegram = {};
|
|
353
|
+
_dimSpeedInMillisecs = _dimSpeedInMillisecs === undefined || _dimSpeedInMillisecs === "" ? 5000 : _dimSpeedInMillisecs;
|
|
354
|
+
let delta = 0;
|
|
355
|
+
if (!node.currentHUEDevice.color_temperature.hasOwnProperty("mirek")) delta = 347 - Math.round(173, 0); // Unable to read the mirek, set medium as default
|
|
356
|
+
// We have also minDimLevelLight and maxDimLevelLight to take care of.
|
|
357
|
+
// Mirek limits are not taken in consideration.
|
|
358
|
+
// Maximum mirek is 347
|
|
359
|
+
if (_KNXbrightness_delta === 0 && _KNXaction === 0) {
|
|
360
|
+
dimDirection = "stop";
|
|
361
|
+
hueTelegram = { color_temperature_delta: { action: dimDirection } };
|
|
362
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
363
|
+
return;
|
|
381
364
|
}
|
|
382
|
-
|
|
383
|
-
node.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
node.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
365
|
+
if (_KNXbrightness_delta > 0 && _KNXaction === 1) {
|
|
366
|
+
if (node.currentHUEDevice.color_temperature.hasOwnProperty("mirek")) delta = 347 - Math.round(node.currentHUEDevice.color_temperature.mirek, 0);
|
|
367
|
+
dimDirection = "up";
|
|
368
|
+
}
|
|
369
|
+
if (_KNXbrightness_delta > 0 && _KNXaction === 0) {
|
|
370
|
+
// Set the minumum delta, taking care of the minimum brightness specified either in the HUE lamp itself, or specified by the user (parameter node.minDimLevelLight)
|
|
371
|
+
if (node.currentHUEDevice.color_temperature.hasOwnProperty("mirek")) delta = Math.round(node.currentHUEDevice.color_temperature.mirek, 0);
|
|
372
|
+
dimDirection = "down";
|
|
373
|
+
}
|
|
374
|
+
// Calculate the dimming time based on delta
|
|
375
|
+
// 10000:x=347:delta
|
|
376
|
+
// x = (10000 * delta) / 347
|
|
377
|
+
_dimSpeedInMillisecs = Math.round((_dimSpeedInMillisecs * delta) / 347, 0);
|
|
378
|
+
|
|
379
|
+
hueTelegram = { color_temperature_delta: { action: dimDirection, mirek_delta: delta }, dynamics: { duration: _dimSpeedInMillisecs } };
|
|
380
|
+
// Switch on the light if off
|
|
381
|
+
if (node.currentHUEDevice.hasOwnProperty("on") !== undefined && node.currentHUEDevice.on.on === false && dimDirection === "up") {
|
|
382
|
+
hueTelegram.on = { on: true };
|
|
383
|
+
}
|
|
384
|
+
node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
|
|
394
385
|
};
|
|
395
386
|
// ***********************************************************
|
|
396
387
|
|
|
397
388
|
node.handleSendHUE = (_event) => {
|
|
398
389
|
try {
|
|
399
|
-
if (_event.id ===
|
|
390
|
+
if (_event.id === node.hueDevice) {
|
|
400
391
|
if (node.currentHUEDevice === undefined) {
|
|
401
392
|
node.setNodeStatusHue({
|
|
402
393
|
fill: "red",
|
|
403
394
|
shape: "ring",
|
|
404
395
|
text: "Rejected HUE message. I'm connecting to the Bridge...",
|
|
405
|
-
payload: ""
|
|
396
|
+
payload: "",
|
|
406
397
|
});
|
|
407
398
|
return;
|
|
408
399
|
}
|
|
409
400
|
if (_event.hasOwnProperty("on")) {
|
|
410
401
|
node.updateKNXLightState(_event.on.on);
|
|
411
402
|
// In case of switch off, set the dim to zero
|
|
412
|
-
if (
|
|
403
|
+
if (
|
|
404
|
+
_event.on.on === false &&
|
|
405
|
+
(config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === "onhueoff")
|
|
406
|
+
) {
|
|
413
407
|
node.updateKNXBrightnessState(0);
|
|
414
408
|
} else {
|
|
415
409
|
// Sends the previous brightness value
|
|
@@ -419,44 +413,57 @@ module.exports = function (RED) {
|
|
|
419
413
|
/* empty */
|
|
420
414
|
}
|
|
421
415
|
}
|
|
422
|
-
if (node.currentHUEDevice !== undefined) node.currentHUEDevice.on = _event.on; // Update the internal object representing the current light
|
|
423
|
-
return;
|
|
424
416
|
}
|
|
425
417
|
if (_event.hasOwnProperty("color")) {
|
|
426
418
|
node.updateKNXLightColorState(_event.color);
|
|
427
|
-
if (node.currentHUEDevice !== undefined) node.currentHUEDevice.color = _event.color; // Update the internal object representing the current light
|
|
428
|
-
return;
|
|
429
419
|
}
|
|
430
420
|
if (_event.hasOwnProperty("dimming")) {
|
|
431
421
|
// Every once on a time, the light transmit the brightness value of 0.39.
|
|
432
422
|
// To avoid wrongly turn light state on, exit
|
|
433
423
|
if (_event.dimming.brightness < 1) _event.dimming.brightness = 0;
|
|
434
|
-
if (node.currentHUEDevice.hasOwnProperty(
|
|
424
|
+
if (node.currentHUEDevice.hasOwnProperty("on") && node.currentHUEDevice.on.on === false && _event.dimming.brightness === 0) return;
|
|
435
425
|
if (node.currentHUEDevice.on.on === false) node.updateKNXLightState(_event.dimming.brightness > 0);
|
|
436
426
|
node.updateKNXBrightnessState(_event.dimming.brightness);
|
|
437
|
-
if (node.currentHUEDevice !== undefined) node.currentHUEDevice.dimming = _event.dimming; // Update the internal object representing the current light
|
|
438
427
|
// If the brightness reaches zero, the hue lamp "on" property must be set to zero as well
|
|
439
428
|
if (_event.dimming.brightness === 0) {
|
|
440
|
-
node.serverHue.hueManager.writeHueQueueAdd(
|
|
429
|
+
node.serverHue.hueManager.writeHueQueueAdd(
|
|
430
|
+
node.hueDevice,
|
|
431
|
+
{ on: { on: false } },
|
|
432
|
+
node.isGrouped_light === false ? "setLight" : "setGroupedLight"
|
|
433
|
+
);
|
|
441
434
|
}
|
|
442
|
-
return;
|
|
443
435
|
}
|
|
444
436
|
if (_event.hasOwnProperty("color_temperature")) {
|
|
445
437
|
node.updateKNXLightHSVState(_event.color_temperature.mirek);
|
|
446
|
-
if (node.currentHUEDevice !== undefined) node.currentHUEDevice.color_temperature = _event.color_temperature; // Update the internal object representing the current light
|
|
447
|
-
return;
|
|
448
438
|
}
|
|
439
|
+
|
|
440
|
+
// Update the current HUE Device with the new _event
|
|
441
|
+
function copiaOggettoRicorsivo(objDestinazione, objOrigine) {
|
|
442
|
+
for (const prop in objOrigine) {
|
|
443
|
+
if (typeof objOrigine[prop] === "object" && objOrigine[prop] !== null) {
|
|
444
|
+
// Se la proprietà è un oggetto, copiamola in modo ricorsivo
|
|
445
|
+
objDestinazione[prop] = objDestinazione[prop] || {};
|
|
446
|
+
copiaOggettoRicorsivo(objDestinazione[prop], objOrigine[prop]);
|
|
447
|
+
} else {
|
|
448
|
+
// Altrimenti, copia il valore della proprietà
|
|
449
|
+
objDestinazione[prop] = objOrigine[prop];
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Copia l'oggettoOrigine nell'oggettoDestinazione mantenendo le proprietà esistenti
|
|
454
|
+
copiaOggettoRicorsivo(node.currentHUEDevice, _event);
|
|
449
455
|
}
|
|
450
456
|
} catch (error) {
|
|
451
457
|
node.status({
|
|
452
458
|
fill: "red",
|
|
453
459
|
shape: "dot",
|
|
454
|
-
text:
|
|
460
|
+
text: `HUE->KNX error ${node.id} ${error.message}`,
|
|
455
461
|
});
|
|
456
462
|
}
|
|
457
463
|
};
|
|
458
464
|
|
|
459
|
-
|
|
465
|
+
// Leave the name after "function", to avoid <anonymous function> in the stack trace, in caso of errors.
|
|
466
|
+
node.updateKNXBrightnessState = function updateKNXBrightnessState(_value) {
|
|
460
467
|
if (config.GALightBrightnessState !== undefined && config.GALightBrightnessState !== "") {
|
|
461
468
|
const knxMsgPayload = {};
|
|
462
469
|
knxMsgPayload.topic = config.GALightBrightnessState;
|
|
@@ -480,7 +487,8 @@ module.exports = function (RED) {
|
|
|
480
487
|
});
|
|
481
488
|
}
|
|
482
489
|
};
|
|
483
|
-
|
|
490
|
+
|
|
491
|
+
node.updateKNXLightState = function updateKNXBrightnessState(_value) {
|
|
484
492
|
try {
|
|
485
493
|
const knxMsgPayload = {};
|
|
486
494
|
knxMsgPayload.topic = config.GALightState;
|
|
@@ -513,7 +521,7 @@ module.exports = function (RED) {
|
|
|
513
521
|
}
|
|
514
522
|
};
|
|
515
523
|
|
|
516
|
-
node.updateKNXLightHSVState = function (_value) {
|
|
524
|
+
node.updateKNXLightHSVState = function updateKNXLightState(_value) {
|
|
517
525
|
if (config.GALightHSVState !== undefined && config.GALightHSVState !== "") {
|
|
518
526
|
const knxMsgPayload = {};
|
|
519
527
|
knxMsgPayload.topic = config.GALightHSVState;
|
|
@@ -541,7 +549,7 @@ module.exports = function (RED) {
|
|
|
541
549
|
}
|
|
542
550
|
};
|
|
543
551
|
|
|
544
|
-
node.updateKNXLightColorState = function (_value) {
|
|
552
|
+
node.updateKNXLightColorState = function updateKNXLightColorState(_value) {
|
|
545
553
|
if (config.GALightColorState !== undefined && config.GALightColorState !== "") {
|
|
546
554
|
const knxMsgPayload = {};
|
|
547
555
|
knxMsgPayload.topic = config.GALightColorState;
|
|
@@ -577,30 +585,18 @@ module.exports = function (RED) {
|
|
|
577
585
|
}
|
|
578
586
|
if (node.serverHue) {
|
|
579
587
|
node.serverHue.removeClient(node);
|
|
580
|
-
// I must get the light object, to store it in the node.currentHUEDevice variable
|
|
581
|
-
// I queue the state request, by passing the callback to call whenever the HUE bridge send me the light status async
|
|
582
588
|
if (node.serverHue !== null && node.serverHue.hueManager !== null) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
shape: "ring",
|
|
595
|
-
text: "Connected. Is on: ",
|
|
596
|
-
payload: node.currentHUEDevice.on.on === true,
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
);
|
|
600
|
-
} catch (err) {
|
|
601
|
-
RED.log.error(`Errore knxUltimateHueLight node.currentHUEDevice ${err.message}`);
|
|
602
|
-
}
|
|
603
|
-
})();
|
|
589
|
+
try {
|
|
590
|
+
// Everytime the node is edited, it comes here to read the currentHueDevice, if any.
|
|
591
|
+
// It comes here also at node-red boot, but at node-red boot, the hueAllResources is null.
|
|
592
|
+
// The hue-config take cares of filling all properties of the node, after it has been connected to the hue Brigde.
|
|
593
|
+
if (node.serverHue.hueAllResources !== null) node.currentHUEDevice = node.serverHue.loadResourcesFromHUEBridge(node);
|
|
594
|
+
} catch (error) { }
|
|
595
|
+
try {
|
|
596
|
+
node.serverHue.addClient(node);
|
|
597
|
+
} catch (err) {
|
|
598
|
+
RED.log.error(`Errore knxUltimateHueLight node.currentHUEDevice ${err.message}`);
|
|
599
|
+
}
|
|
604
600
|
}
|
|
605
601
|
}
|
|
606
602
|
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
<script src="https://kit.fontawesome.com/11f26b4500.js" crossorigin="anonymous"></script>
|
|
224
224
|
|
|
225
225
|
<script type="text/markdown" data-help-name="knxUltimateHueLightSensor">
|
|
226
|
-
|
|
226
|
+
This node lets you get the events from your HUE motion device.
|
|
227
227
|
|
|
228
228
|
Here you can get the HUE Light Sensors light events, that represents a lux value, evetytime the ambient light changes.<br/>
|
|
229
229
|
Start typing in the GA field, the name or group address of your KNX device, the avaiable devices start showing up while you're typing.
|
|
@@ -80,10 +80,10 @@ module.exports = function (RED) {
|
|
|
80
80
|
// I queue the state request, by passing the callback to call whenever the HUE bridge send me the light status async
|
|
81
81
|
if (node.serverHue !== null && node.serverHue.hueManager !== null) {
|
|
82
82
|
(async () => {
|
|
83
|
-
node.serverHue.addClient(node)
|
|
83
|
+
node.serverHue.addClient(node);
|
|
84
84
|
try {
|
|
85
85
|
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, null, 'getLightLevel', (jLight) => {
|
|
86
|
-
node.handleSendHUE(jLight)
|
|
86
|
+
node.handleSendHUE(jLight);
|
|
87
87
|
})
|
|
88
88
|
} catch (error) {
|
|
89
89
|
RED.log.error('Errore knxUltimateHueLightSensor subscribing: ' + error.message)
|
|
@@ -211,7 +211,7 @@
|
|
|
211
211
|
<input type="text" id="node-input-namemotion" style="width:200px;margin-left: 5px; text-align: left;">
|
|
212
212
|
</div>
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
<br/>
|
|
215
215
|
<br/>
|
|
216
216
|
<br/>
|
|
217
217
|
|
|
@@ -220,9 +220,9 @@ s<br/>
|
|
|
220
220
|
<script src="https://kit.fontawesome.com/11f26b4500.js" crossorigin="anonymous"></script>
|
|
221
221
|
|
|
222
222
|
<script type="text/markdown" data-help-name="knxUltimateHueMotion">
|
|
223
|
-
|
|
223
|
+
This node lets you get the events from your HUE motion device.
|
|
224
224
|
|
|
225
|
-
Here you can get the HUE motion events
|
|
225
|
+
Here you can get the HUE motion events.
|
|
226
226
|
Start typing in the GA field, the name or group address of your KNX device, the avaiable devices start showing up while you're typing.
|
|
227
227
|
|
|
228
228
|
**General**
|
|
@@ -245,7 +245,6 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
245
245
|
|
|
246
246
|
`msg.payload` is used as the payload of the published message.
|
|
247
247
|
It contains the detailed event sent by your Hue devicem so you can use it for whatever you want.
|
|
248
|
-
It contains the detailed event sent by your Hue devicem so you can use it for whatever you want.
|
|
249
248
|
|
|
250
249
|
<br/>
|
|
251
250
|
|