node-red-contrib-knx-ultimate 2.2.36 → 2.2.37

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/CHANGELOG.md CHANGED
@@ -6,6 +6,9 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ **Version 2.2.37** - December 2023<br/>
10
+ - HUE Light Node: you can now set the DIM direction for tunable white lights. Fixed some issues as well.<br/>
11
+
9
12
  **Version 2.2.36** - December 2023<br/>
10
13
  - HUE Light Node: Ensure at least one liht belonging to a group was on before switching to nighttime. Otherwise turn all lights on at daytime.<br/>
11
14
 
@@ -633,6 +633,7 @@
633
633
  colorAtSwitchOnNightTime: { value: '{ "kelvin":2700, "brightness":20 }' },
634
634
 
635
635
  invertDayNight: { value: false },
636
+ invertDimTunableWhiteDirection: { value: false },
636
637
 
637
638
  updateKNXBrightnessStatusOnHUEOnOff: { value: "no" },
638
639
  dimSpeed: { value: 5000, required: false },
@@ -1028,6 +1029,13 @@
1028
1029
  <label for="node-input-nameLightKelvinState" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
1029
1030
  <input type="text" id="node-input-nameLightKelvinState" style="width:190px;margin-left: 5px; text-align: left;">
1030
1031
  </div>
1032
+ <div class="form-row">
1033
+ <label style="width:170px" for="node-input-invertDimTunableWhiteDirection">
1034
+ <i class="fa fa-shuffle"></i> Invert DIM direction
1035
+ </label>
1036
+ <input type="checkbox" id="node-input-invertDimTunableWhiteDirection"
1037
+ style="display:inline-block; width:auto; vertical-align:top;" />
1038
+ </div>
1031
1039
  </p>
1032
1040
  </div>
1033
1041
  <div id="tabs-4">
@@ -1283,7 +1291,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
1283
1291
  | Control kelvin | **DPT 7.600:** set the HUE light's temperature in Kelvin degrees, using the KNX range from 0 to 65536. This range will be then transformed in mirek.<br/>**DPT 9.002:** set the temperature using Philips HUE range: 2000K - 6535K (Ambiance range starts at 2200K). Please be aware, conversion may produce slightly changes in Kelvin degrees value, due to KNX RGB or Kelvin degrees to HUE mirek degrees conversion.|
1284
1292
  | Status %| Link this to the light temperature status group address. Datapoint is 5.001 absolute value. 0 is full warm, 100 is full cold.|
1285
1293
  | Status kelvin | **DPT 7.600:** get the HUE light's temperature in Kelvin degrees, using the KNX range from 0 to 65536. This range will be then transformed in kelvin degrees.<br/>**DPT 9.002:** get the temperature using Philips HUE range: 2000K - 6535K (Ambiance range starts at 2200K). Please be aware, conversion may produce slightly changes in Kelvin degrees value, due to KNX RGB or Kelvin degrees to HUE mirek degrees conversion. |
1286
-
1294
+ | Invert DIM direction | Inverts the DIM direction. |
1287
1295
  <br/>
1288
1296
 
1289
1297
  **Colors**
