node-red-contrib-knx-ultimate 2.2.2 → 2.2.4

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.
@@ -37,29 +37,30 @@ module.exports = function (RED) {
37
37
  node.hueDevice = config.hueDevice.split("#")[0];
38
38
 
39
39
  // Used to call the status update from the config node.
40
- node.setNodeStatus = ({ fill, shape, text, payload }) => { };
40
+ node.setNodeStatus = ({
41
+ fill, shape, text, payload,
42
+ }) => { };
41
43
  // Used to call the status update from the HUE config node.
42
44
  node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
43
- if (payload === undefined) return;
45
+ if (payload === undefined) payload = '';
44
46
  const dDate = new Date();
45
47
  payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
46
48
  node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
47
49
  };
48
50
 
49
- node.setNodeStatusHue({
50
- fill: "grey",
51
- shape: "ring",
52
- text: "Connecting to the Bridge...",
53
- payload: "",
54
- });
51
+ function getRandomIntInclusive(min, max) {
52
+ min = Math.ceil(min);
53
+ max = Math.floor(max);
54
+ return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
55
+ }
55
56
 
56
57
  // This function is called by the hue-config.js
57
58
  node.handleSend = (msg) => {
58
59
  if (node.currentHUEDevice === undefined) {
59
60
  node.setNodeStatusHue({
60
- fill: "red",
61
+ fill: "grey",
61
62
  shape: "ring",
62
- text: "Rejected KNX message. I'm connecting to the Bridge...",
63
+ text: "Currently not ready.",
63
64
  payload: "",
64
65
  });
65
66
  return;
@@ -89,9 +90,9 @@ module.exports = function (RED) {
89
90
  if (jColorChoosen !== null) {
90
91
  let gamut = null;
91
92
  if (
92
- node.currentHUEDevice !== undefined &&
93
- node.currentHUEDevice.hasOwnProperty("color") &&
94
- node.currentHUEDevice.color.hasOwnProperty("gamut_type")
93
+ node.currentHUEDevice !== undefined
94
+ && node.currentHUEDevice.hasOwnProperty("color")
95
+ && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
95
96
  ) {
96
97
  gamut = node.currentHUEDevice.color.gamut_type;
97
98
  }
@@ -101,7 +102,7 @@ module.exports = function (RED) {
101
102
  node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
102
103
  state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } };
103
104
  } else {
104
- state = { on: { on: true }, dimming: node.currentHUEDevice.dimming };
105
+ state = { on: { on: true } };
105
106
  }
106
107
  } else {
107
108
  state = { on: { on: false } };
@@ -119,7 +120,9 @@ module.exports = function (RED) {
119
120
  // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
120
121
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM));
121
122
  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) });
123
+ node.setNodeStatusHue({
124
+ fill: "green", shape: "dot", text: "KNX->HUE", payload: JSON.stringify(msg.payload),
125
+ });
123
126
  break;
124
127
  case config.GADaylightSensor:
125
128
  if (config.enableDayNightLighting === "yes") {
@@ -142,7 +145,9 @@ module.exports = function (RED) {
142
145
  // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
143
146
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightHSV));
144
147
  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) });
148
+ node.setNodeStatusHue({
149
+ fill: "green", shape: "dot", text: "KNX->HUE", payload: JSON.stringify(msg.payload),
150
+ });
146
151
  }
147
152
  break;
148
153
  case config.GALightHSVPercentage:
@@ -191,9 +196,9 @@ module.exports = function (RED) {
191
196
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColor));
192
197
  let gamut = null;
193
198
  if (
194
- node.currentHUEDevice !== undefined &&
195
- node.currentHUEDevice.hasOwnProperty("color") &&
196
- node.currentHUEDevice.color.hasOwnProperty("gamut_type")
199
+ node.currentHUEDevice !== undefined
200
+ && node.currentHUEDevice.hasOwnProperty("color")
201
+ && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
197
202
  ) {
198
203
  gamut = node.currentHUEDevice.color.gamut_type;
199
204
  }
@@ -225,10 +230,9 @@ module.exports = function (RED) {
225
230
  node.blinkValue = !node.blinkValue;
226
231
  msg.payload = node.blinkValue;
227
232
  // state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
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 } };
233
+ state = msg.payload === true
234
+ ? { on: { on: true }, dimming: { brightness: 100 }, dynamics: { duration: 0 } }
235
+ : { on: { on: false }, dimming: { brightness: 0 }, dynamics: { duration: 0 } };
232
236
  node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
