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.
@@ -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
- config.hueDevice = config.hueDevice.split("#")[0];
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
- && node.currentHUEDevice.hasOwnProperty("color")
92
- && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
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(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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
- if (msg.payload.data > 0) {
120
- const dimDirection = msg.payload.decr_incr === 1 ? "up" : "down";
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
- if (msg.payload.data > 0) {
157
- const dimDirectionTunableWhite = msg.payload.decr_incr === 1 ? "up" : "down";
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(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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
- && node.currentHUEDevice.hasOwnProperty("color")
218
- && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
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(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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 = msg.payload === true
251
- ? { on: { on: true }, dimming: { brightness: 100 }, dynamics: { duration: 0 } }
252
- : { on: { on: false }, dimming: { brightness: 0 }, dynamics: { duration: 0 } };
253
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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
- config.hueDevice,
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
- && node.currentHUEDevice.hasOwnProperty("color")
293
- && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
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(config.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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
- config.hueDevice,
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.timerDim = undefined;
333
- node.dimDirection = {};
334
- node.timeoutDim = 0;
335
- node.startDimStopper = function (_direction) {
336
- node.timeoutDim = 0;
337
- if (node.timerDim !== undefined) clearInterval(node.timerDim);
338
- if (_direction === "stop") {
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
- switch (_direction) {
342
- case "up":
343
- node.dimDirection = { dimming_delta: { action: "up", brightness_delta: 10 } };
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
- node.timerDim = setInterval(() => {
352
- node.timeoutDim += 1;
353
- if (node.timeoutDim > 150) {
354
- node.timeoutDim = 0;
355
- clearInterval(node.timerDim);
356
- }
357
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirection, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
358
- }, 700);
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.timerDimTunableWhite = undefined;
366
- node.dimDirectionTunableWhite = {};
367
- node.timeoutDimTunableWhite = 0;
368
- node.startDimStopperTunableWhite = function (_direction) {
369
- node.timeoutDimTunableWhite = 0;
370
- if (node.timerDimTunableWhite !== undefined) clearInterval(node.timerDimTunableWhite);
371
- if (_direction === "stop") return;
372
- switch (_direction) {
373
- case "up":
374
- node.dimDirectionTunableWhite = { color_temperature_delta: { action: "up", mirek_delta: 10 } };
375
- break;
376
- case "down":
377
- node.dimDirectionTunableWhite = { color_temperature_delta: { action: "down", mirek_delta: 10 } };
378
- break;
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
- node.timerDimTunableWhite = setInterval(() => {
383
- node.timeoutDimTunableWhite += 1;
384
- if (node.timeoutDimTunableWhite > 150) {
385
- node.timeoutDimTunableWhite = 0;
386
- clearInterval(node.timerDimTunableWhite);
387
- }
388
- node.serverHue.hueManager.writeHueQueueAdd(
389
- config.hueDevice,
390
- node.dimDirectionTunableWhite,
391
- node.isGrouped_light === false ? "setLight" : "setGroupedLight"
392
- );
393
- }, 700);
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 === config.hueDevice) {
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 (_event.on.on === false && (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === 'onhueoff')) {
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('on') && node.currentHUEDevice.on.on === false && _event.dimming.brightness === 0) return;
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(config.hueDevice, { on: { on: false } }, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
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: 'HUE->KNX error ' + node.id + ' ' + error.message
460
+ text: `HUE->KNX error ${node.id} ${error.message}`,
455
461
  });
456
462
  }
457
463
  };
458
464
 
459
- node.updateKNXBrightnessState = function (_value) {
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
- node.updateKNXLightState = function (_value) {
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
- (async () => {
584
- try {
585
- node.serverHue.addClient(node);
586
- await node.serverHue.hueManager.writeHueQueueAdd(
587
- config.hueDevice,
588
- null,
589
- node.isGrouped_light === false ? "getLight" : "getGroupedLight",
590
- (jLight) => {
591
- node.currentHUEDevice = jLight;
592
- node.setNodeStatusHue({
593
- fill: "blue",
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
- <p> This node lets you get the events from your HUE motion device.<br/>
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
- s<br/>
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
- <p> This node lets you get the events from your HUE motion device.<br/>
223
+ This node lets you get the events from your HUE motion device.
224
224
 
225
- Here you can get the HUE motion events.<br/>
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