@@ -45,6 +45,9 @@ module.exports = function (RED) {
45
45
  config.colorAtSwitchOnNightTime = (config.colorAtSwitchOnNightTime === '' || config.colorAtSwitchOnNightTime === undefined) ? '{ "kelvin":2700, "brightness":20 }' : config.colorAtSwitchOnNightTime;
46
46
  config.colorAtSwitchOnDayTime = config.colorAtSwitchOnDayTime.replace("geen", "green");
47
47
  config.colorAtSwitchOnNightTime = config.colorAtSwitchOnNightTime.replace("geen", "green");
48
+ config.dimSpeed = config.dimSpeed === undefined ? 5000 : Number(config.dimSpeed);
49
+ config.invertDimTunableWhiteDirection = config.invertDimTunableWhiteDirection === undefined ? false : true;
50
+
48
51
  // Transform HEX in RGB and stringified json in json oblects.
49
52
  if (config.colorAtSwitchOnDayTime.indexOf("#") !== -1) {
50
53
  // Transform to rgb.
@@ -286,7 +289,7 @@ module.exports = function (RED) {
286
289
  // { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
287
290
  // { decr_incr: 0, data: 1 } : Start decreasing until { decr_incr: 0, data: 0 } is received.
288
291
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightHSV));
289
- node.hueDimmingTunableWhite(msg.payload.decr_incr, msg.payload.data, config.dimSpeed);
292
+ node.hueDimmingTunableWhite(msg.payload.decr_incr, msg.payload.data, 5000);
290
293
  node.setNodeStatusHue({
291
294
  fill: "green", shape: "dot", text: "KNX->HUE", payload: JSON.stringify(msg.payload),
292
295
  });
@@ -481,106 +484,137 @@ module.exports = function (RED) {
481
484
 
482
485
  // Start dimming
483
486
  // ***********************************************************
484
- node.hueDimming = function hueDimming(_KNXaction, _KNXbrightness_delta, _dimSpeedInMillisecs = undefined) {
485
- // 31/10/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success
487
+ node.hueDimming = function hueDimming(_KNXaction, _KNXbrightness_Direction, _dimSpeedInMillisecs = undefined) {
488
+ // 31/10/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success, will use the standard dimming calculations
486
489
  // i decide to go to the "step brightness" way.
487
- let hueTelegram = {};
488
- const numStep = 10; // Steps from 0 to 100 by 10
489
- if (_dimSpeedInMillisecs === undefined || _dimSpeedInMillisecs === '') _dimSpeedInMillisecs = 5000;
490
-
491
- if (_KNXbrightness_delta === 0 && _KNXaction === 0) {
492
- // STOP DIM
493
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
494
- node.brightnessStep = null;
495
- return;
496
- }
490
+ try {
491
+ let hueTelegram = {};
492
+ let numStep = 10; // Steps from 0 to 100 by 10
493
+
494
+ if (_KNXbrightness_Direction === 0 && _KNXaction === 0) {
495
+ // STOP DIM
496
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
497
+ node.brightnessStep = null;
498
+ return;
499
+ }
497
500
 
498
- // Set the actual brightness to start with
499
- if (node.brightnessStep === null || node.brightnessStep === undefined) node.brightnessStep = node.currentHUEDevice.dimming.brightness || 50;
500
- node.brightnessStep = Math.ceil(Number(node.brightnessStep));
501
-
502
- // Set the speed
503
- _dimSpeedInMillisecs /= numStep;
504
-
505
- // We have also minDimLevelLight and maxDimLevelLight to take care of.
506
- let minDimLevelLight = config.minDimLevelLight === undefined ? 10 : Number(config.minDimLevelLight);
507
- if (config.minDimLevelLight === "useHueLightLevel" && node.currentHUEDevice.dimming.min_dim_level === undefined) minDimLevelLight = 10;
508
- const maxDimLevelLight = config.maxDimLevelLight === undefined ? 100 : Number(config.maxDimLevelLight);
509
-
510
- if (_KNXbrightness_delta > 0 && _KNXaction === 1) {
511
- // DIM UP
512
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
513
- node.timerStepDim = setInterval(() => {
514
- node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
515
- node.brightnessStep += numStep;
516
- if (node.brightnessStep > maxDimLevelLight) node.brightnessStep = maxDimLevelLight;
517
- hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs } };
518
- // Switch on the light if off
519
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
520
- hueTelegram.on = { on: true };
521
- }
522
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
523
- if (node.brightnessStep >= maxDimLevelLight) clearInterval(node.timerStepDim);
524
- }, _dimSpeedInMillisecs);
525
- }
526
- if (_KNXbrightness_delta > 0 && _KNXaction === 0) {
527
- if (node.currentHUEDevice.on.on === false) return; // Don't dim down, if the light is already off.
528
- // DIM DOWN
529
- if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
530
- node.timerStepDim = setInterval(() => {
531
- node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
532
- node.brightnessStep -= numStep;
533
- if (node.brightnessStep < minDimLevelLight) node.brightnessStep = minDimLevelLight;
534
- hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs } };
535
- // Switch off the light if on
536
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStep === 0) {
537
- hueTelegram.on = { on: false };
538
- }
539
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
540
- if (node.brightnessStep <= minDimLevelLight) clearInterval(node.timerStepDim);
541
- }, _dimSpeedInMillisecs);
542
- }
501
+ // Set the actual brightness to start with
502
+ if (node.brightnessStep === null || node.brightnessStep === undefined) node.brightnessStep = node.currentHUEDevice.dimming.brightness || 50;
503
+ node.brightnessStep = Math.ceil(Number(node.brightnessStep));
504
+
505
+ // Set the speed
506
+ _dimSpeedInMillisecs /= numStep;
507
+ numStep = Math.round((config.maxDimLevelLight - config.minDimLevelLight) / numStep, 0);
508
+
509
+ // We have also minDimLevelLight and maxDimLevelLight to take care of.
510
+ let minDimLevelLight = config.minDimLevelLight === undefined ? 10 : Number(config.minDimLevelLight);
511
+ if (config.minDimLevelLight === "useHueLightLevel" && node.currentHUEDevice.dimming.min_dim_level === undefined) minDimLevelLight = 10;
512
+ const maxDimLevelLight = config.maxDimLevelLight === undefined ? 100 : Number(config.maxDimLevelLight);
513
+
514
+ if (_KNXbrightness_Direction > 0 && _KNXaction === 1) {
515
+ // DIM UP
516
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
517
+ node.timerStepDim = setInterval(() => {
518
+ node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
519
+ node.brightnessStep += numStep;
520
+ if (node.brightnessStep > maxDimLevelLight) node.brightnessStep = maxDimLevelLight;
521
+ hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs + 100 } }; // + 100 is to avoid ladder effect
522
+ // Switch on the light if off
523
+ if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
524
+ hueTelegram.on = { on: true };
525
+ }
526
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
527
+ if (node.brightnessStep >= maxDimLevelLight) clearInterval(node.timerStepDim);
528
+ }, _dimSpeedInMillisecs);
529
+ }
530
+ if (_KNXbrightness_Direction > 0 && _KNXaction === 0) {
531
+ if (node.currentHUEDevice.on.on === false) return; // Don't dim down, if the light is already off.
532
+ // DIM DOWN
533
+ if (node.timerStepDim !== undefined) clearInterval(node.timerStepDim);
534
+ node.timerStepDim = setInterval(() => {
535
+ node.updateKNXBrightnessState(node.brightnessStep); // Unnecessary, but necessary to set the KNX Status in real time.
536
+ node.brightnessStep -= numStep;
537
+ if (node.brightnessStep < minDimLevelLight) node.brightnessStep = minDimLevelLight;
538
+ hueTelegram = { dimming: { brightness: node.brightnessStep }, dynamics: { duration: _dimSpeedInMillisecs + 100 } };// + 100 is to avoid ladder effect
539
+ // Switch off the light if on
540
+ if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStep === 0) {
541
+ hueTelegram.on = { on: false };
542
+ }
543
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
544
+ if (node.brightnessStep <= minDimLevelLight) clearInterval(node.timerStepDim);
545
+ }, _dimSpeedInMillisecs);
546
+ }
547
+ } catch (error) { }
543
548
  };