233
237
  }, 1000);
234
238
  } else {
@@ -236,7 +240,7 @@ module.exports = function (RED) {
236
240
  node.serverHue.hueManager.writeHueQueueAdd(
237
241
  node.hueDevice,
238
242
  { on: { on: false } },
239
- node.isGrouped_light === false ? "setLight" : "setGroupedLight"
243
+ node.isGrouped_light === false ? "setLight" : "setGroupedLight",
240
244
  );
241
245
  }
242
246
  node.setNodeStatusHue({
@@ -247,48 +251,45 @@ module.exports = function (RED) {
247
251
  });
248
252
  break;
249
253
  case config.GALightColorCycle:
250
- if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle);
251
- const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColorCycle));
252
- if (gaValColorCycle === true) {
253
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, { on: { on: true } }, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
254
- node.timerColorCycle = setInterval(() => {
255
- try {
256
- function getRandomIntInclusive(min, max) {
257
- min = Math.ceil(min);
258
- max = Math.floor(max);
259
- return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
260
- }
261
- const red = getRandomIntInclusive(0, 255);
262
- const green = getRandomIntInclusive(0, 255);
263
- const blue = getRandomIntInclusive(0, 255);
264
- let gamut = null;
265
- if (
266
- node.currentHUEDevice !== undefined &&
267
- node.currentHUEDevice.hasOwnProperty("color") &&
268
- node.currentHUEDevice.color.hasOwnProperty("gamut_type")
269
- ) {
270
- gamut = node.currentHUEDevice.color.gamut_type;
271
- }
272
- const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut);
273
- const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue);
274
- state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } };
275
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
276
- } catch (error) { }
277
- }, 10000);
278
- } else {
254
+ {
279
255
  if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle);
280
- node.serverHue.hueManager.writeHueQueueAdd(
281
- node.hueDevice,
282
- { on: { on: false } },
283
- node.isGrouped_light === false ? "setLight" : "setGroupedLight"
284
- );
256
+ const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColorCycle));
257
+ if (gaValColorCycle === true) {
258
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, { on: { on: true } }, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
259
+ node.timerColorCycle = setInterval(() => {
260
+ try {
261
+ const red = getRandomIntInclusive(0, 255);
262
+ const green = getRandomIntInclusive(0, 255);
263
+ const blue = getRandomIntInclusive(0, 255);
264
+ let gamut = null;
265
+ if (
266
+ node.currentHUEDevice !== undefined
267
+ && node.currentHUEDevice.hasOwnProperty("color")
268
+ && node.currentHUEDevice.color.hasOwnProperty("gamut_type")
269
+ ) {
270
+ gamut = node.currentHUEDevice.color.gamut_type;
271
+ }
272
+ const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut);
273
+ const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue);
274
+ state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } };
275
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, state, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
276
+ } catch (error) { }
277
+ }, 10000);
278
+ } else {
279
+ if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle);
280
+ node.serverHue.hueManager.writeHueQueueAdd(
281
+ node.hueDevice,
282
+ { on: { on: false } },
283
+ node.isGrouped_light === false ? "setLight" : "setGroupedLight",
284
+ );
285
+ }
286
+ node.setNodeStatusHue({
287
+ fill: "green",
288
+ shape: "dot",
289
+ text: "KNX->HUE",
290
+ payload: gaValColorCycle,
291
+ });
285
292
  }
286
- node.setNodeStatusHue({
287
- fill: "green",
288
- shape: "dot",
289
- text: "KNX->HUE",
290
- payload: gaValColorCycle,
291
- });
292
293
  break;
293
294
  default:
294
295
  break;
@@ -305,42 +306,63 @@ module.exports = function (RED) {
305
306
  // Start dimming
306
307
  // ***********************************************************
307
308
  node.hueDimming = function hueDimming(_KNXaction, _KNXbrightness_delta, _dimSpeedInMillisecs = undefined) {
308
- let dimDirection = "stop";
309
+ // 31/10/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success
310
+ // i decide to go to the "step brightness" way.
309
311
  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;
312
+ const numStep = 10; // Steps from 0 to 100 by 10
313
+ if (_dimSpeedInMillisecs === undefined || _dimSpeedInMillisecs === '') _dimSpeedInMillisecs = 5000;
317
314
 
318
315
  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");
316
+ // STOP DIM
317
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
318
+ node.brightnessStep = null;
322
319
  return;
323
320
  }
321
+
322
+ // Set the actual brightness to start with
323
+ if (node.brightnessStep === null || node.brightnessStep === undefined) node.brightnessStep = node.currentHUEDevice.dimming.brightness || 50;
324
+ node.brightnessStep = Math.ceil(Number(node.brightnessStep));
325
+
326
+ // Set the speed
327
+ _dimSpeedInMillisecs /= numStep;
328
+
329
+ // We have also minDimLevelLight and maxDimLevelLight to take care of.
330
+ let minDimLevelLight = config.minDimLevelLight === undefined ? 10 : Number(config.minDimLevelLight);
331
+ if (config.minDimLevelLight === "useHueLightLevel" && node.currentHUEDevice.dimming.min_dim_level === undefined) minDimLevelLight = 10;
332
+ const maxDimLevelLight = config.maxDimLevelLight === undefined ? 100 : Number(config.maxDimLevelLight);
333
+
324
334
  if (_KNXbrightness_delta > 0 && _KNXaction === 1) {
325
- delta = 100 - Math.round(node.currentHUEDevice.dimming.brightness, 0) - (100 - Number(maxDimLevelLight));
326
- dimDirection = "up";
335
+ // DIM UP
336
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
337
+ node.timerStepDim = setInterval(() => {
338
+ node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
339
+ node.brightnessStep += numStep;
340
+ if (node.brightnessStep > maxDimLevelLight) node.brightnessStep = maxDimLevelLight;
341
+ hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs } };
342
+ // Switch on the light if off
343
+ if (node.currentHUEDevice.hasOwnProperty("on") !== undefined && node.currentHUEDevice.on.on === false) {
344
+ hueTelegram.on = { on: true };
345
+ }
346
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
347
+ if (node.brightnessStep >= maxDimLevelLight) clearInterval(node.timerStepDim);
348
+ }, _dimSpeedInMillisecs);
327
349
  }
328
350
  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 };
351
+ // DIM DOWN
352
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
353
+ node.timerStepDim = setInterval(() => {
354
+ node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
355
+ node.brightnessStep -= numStep;
356
+ if (node.brightnessStep < minDimLevelLight) node.brightnessStep = minDimLevelLight;
357
+ hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs } };
358
+ // Switch off the light if on
359
+ if (node.currentHUEDevice.hasOwnProperty("on") !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStep === 0) {
360
+ hueTelegram.on = { on: false };
361
+ }
362
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
363
+ if (node.brightnessStep <= minDimLevelLight) clearInterval(node.timerStepDim);
364
+ }, _dimSpeedInMillisecs);
342
365
  }
343
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
344
366
  };
345
367
  // ***********************************************************
346
368
 
@@ -401,57 +423,69 @@ module.exports = function (RED) {
401
423
  node.updateKNXLightState(_event.on.on);
402
424
  // In case of switch off, set the dim to zero
403
425
  if (
404
- _event.on.on === false &&
405
- (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === "onhueoff")
426
+ _event.on.on === false
427
+ && (config.updateKNXBrightnessStatusOnHUEOnOff === undefined || config.updateKNXBrightnessStatusOnHUEOnOff === "onhueoff")
406
428
  ) {
407
429
  node.updateKNXBrightnessState(0);
430
+ node.currentHUEDevice.dimming.brightness = 0;
408
431
  } else {
409
- // Sends the previous brightness value
410
- try {
411
- node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
412
- } catch (error) {
413
- /* empty */
414
- }
432
+ // // Sends the previous brightness value
433
+ // try {
434
+ // node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
435
+ // } catch (error) {
436
+ // /* empty */
437
+ // }
415
438
  }
439
+ node.currentHUEDevice.on.on = _event.on.on;
416
440
  }
417
441
  if (_event.hasOwnProperty("color")) {
418
- node.updateKNXLightColorState(_event.color);
442
+ if (_event.type !== 'grouped_light') {
443
+ // In grouped lights, there is group color, but each light has it's own color.
444
+ node.updateKNXLightColorState(_event.color);
445
+ node.currentHUEDevice.color = _event.color;
446
+ }
419
447
  }