544
549
  // ***********************************************************
545
550
 
546
551
  // Start dimming tunable white
547
552
  // mirek: required(integer minimum: 153, maximum: 500)
548
553
  // ***********************************************************
549
- node.hueDimmingTunableWhite = function hueDimming(_KNXaction, _KNXbrightness_delta, _dimSpeedInMillisecs = undefined) {
550
- let dimDirection = "stop";
551
- let hueTelegram = {};
552
- _dimSpeedInMillisecs = _dimSpeedInMillisecs === undefined || _dimSpeedInMillisecs === "" ? 5000 : _dimSpeedInMillisecs;
553
- let delta = 0;
554
- if (node.currentHUEDevice.color_temperature.mirek === undefined) delta = 347 - Math.round(173, 0); // Unable to read the mirek, set medium as default
555
- // We have also minDimLevelLight and maxDimLevelLight to take care of.
556
- // Mirek limits are not taken in consideration.
557
- // Maximum mirek is 347
558
- if (_KNXbrightness_delta === 0 && _KNXaction === 0) {
559
- dimDirection = "stop";
560
- hueTelegram = { color_temperature_delta: { action: dimDirection } };
561
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
562
- return;
563
- }
564
- if (_KNXbrightness_delta > 0 && _KNXaction === 1) {
565
- if (node.currentHUEDevice.color_temperature.mirek !== undefined) delta = 347 - Math.round(node.currentHUEDevice.color_temperature.mirek, 0);
566
- dimDirection = "up";
567
- }
568
- if (_KNXbrightness_delta > 0 && _KNXaction === 0) {
569
- // 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)
570
- if (node.currentHUEDevice.color_temperature.mirek !== undefined) delta = Math.round(node.currentHUEDevice.color_temperature.mirek, 0);
571
- dimDirection = "down";
572
- }
573
- // Calculate the dimming time based on delta
574
- // 10000:x=347:delta
575
- // x = (10000 * delta) / 347
576
- _dimSpeedInMillisecs = Math.round((_dimSpeedInMillisecs * delta) / 347, 0);
577
-
578
- hueTelegram = { color_temperature_delta: { action: dimDirection, mirek_delta: delta }, dynamics: { duration: _dimSpeedInMillisecs } };
579
- // Switch on the light if off
580
- if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false && dimDirection === "up") {
581
- hueTelegram.on = { on: true };
582
- }
583
- node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
554
+ node.hueDimmingTunableWhite = function hueDimming(_KNXaction, _KNXbrightness_DirectionTunableWhite, _dimSpeedInMillisecsTunableWhite = undefined) {
555
+ // 23/23/2023 after many attempts to use dimming_delta function of the HueApeV2, loosing days of my life, without a decent success, will use the standard dimming calculations
556
+ // i decide to go to the "step brightness" way.
557
+ try {
558
+
559
+ if (_KNXbrightness_DirectionTunableWhite === 0 && _KNXaction === 0) {
560
+ // STOP DIM
561
+ if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite);
562
+ node.brightnessStepTunableWhite = null;
563
+ return;
564
+ }
565
+
566
+ let numStepTunableWhite = 10; // Steps from 153 to 500
567
+ if (config.invertDimTunableWhiteDirection === true) {
568
+ if (_KNXaction === 1) { _KNXaction = 0; } else { _KNXaction = 1; }
569
+ }
570
+
571
+ // Set the actual brightness to start with
572
+ if (node.brightnessStepTunableWhite === null || node.brightnessStepTunableWhite === undefined) node.brightnessStepTunableWhite = node.currentHUEDevice.color_temperature.mirek || 372;
573
+ node.brightnessStepTunableWhite = Math.ceil(Number(node.brightnessStepTunableWhite));
574
+
575
+ // Set the speed
576
+ _dimSpeedInMillisecsTunableWhite = Math.ceil(_dimSpeedInMillisecsTunableWhite / numStepTunableWhite);
577
+
578
+ const minDimLevelLightTunableWhite = 153;
579
+ const maxDimLevelLightTunableWhite = 500;
580
+ //numStepTunableWhite = hueColorConverter.ColorConverter.scale(numStepTunableWhite, [0, 100], [minDimLevelLightTunableWhite, maxDimLevelLightTunableWhite]);
581
+ //numStepTunableWhite = hueColorConverter.ColorConverter.scale(numStepTunableWhite, [node.brightnessStepTunableWhite, maxDimLevelLightTunableWhite], [node.brightnessStepTunableWhite, maxDimLevelLightTunableWhite]);
582
+ numStepTunableWhite = Math.round((maxDimLevelLightTunableWhite - minDimLevelLightTunableWhite) / numStepTunableWhite, 0);
583
+
584
+ if (_KNXbrightness_DirectionTunableWhite > 0 && _KNXaction === 1) {
585
+ // DIM UP
586
+ if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite);
587
+ node.timerStepDimTunableWhite = setInterval(() => {
588
+ node.updateKNXLightHSVState(node.brightnessStepTunableWhite); // Unnecessary, but necessary to set the KNX Status in real time.
589
+ node.brightnessStepTunableWhite += numStepTunableWhite; // *2 to speed up the things
590
+ if (node.brightnessStepTunableWhite > maxDimLevelLightTunableWhite) node.brightnessStepTunableWhite = maxDimLevelLightTunableWhite;
591
+ const hueTelegram = { color_temperature: { mirek: node.brightnessStepTunableWhite }, dynamics: { duration: _dimSpeedInMillisecsTunableWhite } };
592
+ // Switch on the light if off
593
+ if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === false) {
594
+ hueTelegram.on = { on: true };
595
+ }
596
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
597
+ if (node.brightnessStepTunableWhite >= maxDimLevelLightTunableWhite) clearInterval(node.timerStepDimTunableWhite);
598
+ }, _dimSpeedInMillisecsTunableWhite);
599
+ }
600
+ if (_KNXbrightness_DirectionTunableWhite > 0 && _KNXaction === 0) {
601
+ if (node.currentHUEDevice.on.on === false) return; // Don't dim down, if the light is already off.
602
+ // DIM DOWN
603
+ if (node.timerStepDimTunableWhite !== undefined) clearInterval(node.timerStepDimTunableWhite);
604
+ node.timerStepDimTunableWhite = setInterval(() => {
605
+ node.updateKNXLightHSVState(node.brightnessStepTunableWhite); // Unnecessary, but necessary to set the KNX Status in real time.
606
+ node.brightnessStepTunableWhite -= numStepTunableWhite; // *2 to speed up the things
607
+ if (node.brightnessStepTunableWhite < minDimLevelLightTunableWhite) node.brightnessStepTunableWhite = minDimLevelLightTunableWhite;
608
+ const hueTelegram = { color_temperature: { mirek: node.brightnessStepTunableWhite }, dynamics: { duration: _dimSpeedInMillisecsTunableWhite } };
609
+ // Switch off the light if on
610
+ if (node.currentHUEDevice.on !== undefined && node.currentHUEDevice.on.on === true && node.brightnessStepTunableWhite === 0) {
611
+ hueTelegram.on = { on: false };
612
+ }
613
+ node.serverHue.hueManager.writeHueQueueAdd(node.hueDevice, hueTelegram, node.isGrouped_light === false ? "setLight" : "setGroupedLight");
614
+ if (node.brightnessStepTunableWhite <= minDimLevelLightTunableWhite) clearInterval(node.timerStepDimTunableWhite);
615
+ }, _dimSpeedInMillisecsTunableWhite);
616
+ }
617
+ } catch (error) { }
584
618
  };
585
619
  // ***********************************************************
586
620
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=16.0.0"
5
5
  },
6
- "version": "2.2.36",
6
+ "version": "2.2.37",
7
7
  "description": "Control your KNX intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.",
8
8
  "dependencies": {
9
9
  "binary-parser": "2.2.1",