420
- if (_event.hasOwnProperty("dimming")) {
448
+ if (_event.hasOwnProperty("dimming") && _event.dimming.brightness !== undefined) {
421
449
  // Every once on a time, the light transmit the brightness value of 0.39.
422
450
  // To avoid wrongly turn light state on, exit
423
451
  if (_event.dimming.brightness < 1) _event.dimming.brightness = 0;
424
- if (node.currentHUEDevice.hasOwnProperty("on") && node.currentHUEDevice.on.on === false && _event.dimming.brightness === 0) return;
425
- if (node.currentHUEDevice.on.on === false) node.updateKNXLightState(_event.dimming.brightness > 0);
426
- node.updateKNXBrightnessState(_event.dimming.brightness);
427
- // If the brightness reaches zero, the hue lamp "on" property must be set to zero as well
428
- if (_event.dimming.brightness === 0) {
429
- node.serverHue.hueManager.writeHueQueueAdd(
430
- node.hueDevice,
431
- { on: { on: false } },
432
- node.isGrouped_light === false ? "setLight" : "setGroupedLight"
433
- );
452
+ if (node.currentHUEDevice.hasOwnProperty("on") && node.currentHUEDevice.on.on === false && _event.dimming.brightness === 0) {
453
+ // Do nothing, because the light is off and the dimming also is 0
454
+ } else {
455
+ if (node.currentHUEDevice.on.on === false) node.updateKNXLightState(_event.dimming.brightness > 0);
456
+ node.updateKNXBrightnessState(_event.dimming.brightness);
457
+ // If the brightness reaches zero, the hue lamp "on" property must be set to zero as well
458
+ if (_event.dimming.brightness === 0) {
459
+ node.serverHue.hueManager.writeHueQueueAdd(
460
+ node.hueDevice,
461
+ { on: { on: false } },
462
+ node.isGrouped_light === false ? "setLight" : "setGroupedLight",
463
+ );
464
+ node.currentHUEDevice.on.on = false;
465
+ }
466
+ node.currentHUEDevice.dimming.brightness = _event.dimming.brightness;
434
467
  }
435
468
  }
436
- if (_event.hasOwnProperty("color_temperature")) {
469
+ if (_event.hasOwnProperty("color_temperature") && _event.color_temperature.mirek !== undefined) {
437
470
  node.updateKNXLightHSVState(_event.color_temperature.mirek);
471
+ node.currentHUEDevice.color_temperature.mirek = _event.color_temperature.mirek;
438
472
  }
439
473
 
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);
474
+ // // Update the current HUE Device with the new _event
475
+ // function copiaOggettoRicorsivo(objDestinazione, objOrigine) {
476
+ // for (const prop in objOrigine) {
477
+ // if (typeof objOrigine[prop] === "object" && objOrigine[prop] !== null) {
478
+ // // Se la proprietà è un oggetto, copiamola in modo ricorsivo
479
+ // objDestinazione[prop] = objDestinazione[prop] || {};
480
+ // copiaOggettoRicorsivo(objDestinazione[prop], objOrigine[prop]);
481
+ // } else {
482
+ // // Altrimenti, copia il valore della proprietà
483
+ // objDestinazione[prop] = objOrigine[prop];
484
+ // }
485
+ // }
486
+ // }
487
+ // // Copia l'oggettoOrigine nell'oggettoDestinazione mantenendo le proprietà esistenti
488
+ // copiaOggettoRicorsivo(node.currentHUEDevice, _event);
455
489
  }
456
490
  } catch (error) {
457
491
  node.status({
@@ -482,7 +516,7 @@ module.exports = function (RED) {
482
516
  node.setNodeStatusHue({
483
517
  fill: "blue",
484
518
  shape: "ring",
485
- text: "HUE->KNX State",
519
+ text: "HUE->KNX Bright",
486
520
  payload: knxMsgPayload.payload,
487
521
  });
488
522
  }
@@ -510,7 +544,7 @@ module.exports = function (RED) {
510
544
  node.setNodeStatusHue({
511
545
  fill: "blue",
512
546
  shape: "ring",
513
- text: "HUE->KNX State",
547
+ text: "HUE->KNX On/Off",
514
548
  payload: knxMsgPayload.payload,
515
549
  });
516
550
  }
@@ -543,7 +577,7 @@ module.exports = function (RED) {
543
577
  node.setNodeStatusHue({
544
578
  fill: "blue",
545
579
  shape: "ring",
546
- text: "HUE->KNX State",
580
+ text: "HUE->KNX HSV",
547
581
  payload: knxMsgPayload.payload,
548
582
  });
549
583
  }
@@ -557,7 +591,7 @@ module.exports = function (RED) {
557
591
  knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(
558
592
  _value.xy.x,
559
593
  _value.xy.y,
560
- node.currentHUEDevice !== undefined ? node.currentHUEDevice.dimming.brightness : 100
594
+ node.currentHUEDevice !== undefined ? node.currentHUEDevice.dimming.brightness : 100,
561
595
  );
562
596
  // Send to KNX bus
563
597
  if (knxMsgPayload.topic !== "" && knxMsgPayload.topic !== undefined) {
@@ -572,12 +606,14 @@ module.exports = function (RED) {
572
606
  node.setNodeStatusHue({
573
607
  fill: "blue",
574
608
  shape: "ring",
575
- text: "HUE->KNX State",
609
+ text: "HUE->KNX Color",
576
610
  payload: knxMsgPayload.payload,
577
611
  });
578
612
  }
579
613
  };
580
614
 
615
+
616
+
581
617
  // On each deploy, unsubscribe+resubscribe
582
618
  if (node.server) {
583
619
  node.server.removeClient(node);
@@ -586,12 +622,6 @@ module.exports = function (RED) {
586
622
  if (node.serverHue) {
587
623
  node.serverHue.removeClient(node);
588
624
  if (node.serverHue !== null && node.serverHue.hueManager !== null) {
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
625
  try {
596
626
  node.serverHue.addClient(node);
597
627
  } catch (err) {
@@ -1,110 +1,101 @@
1
1
  module.exports = function (RED) {
2
2
  function knxUltimateHueLightSensor(config) {
3
- RED.nodes.createNode(this, config)
4
- const node = this
5
- node.server = RED.nodes.getNode(config.server)
6
- node.serverHue = RED.nodes.getNode(config.serverHue)
7
- node.topic = node.name
8
- node.name = config.name === undefined ? 'Hue' : config.name
9
- node.dpt = ''
10
- node.notifyreadrequest = false
11
- node.notifyreadrequestalsorespondtobus = 'false'
12
- node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
13
- node.notifyresponse = false
14
- node.notifywrite = true
15
- node.initialread = true
16
- node.listenallga = true // Don't remove
17
- node.outputtype = 'write'
18
- node.outputRBE = false // Apply or not RBE to the output (Messages coming from flow)
19
- node.inputRBE = false // Apply or not RBE to the input (Messages coming from BUS)
20
- node.currentPayload = '' // Current value for the RBE input and for the .previouspayload msg
21
- node.passthrough = 'no'
22
- node.formatmultiplyvalue = 1
23
- node.formatnegativevalue = 'leave'
24
- node.formatdecimalsvalue = 2
3
+ RED.nodes.createNode(this, config);
4
+ const node = this;
5
+ node.server = RED.nodes.getNode(config.server);
6
+ node.serverHue = RED.nodes.getNode(config.serverHue);
7
+ node.topic = node.name;
8
+ node.name = config.name === undefined ? 'Hue' : config.name;
9
+ node.dpt = '';
10
+ node.notifyreadrequest = false;
11
+ node.notifyreadrequestalsorespondtobus = 'false';
12
+ node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = '';
13
+ node.notifyresponse = false;
14
+ node.notifywrite = true;
15
+ node.initialread = true;
16
+ node.listenallga = true; // Don't remove
17
+ node.outputtype = 'write';
18
+ node.outputRBE = false; // Apply or not RBE to the output (Messages coming from flow)
19
+ node.inputRBE = false; // Apply or not RBE to the input (Messages coming from BUS)
20
+ node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg
21
+ node.passthrough = 'no';
22
+ node.formatmultiplyvalue = 1;
23
+ node.formatnegativevalue = 'leave';
24
+ node.formatdecimalsvalue = 2;
25
25
 
26
26
  // Used to call the status update from the config node.
27
27
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
28
28
 
29
- }
29
+ };
30
30
  // Used to call the status update from the HUE config node.
31
31
  node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
32
- if (payload === undefined) return
33
- const dDate = new Date()
34
- payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
35
- node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
36
- }
32
+ if (payload === undefined) payload = '';
33
+ const dDate = new Date();
34
+ payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
35
+ node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' });
36
+ };
37
37
 
38
38
  // This function is called by the knx-ultimate config node, to output a msg.payload.
39
39
  node.handleSend = msg => {
40
- }
40
+ };
41
41
 
42
42
  node.handleSendHUE = _event => {
43
43
  try {
44
44
  if (_event.id === config.hueDevice) {
45
- const knxMsgPayload = {}
46
- knxMsgPayload.topic = config.GAlightsensor
47
- knxMsgPayload.dpt = config.dptlightsensor
45
+ const knxMsgPayload = {};
46
+ knxMsgPayload.topic = config.GAlightsensor;
47
+ knxMsgPayload.dpt = config.dptlightsensor;
48
48
 
49
49
  if (_event.hasOwnProperty('light') && _event.light.hasOwnProperty('light_level')) {
50
50
  //console.log(Math.round(10 ** ((_event.light.light_level - 1) / 10000)))
51
51
  //console.log(_event.light.light_level === 0 ? 0 : Math.round(Math.pow(10, (_event.light.light_level - 1) / 10000)))
52
- knxMsgPayload.payload = _event.light.light_level === 0 ? 0 : Math.round(Math.pow(10, (_event.light.light_level - 1) / 10000))
52
+ knxMsgPayload.payload = _event.light.light_level === 0 ? 0 : Math.round(Math.pow(10, (_event.light.light_level - 1) / 10000));
53
53
  // Send to KNX bus
54
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
55
- node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
54
+ if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id });
55
+ node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' });
56
56
 
57
57
  // Setup the output msg
58
- knxMsgPayload.name = node.name
59
- knxMsgPayload.event = 'light_level'
58
+ knxMsgPayload.name = node.name;
59
+ knxMsgPayload.event = 'light_level';
60
60
 
61
61
  // Send payload
62
- knxMsgPayload.rawEvent = _event
63
- node.send(knxMsgPayload)
64
- node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload })
62
+ knxMsgPayload.rawEvent = _event;
63
+ node.send(knxMsgPayload);
64
+ node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload });
65
65
  }
66
66
  }
67
67
  } catch (error) {
68
- node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
68
+ node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' });
69
69
  }
70
- }
70
+ };
71
71
 
72
72
  // On each deploy, unsubscribe+resubscribe
73
73
  if (node.server) {
74
- node.server.removeClient(node)
75
- node.server.addClient(node)
74
+ node.server.removeClient(node);
75
+ node.server.addClient(node);
76
76
  }
77
77
  if (node.serverHue) {
78
- node.serverHue.removeClient(node)
78
+ node.serverHue.removeClient(node);
79
79
  // I must get the object, to store read the status
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
- (async () => {
83
- node.serverHue.addClient(node);
84
- try {
85
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, null, 'getLightLevel', (jLight) => {
86
- node.handleSendHUE(jLight);
87
- })
88
- } catch (error) {
89
- RED.log.error('Errore knxUltimateHueLightSensor subscribing: ' + error.message)
90
- }
91
- })()
82
+ node.serverHue.addClient(node);
92
83
  }
93
84
  }
94
85
 
95
86
  node.on('input', function (msg) {
96
87
 
97
- })
88
+ });
98
89
 
99
90
  node.on('close', function (done) {
100
91
  if (node.server) {
101
- node.server.removeClient(node)
92
+ node.server.removeClient(node);
102
93
  }
103
94
  if (node.serverHue) {
104
- node.serverHue.removeClient(node)
95
+ node.serverHue.removeClient(node);
105
96
  }
106
- done()
107
- })
97
+ done();
98
+ });
108
99
  }
109
- RED.nodes.registerType('knxUltimateHueLightSensor', knxUltimateHueLightSensor)
110
- }
100
+ RED.nodes.registerType('knxUltimateHueLightSensor', knxUltimateHueLightSensor);
101
+ };