node-red-contrib-knx-ultimate 2.2.32 → 2.2.34
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 +10 -1
- package/nodes/knxUltimate-config.js +1 -0
- package/nodes/knxUltimateHueLight.html +104 -27
- package/nodes/knxUltimateHueLight.js +81 -53
- package/nodes/plugins/HomeAssistantImporter-sidebar-plugin.html +38 -0
- package/nodes/utils/commonFunctions.js +21 -0
- package/package.json +5 -4
- package/resources/HA-icon.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 2.2.34** - December 2023<br/>
|
|
10
|
+
- NEW: HUE Light Node: there is a new tab that auto-generates the light entity for Home Assistant.<br/>
|
|
11
|
+
- HUE Light: resuming the last daytime status after nighttime, if the switch on behaviour at daytime is set to None.<br/>
|
|
12
|
+
- The new HUE Scene node has exited the BETA status and is now considered safe to be used.<br/>
|
|
13
|
+
|
|
14
|
+
**Version 2.2.33** - December 2023<br/>
|
|
15
|
+
- Quickfix: HUE Light: fixed an issue in the conversion of tunable white from Datapint 7.600 to mired and vice versa.<br/>
|
|
16
|
+
- WARNING: the new HUE Scene node is to be considered **BETA (= in testing with user feedback)**.<br/>
|
|
17
|
+
|
|
9
18
|
**Version 2.2.32** - December 2023<br/>
|
|
10
|
-
- Quickfix: HUE Light: fixed an issue in the conversion of tunable white from 9.002 to mired and vice versa.<br/>
|
|
19
|
+
- Quickfix: HUE Light: fixed an issue in the conversion of tunable white from Datapoint 9.002 to mired and vice versa.<br/>
|
|
11
20
|
- WARNING: the new HUE Scene node is to be considered **BETA (= in testing with user feedback)**.<br/>
|
|
12
21
|
|
|
13
22
|
**Version 2.2.31** - December 2023<br/>
|
|
@@ -15,6 +15,7 @@ const dptlib = require("../KNXEngine/src/dptlib");
|
|
|
15
15
|
const payloadRounder = require("./utils/payloadManipulation");
|
|
16
16
|
const loggerEngine = require("./utils/sysLogger.js");
|
|
17
17
|
|
|
18
|
+
|
|
18
19
|
// Helpers
|
|
19
20
|
const sortBy = (field) => (a, b) => {
|
|
20
21
|
if (a[field] > b[field]) {
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
$("#node-input-specifySwitchOnBrightness").empty().append(
|
|
190
190
|
$("<option>")
|
|
191
191
|
.val("no")
|
|
192
|
-
.text("
|
|
192
|
+
.text("None")
|
|
193
193
|
).append(
|
|
194
194
|
$("<option>")
|
|
195
195
|
.val("yes")
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
$("#node-input-specifySwitchOnBrightness").empty().append(
|
|
223
223
|
$("<option>")
|
|
224
224
|
.val("no")
|
|
225
|
-
.text("
|
|
225
|
+
.text("None")
|
|
226
226
|
);
|
|
227
227
|
$("#node-input-enableDayNightLighting").empty().append(
|
|
228
228
|
$("<option>")
|
|
@@ -655,11 +655,28 @@
|
|
|
655
655
|
},
|
|
656
656
|
paletteLabel: "Hue Light",
|
|
657
657
|
oneditprepare: function () {
|
|
658
|
+
// $.post("banana", { func: "getNameAndTime" }, function (data) {
|
|
659
|
+
// //alert(data.body); // John
|
|
660
|
+
// }, "json");
|
|
661
|
+
try {
|
|
662
|
+
RED.sidebar.show("help");
|
|
663
|
+
} catch (error) { }
|
|
658
664
|
onEditPrepare(this);
|
|
665
|
+
let node = this;
|
|
666
|
+
node.yamlEditor = RED.editor.createEditor({
|
|
667
|
+
id: 'aceEditor',
|
|
668
|
+
mode: 'ace/mode/text'
|
|
669
|
+
});
|
|
670
|
+
node.yamlEditor.session.setValue(yamelize());
|
|
671
|
+
$('[id*="node-input-"]').on('keyup change autocompletechange', function () {
|
|
672
|
+
try {
|
|
673
|
+
node.yamlEditor.session.setValue(yamelize());
|
|
674
|
+
} catch (error) {
|
|
675
|
+
}
|
|
676
|
+
});
|
|
659
677
|
},
|
|
660
678
|
oneditsave: function () {
|
|
661
679
|
//RED.sidebar.removeTab("tabNRColor");
|
|
662
|
-
//RED.sidebar.show("help");
|
|
663
680
|
if ($("#node-input-enableNodePINS").val() === "yes") {
|
|
664
681
|
this.outputs = 1;
|
|
665
682
|
this.inputs = 1;
|
|
@@ -674,9 +691,6 @@
|
|
|
674
691
|
}
|
|
675
692
|
});
|
|
676
693
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
694
|
function rgbHex(red, green, blue, alpha) {
|
|
681
695
|
const toHex = (red, green, blue, alpha) => ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1) + alpha;
|
|
682
696
|
const parseCssRgbString = (input) => {
|
|
@@ -747,6 +761,60 @@
|
|
|
747
761
|
|
|
748
762
|
return toHex(red, green, blue, alpha);
|
|
749
763
|
}
|
|
764
|
+
function yamelize() {
|
|
765
|
+
try {
|
|
766
|
+
// Get the HUE Node properties and transform it into yaml
|
|
767
|
+
let sYaml = '- name: "' + $("#node-input-name").val() + '"' + "\n";
|
|
768
|
+
sYaml += $("#node-input-GALightSwitch").val() != '' ? ' address: "' + $("#node-input-GALightSwitch").val() + '"' + "\n" : '';
|
|
769
|
+
sYaml += $("#node-input-GALightState").val() != '' ? ' state_address: "' + $("#node-input-GALightState").val() + '"' + "\n" : '';
|
|
770
|
+
sYaml += $("#node-input-GALightBrightness").val() != '' ? ' brightness_address: "' + $("#node-input-GALightBrightness").val() + '"' + "\n" : '';
|
|
771
|
+
sYaml += $("#node-input-GALightBrightnessState").val() != '' ? ' brightness_state_address: "' + $("#node-input-GALightBrightnessState").val() + '"' + "\n" : '';
|
|
772
|
+
|
|
773
|
+
//#region color_temperature_mode
|
|
774
|
+
// ----------------------------
|
|
775
|
+
if ($("#node-input-GALightHSVPercentage").val !== '') {
|
|
776
|
+
|
|
777
|
+
// color_temperature_mode: relative
|
|
778
|
+
sYaml += ' color_temperature_mode: relative' + '\n';
|
|
779
|
+
sYaml += ' color_temperature_address: "' + $("#node-input-GALightHSVPercentage").val() + '"\n';
|
|
780
|
+
sYaml += $("#node-input-GALightHSVState").val() != '' ? ' color_temperature_state_address: "' + $("#node-input-GALightHSVState").val() + '"' + "\n" : '';
|
|
781
|
+
sYaml += ' min_kelvin: 2200' + '\n';
|
|
782
|
+
sYaml += ' max_kelvin: 6500' + '\n';
|
|
783
|
+
|
|
784
|
+
} else if ($("#node-input-GALightKelvin").val() !== '') {
|
|
785
|
+
|
|
786
|
+
if ($("#node-input-dptLightKelvin").val() === '7.600') {
|
|
787
|
+
sYaml += ' color_temperature_mode: absolute' + '\n';
|
|
788
|
+
sYaml += ' color_temperature_address: "' + $("#node-input-GALightKelvin").val() + '"\n';
|
|
789
|
+
if ($("#node-input-dptLightKelvinState").val() === '7.600') {
|
|
790
|
+
// Add the status only if also 7.600
|
|
791
|
+
sYaml += $("#node-input-GALightKelvinState").val() != '' ? ' color_temperature_state_address: "' + $("#node-input-GALightKelvinState").val() + '"' + "\n" : '';
|
|
792
|
+
}
|
|
793
|
+
sYaml += ' min_kelvin: 2200' + '\n';
|
|
794
|
+
sYaml += ' max_kelvin: 6500' + '\n';
|
|
795
|
+
|
|
796
|
+
} else if ($("#node-input-dptLightKelvin").val() === '9.002') {
|
|
797
|
+
|
|
798
|
+
sYaml += ' color_temperature_mode: absolute_float' + '\n';
|
|
799
|
+
sYaml += ' color_temperature_address: "' + $("#node-input-GALightKelvin").val() + '"\n';
|
|
800
|
+
if ($("#node-input-dptLightKelvinState").val() === '9.002') {
|
|
801
|
+
// Add the status only if also 7.600
|
|
802
|
+
sYaml += $("#node-input-GALightKelvinState").val() != '' ? ' color_temperature_state_address: "' + $("#node-input-GALightKelvinState").val() + '"' + "\n" : '';
|
|
803
|
+
}
|
|
804
|
+
sYaml += ' min_kelvin: 2200' + '\n';
|
|
805
|
+
sYaml += ' max_kelvin: 6500' + '\n';
|
|
806
|
+
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
// ----------------------------
|
|
810
|
+
//#endregion
|
|
811
|
+
|
|
812
|
+
sYaml += $("#node-input-GALightColor").val() != '' ? ' color_address: "' + $("#node-input-GALightColor").val() + '"' + "\n" : '';
|
|
813
|
+
sYaml += $("#node-input-GALightColorState").val() != '' ? ' color_state_address: "' + $("#node-input-GALightColorState").val() + '"' + "\n" : '';
|
|
814
|
+
|
|
815
|
+
return (sYaml);
|
|
816
|
+
} catch (error) { }
|
|
817
|
+
}
|
|
750
818
|
|
|
751
819
|
}())
|
|
752
820
|
|
|
@@ -795,30 +863,29 @@
|
|
|
795
863
|
<br />
|
|
796
864
|
|
|
797
865
|
|
|
798
|
-
<div id="tabs"
|
|
866
|
+
<div id="tabs" hidden>
|
|
799
867
|
<ul>
|
|
800
|
-
<li><a href="#tabs-1">Switching</a></li>
|
|
801
|
-
<li><a href="#tabs-2">Dim/Brightness</a></li>
|
|
802
|
-
<li><a href="#tabs-3">Tunable white</a></li>
|
|
803
|
-
<li><a href="#tabs-4">Colors</a></li>
|
|
804
|
-
<li><a href="#tabs-5">Effects</a></li>
|
|
805
|
-
<li><a href="#tabs-6">Behaviour</a></li>
|
|
868
|
+
<li><a href="#tabs-1"><i class="fa-solid fa-toggle-on fa-beat"></i> Switching</a></li>
|
|
869
|
+
<li><a href="#tabs-2"><i class="fa-solid fa-arrow-up-wide-short fa-beat"></i> Dim/Brightness</a></li>
|
|
870
|
+
<li><a href="#tabs-3"><i class="fa-solid fa-temperature-quarter fa-beat"></i> Tunable white</a></li>
|
|
871
|
+
<li><a href="#tabs-4"><i class="fa-solid fa-palette fa-beat"></i> Colors</a></li>
|
|
872
|
+
<li><a href="#tabs-5"><i class="fa-solid fa-heart-circle-check fa-beat"></i> Effects</a></li>
|
|
873
|
+
<li><a href="#tabs-6"><i class="fa-solid fa-code-merge fa-beat"></i> Behaviour</a></li>
|
|
874
|
+
<li><a href="#tabs-7"><i class="fa-solid fa-house fa-beat"></i> Home Assistant Export (beta)</a></li>
|
|
806
875
|
</ul>
|
|
807
876
|
<div id="tabs-1">
|
|
808
877
|
<p>
|
|
809
878
|
<div class="form-row">
|
|
810
879
|
<label for="node-input-nameLightSwitch" style="width:110px;"><i class="fa fa-play-circle-o"></i> Control</label>
|
|
811
880
|
|
|
812
|
-
<label for="node-input-GALightSwitch" style="width:20px;"
|
|
813
|
-
data-i18n="knxUltimateHueLight.node-input-GALightSwitch"></span></label>
|
|
881
|
+
<label for="node-input-GALightSwitch" style="width:20px;">GA</label>
|
|
814
882
|
<input type="text" id="node-input-GALightSwitch" placeholder="Ex: 1/1/1"
|
|
815
883
|
style="width:70px;margin-left: 5px; text-align: left;">
|
|
816
884
|
|
|
817
885
|
<label for="node-input-dptLightSwitch" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
|
|
818
886
|
<select id="node-input-dptLightSwitch" style="width:140px;"></select>
|
|
819
887
|
|
|
820
|
-
<label for="node-input-nameLightSwitch" style="width:50px; margin-left: 0px; text-align: right;"
|
|
821
|
-
data-i18n="knxUltimateHueLight.node-input-name"></span></label>
|
|
888
|
+
<label for="node-input-nameLightSwitch" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
|
|
822
889
|
<input type="text" id="node-input-nameLightSwitch" style="width:190px;margin-left: 5px; text-align: left;">
|
|
823
890
|
</div>
|
|
824
891
|
<div class="form-row">
|
|
@@ -842,8 +909,7 @@
|
|
|
842
909
|
<div class="form-row">
|
|
843
910
|
<label for="node-input-nameLightDIM" style="width:110px;"><i class="fa fa-play-circle-o"></i> Control</label>
|
|
844
911
|
|
|
845
|
-
<label for="node-input-GALightDIM" style="width:20px;"
|
|
846
|
-
data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
|
|
912
|
+
<label for="node-input-GALightDIM" style="width:20px;">GA</label>
|
|
847
913
|
<input type="text" id="node-input-GALightDIM" placeholder="Ex: 1/1/1"
|
|
848
914
|
style="width:70px;margin-left: 5px; text-align: left;">
|
|
849
915
|
|
|
@@ -858,8 +924,7 @@
|
|
|
858
924
|
<label for="node-input-nameLightBrightness" style="width:110px;"><i class="fa fa-play-circle-o"></i> Control
|
|
859
925
|
%</label>
|
|
860
926
|
|
|
861
|
-
<label for="node-input-GALightBrightness" style="width:20px;"
|
|
862
|
-
data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
|
|
927
|
+
<label for="node-input-GALightBrightness" style="width:20px;">GA</label>
|
|
863
928
|
<input type="text" id="node-input-GALightBrightness" placeholder="Ex: 1/1/1"
|
|
864
929
|
style="width:70px;margin-left: 5px; text-align: left;">
|
|
865
930
|
|
|
@@ -939,8 +1004,7 @@
|
|
|
939
1004
|
<label for="node-input-nameLightHSVState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Status
|
|
940
1005
|
%</label>
|
|
941
1006
|
|
|
942
|
-
<label for="node-input-GALightHSVState" style="width:20px;"
|
|
943
|
-
data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
|
|
1007
|
+
<label for="node-input-GALightHSVState" style="width:20px;">GA</label>
|
|
944
1008
|
<input type="text" id="node-input-GALightHSVState" placeholder="Ex: 1/1/1"
|
|
945
1009
|
style="width:70px;margin-left: 5px; text-align: left;">
|
|
946
1010
|
|
|
@@ -1062,7 +1126,7 @@
|
|
|
1062
1126
|
<i class="fa fa-tag"></i> Switch on behaviour
|
|
1063
1127
|
</label>
|
|
1064
1128
|
<select id="node-input-specifySwitchOnBrightness">
|
|
1065
|
-
<option value="no">
|
|
1129
|
+
<option value="no">None</option>
|
|
1066
1130
|
<!-- <option value="temperature">Select temperature and brightness</option>
|
|
1067
1131
|
<option value="yes">Select color</option> -->
|
|
1068
1132
|
</select>
|
|
@@ -1165,14 +1229,19 @@
|
|
|
1165
1229
|
</div>
|
|
1166
1230
|
</p>
|
|
1167
1231
|
</div>
|
|
1232
|
+
<div id="tabs-7">
|
|
1233
|
+
<p>
|
|
1234
|
+
<br/> <b>YAML</b> <br/>
|
|
1235
|
+
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="aceEditor"></div>
|
|
1236
|
+
<!-- <button type="button" class="red-ui-button">Button</button> -->
|
|
1237
|
+
</p>
|
|
1238
|
+
</div>
|
|
1168
1239
|
|
|
1169
1240
|
<br />
|
|
1170
1241
|
</script>
|
|
1171
1242
|
|
|
1172
1243
|
|
|
1173
1244
|
<script type="text/markdown" data-help-name="knxUltimateHueLight">
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
1245
|
<p>This node lets you control your Philips HUE light and grouped lights and also gets the states of this lights, to be sent to the KNX bus.</p>
|
|
1177
1246
|
|
|
1178
1247
|
**General**
|
|
@@ -1238,7 +1307,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
1238
1307
|
| Property | Description |
|
|
1239
1308
|
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1240
1309
|
| KNX Brightness Status | Updates the KNX brightness group address status, whenever the HUE lamp is switched ON/OFF. The options are **When HUE light is Off send 0%. When HUE On, restore previous value (Default KNX behaviour)** and **Leave as is (default HUE behaviour)**. If you have KNX dimmer with brightness status, like MDT, the suggested option is ***When HUE light is Off send 0%. When HUE On, restore previous value (Default KNX behaviour)*** |
|
|
1241
|
-
| Switch on behaviour | It sets the behaviour of your lights when switched on. You can choose from differents behaviours.<br/>**Select color:** the light will be switched on with the color of your choice. To change color, just CLICK on the color selector (under the *Select color* control).<br/>**Select temperature and brightness:** the light will be switched on with the temperature (Kelvin) and brightness (0-100) of your choice.<br
|
|
1310
|
+
| Switch on behaviour | It sets the behaviour of your lights when switched on. You can choose from differents behaviours.<br/>**Select color:** the light will be switched on with the color of your choice. To change color, just CLICK on the color selector (under the *Select color* control).<br/>**Select temperature and brightness:** the light will be switched on with the temperature (Kelvin) and brightness (0-100) of your choice.<br/>**None:** the light will retain its last status. In case you've enable the night lighting, after the night time ends, the lamp will resume the color/temperature/brightness state set at day time. |
|
|
1242
1311
|
| Night Lighting | It allows to set a particular light color/brightness at nighttime. The options are the same as the daytime. You could select either a temperature/brightness or color. A cozy temperature of 2700 Kelvin, with a brightness of 10% or 20%, is a good choice for bathroom's night light.|
|
|
1243
1312
|
| Day/Night | Select the group address used to set the day/night behaviour. The group address value is _true_ if daytime, _false_ if nighttime. |
|
|
1244
1313
|
| Invert day/night values | Invert the values of _Day/Night_ group address. Default value is **unchecked**. |
|
|
@@ -1253,6 +1322,14 @@ The Dimming function works in **KNX mode `start` and `stop`**. To start dimming,
|
|
|
1253
1322
|
|
|
1254
1323
|
<br/>
|
|
1255
1324
|
|
|
1325
|
+
**Home Assistant Export**
|
|
1326
|
+
|
|
1327
|
+
| Property | Description |
|
|
1328
|
+
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1329
|
+
| YAML | Get or sets the node properties based on Home Assistant YAML format. By editing the node properties, the YAML will automatically be created. You can copy and paste it into the "knx_lights.yaml" Home Assistant config file. Not yet implemented: likewise, if you copy the single light descriptor from the "knx_lights.yaml" Home Assistant config file and paste it here, the relative node properties will be automatically set. |
|
|
1330
|
+
|
|
1331
|
+
<br/>
|
|
1332
|
+
|
|
1256
1333
|
[Find it useful?](https://www.paypal.me/techtoday)
|
|
1257
1334
|
|
|
1258
1335
|
<br/>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/* eslint-disable camelcase */
|
|
3
3
|
/* eslint-disable max-len */
|
|
4
4
|
/* eslint-disable no-lonely-if */
|
|
5
|
+
const cloneDeep = require("lodash/cloneDeep");
|
|
6
|
+
|
|
5
7
|
module.exports = function (RED) {
|
|
6
8
|
const dptlib = require("../KNXEngine/src/dptlib");
|
|
7
9
|
const hueColorConverter = require("./utils/hueColorConverter");
|
|
@@ -31,6 +33,7 @@ module.exports = function (RED) {
|
|
|
31
33
|
node.formatnegativevalue = "leave";
|
|
32
34
|
node.formatdecimalsvalue = 2;
|
|
33
35
|
node.currentHUEDevice = undefined; // At start, this value is filled by a call to HUE api. It stores a value representing the current light status.
|
|
36
|
+
node.HUEDeviceWhileDaytime = null;// This retains the HUE device status while daytime, to be restored after nighttime elapsed.
|
|
34
37
|
node.DayTime = true;
|
|
35
38
|
node.isGrouped_light = config.hueDevice.split("#")[1] === "grouped_light";
|
|
36
39
|
node.hueDevice = config.hueDevice.split("#")[0];
|
|
@@ -100,57 +103,68 @@ module.exports = function (RED) {
|
|
|
100
103
|
case config.GALightSwitch:
|
|
101
104
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch));
|
|
102
105
|
if (msg.payload === true) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
if (node.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
// From HUE Api core concepts:
|
|
107
|
+
// If you try and control multiple conflicting parameters at once e.g. {"color": {"xy": {"x":0.5,"y":0.5}}, "color_temperature": {"mirek": 250}}
|
|
108
|
+
// the lights can only physically do one, for this we apply the rule that xy beats ct. Simple.
|
|
109
|
+
// color_temperature.mirek: color temperature in mirek is null when the light color is not in the ct spectrum
|
|
110
|
+
if (node.DayTime === true && config.specifySwitchOnBrightness === "no" && node.HUEDeviceWhileDaytime !== null) {
|
|
111
|
+
// The DayNight has switched into day, so restore the previous light status
|
|
112
|
+
state = { on: { on: true }, dimming: node.HUEDeviceWhileDaytime.dimming, color: node.HUEDeviceWhileDaytime.color, color_temperature: node.HUEDeviceWhileDaytime.color_temperature };
|
|
113
|
+
if (node.HUEDeviceWhileDaytime.color_temperature.mirek === null) delete state.color_temperature; // Otherwise the lamp will not turn on due to an error. color_temperature.mirek: color temperature in mirek is null when the light color is not in the ct spectrum
|
|
114
|
+
node.HUEDeviceWhileDaytime = null; // Nullize the object.
|
|
115
|
+
} else {
|
|
116
|
+
let colorChoosen;
|
|
117
|
+
let temperatureChoosen;
|
|
118
|
+
let brightnessChoosen;
|
|
119
|
+
// The light must support the temperature (in this case, colorAtSwitchOnNightTime is an object {kelvin:xx, brightness:yy})
|
|
120
|
+
if (node.currentHUEDevice.color_temperature !== undefined) {
|
|
121
|
+
if (node.DayTime === true && config.specifySwitchOnBrightness === "temperature") {
|
|
122
|
+
temperatureChoosen = config.colorAtSwitchOnDayTime.kelvin;
|
|
123
|
+
} else if (node.DayTime === false && config.enableDayNightLighting === "temperature") {
|
|
124
|
+
temperatureChoosen = config.colorAtSwitchOnNightTime.kelvin;
|
|
125
|
+
}
|
|
112
126
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
if (node.currentHUEDevice.dimming !== undefined) {
|
|
128
|
+
// Check wether the user selected specific brightness at switch on (in this case, colorAtSwitchOnNightTime is an object {kelvin:xx, brightness:yy})
|
|
129
|
+
if (node.DayTime === true && config.specifySwitchOnBrightness === "temperature") {
|
|
130
|
+
brightnessChoosen = config.colorAtSwitchOnDayTime.brightness;
|
|
131
|
+
} else if (node.DayTime === false && config.enableDayNightLighting === "temperature") {
|
|
132
|
+
brightnessChoosen = config.colorAtSwitchOnNightTime.brightness;
|
|
133
|
+
}
|
|
120
134
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
if (node.currentHUEDevice.color !== undefined) {
|
|
136
|
+
// Check wether the user selected specific color at switch on (in this case, colorAtSwitchOnDayTime is a text with HTML web color)
|
|
137
|
+
if (node.DayTime === true && config.specifySwitchOnBrightness === "yes") {
|
|
138
|
+
colorChoosen = config.colorAtSwitchOnDayTime;
|
|
139
|
+
} else if (node.DayTime === false && config.enableDayNightLighting === "yes") {
|
|
140
|
+
colorChoosen = config.colorAtSwitchOnNightTime;
|
|
141
|
+
}
|
|
128
142
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
143
|
+
// Create the HUE command
|
|
144
|
+
if (colorChoosen !== undefined) {
|
|
145
|
+
// Now we have a jColorChoosen. Proceed illuminating the light
|
|
146
|
+
let gamut = null;
|
|
147
|
+
if (node.currentHUEDevice.color.gamut_type !== undefined) {
|
|
148
|
+
gamut = node.currentHUEDevice.color.gamut_type;
|
|
149
|
+
}
|
|
150
|
+
const dretXY = hueColorConverter.ColorConverter.rgbToXy(colorChoosen.red, colorChoosen.green, colorChoosen.blue, gamut);
|
|
151
|
+
const dbright = hueColorConverter.ColorConverter.getBrightnessFromRGBOrHex(colorChoosen.red, colorChoosen.green, colorChoosen.blue);
|
|
152
|
+
node.currentHUEDevice.dimming.brightness = Math.round(dbright, 0);
|
|
153
|
+
node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
|
|
154
|
+
state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } };
|
|
155
|
+
} else if (temperatureChoosen !== undefined) {
|
|
156
|
+
// Kelvin
|
|
157
|
+
const mirek = hueColorConverter.ColorConverter.kelvinToMirek(temperatureChoosen);
|
|
158
|
+
node.currentHUEDevice.color_temperature.mirek = mirek;
|
|
159
|
+
node.currentHUEDevice.dimming.brightness = brightnessChoosen;
|
|
160
|
+
node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
|
|
161
|
+
// Kelvin temp
|
|
162
|
+
state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen }, color_temperature: { mirek: mirek } } : { on: { on: false } };
|
|
163
|
+
} else if (brightnessChoosen !== undefined) {
|
|
164
|
+
state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen } } : { on: { on: false } };
|
|
165
|
+
} else {
|
|
166
|
+
state = { on: { on: true } };
|
|
136
167
|
}
|
|
137
|
-
const dretXY = hueColorConverter.ColorConverter.rgbToXy(colorChoosen.red, colorChoosen.green, colorChoosen.blue, gamut);
|
|
138
|
-
const dbright = hueColorConverter.ColorConverter.getBrightnessFromRGBOrHex(colorChoosen.red, colorChoosen.green, colorChoosen.blue);
|
|
139
|
-
node.currentHUEDevice.dimming.brightness = Math.round(dbright, 0);
|
|
140
|
-
node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
|
|
141
|
-
state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } };
|
|
142
|
-
} else if (temperatureChoosen !== undefined) {
|
|
143
|
-
// Kelvin
|
|
144
|
-
const mirek = hueColorConverter.ColorConverter.kelvinToMirek(temperatureChoosen);
|
|
145
|
-
node.currentHUEDevice.color_temperature.mirek = mirek;
|
|
146
|
-
node.currentHUEDevice.dimming.brightness = brightnessChoosen;
|
|
147
|
-
node.updateKNXBrightnessState(node.currentHUEDevice.dimming.brightness);
|
|
148
|
-
// Kelvin temp
|
|
149
|
-
state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen }, color_temperature: { mirek: mirek } } : { on: { on: false } };
|
|
150
|
-
} else if (brightnessChoosen !== undefined) {
|
|
151
|
-
state = brightnessChoosen > 0 ? { on: { on: true }, dimming: { brightness: brightnessChoosen } } : { on: { on: false } };
|
|
152
|
-
} else {
|
|
153
|
-
state = { on: { on: true } };
|
|
154
168
|
}
|
|
155
169
|
} else {
|
|
156
170
|
state = { on: { on: false } };
|
|
@@ -175,11 +189,15 @@ module.exports = function (RED) {
|
|
|
175
189
|
break;
|
|
176
190
|
case config.GALightKelvin:
|
|
177
191
|
let retMirek;
|
|
192
|
+
let kelvinValue = 0;
|
|
178
193
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightKelvin));
|
|
179
194
|
if (config.dptLightKelvin === "7.600") {
|
|
180
195
|
if (msg.payload > 65535) msg.payload = 65535;
|
|
181
196
|
if (msg.payload < 0) msg.payload = 0;
|
|
182
|
-
|
|
197
|
+
// kelvinValue = hueColorConverter.ColorConverter.mirekToKelvin(_value);
|
|
198
|
+
// knxMsgPayload.payload = hueColorConverter.ColorConverter.scale(kelvinValue, [2000, 6535], [0, 65535]);
|
|
199
|
+
kelvinValue = hueColorConverter.ColorConverter.scale(msg.payload, [0, 65535], [2000, 6535]);
|
|
200
|
+
retMirek = hueColorConverter.ColorConverter.kelvinToMirek(kelvinValue);
|
|
183
201
|
} else if (config.dptLightKelvin === "9.002") {
|
|
184
202
|
// Relative temperature in Kelvin. Use HUE scale.
|
|
185
203
|
if (msg.payload > 6535) msg.payload = 6535;
|
|
@@ -192,12 +210,21 @@ module.exports = function (RED) {
|
|
|
192
210
|
fill: "green",
|
|
193
211
|
shape: "dot",
|
|
194
212
|
text: "KNX->HUE",
|
|
195
|
-
payload:
|
|
213
|
+
payload: kelvinValue,
|
|
196
214
|
});
|
|
197
215
|
break;
|
|
198
216
|
case config.GADaylightSensor:
|
|
199
217
|
node.DayTime = Boolean(dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptDaylightSensor)));
|
|
200
218
|
if (config.invertDayNight !== undefined && config.invertDayNight === true) node.DayTime = !node.DayTime;
|
|
219
|
+
if (config.specifySwitchOnBrightness === "no") {
|
|
220
|
+
// This retains the HUE device status while daytime, to be restored after nighttime elapsed. https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/298
|
|
221
|
+
if (node.DayTime === false) {
|
|
222
|
+
// DayTime has switched to false: save the currentHUEDevice into the HUEDeviceWhileDaytime
|
|
223
|
+
node.HUEDeviceWhileDaytime = cloneDeep(node.currentHUEDevice);
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
node.HUEDeviceWhileDaytime = null;
|
|
227
|
+
}
|
|
201
228
|
node.setNodeStatusHue({
|
|
202
229
|
fill: "green",
|
|
203
230
|
shape: "dot",
|
|
@@ -526,7 +553,7 @@ module.exports = function (RED) {
|
|
|
526
553
|
// Output the msg to the flow
|
|
527
554
|
node.send(_event);
|
|
528
555
|
|
|
529
|
-
// // DEBUG
|
|
556
|
+
// // DEBUG testing enable/disable HTML UI Tabs
|
|
530
557
|
//delete _event.dimming;
|
|
531
558
|
//delete _event.color;
|
|
532
559
|
//delete _event.color_temperature;
|
|
@@ -734,12 +761,13 @@ module.exports = function (RED) {
|
|
|
734
761
|
node.updateKNXLightKelvinState = function updateKNXLightKelvinState(_value, _outputtype = "write") {
|
|
735
762
|
if (config.GALightKelvinState !== undefined && config.GALightKelvinState !== "") {
|
|
736
763
|
const knxMsgPayload = {};
|
|
764
|
+
let kelvinValue = 0;
|
|
737
765
|
knxMsgPayload.topic = config.GALightKelvinState;
|
|
738
766
|
knxMsgPayload.dpt = config.dptLightKelvinState;
|
|
739
767
|
if (config.dptLightKelvinState === "7.600") {
|
|
740
|
-
|
|
768
|
+
kelvinValue = hueColorConverter.ColorConverter.mirekToKelvin(_value);
|
|
769
|
+
knxMsgPayload.payload = hueColorConverter.ColorConverter.scale(kelvinValue, [2000, 6535], [0, 65535]);
|
|
741
770
|
} else if (config.dptLightKelvinState === "9.002") {
|
|
742
|
-
//knxMsgPayload.payload = hueColorConverter.ColorConverter.scale(_value, [153, 500], [6535, 2000]);
|
|
743
771
|
knxMsgPayload.payload = hueColorConverter.ColorConverter.mirekToKelvin(_value);
|
|
744
772
|
}
|
|
745
773
|
// Send to KNX bus
|
|
@@ -758,7 +786,7 @@ module.exports = function (RED) {
|
|
|
758
786
|
fill: "blue",
|
|
759
787
|
shape: "ring",
|
|
760
788
|
text: "HUE->KNX Kelvin",
|
|
761
|
-
payload:
|
|
789
|
+
payload: kelvinValue,
|
|
762
790
|
});
|
|
763
791
|
}
|
|
764
792
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
|
|
3
|
+
// Aggiungere questo JSON al package.json
|
|
4
|
+
// "plugins": {
|
|
5
|
+
// "sidebar-plugin": "/nodes/plugins/HomeAssistantImporter-sidebar-plugin.html"
|
|
6
|
+
// }
|
|
7
|
+
(function () {
|
|
8
|
+
RED.plugins.registerPlugin("HomeAssistantImporter-sidebar-plugin", {
|
|
9
|
+
onadd: function () {
|
|
10
|
+
|
|
11
|
+
//#region Create Home Assistant Import TAB on the left tabs.
|
|
12
|
+
// The sidebar content
|
|
13
|
+
const content = $("<div>").css({ "position": "relative", "height": "100%" });
|
|
14
|
+
|
|
15
|
+
// (optional) A toolbar header for the sidebar
|
|
16
|
+
const header = $("<div>", { class: "red-ui-sidebar-header" }).appendTo(content);
|
|
17
|
+
// const textarea = "<textarea rows="20" id="node - config - input - csv" style="width: 100 % "
|
|
18
|
+
// data - i18n="[placeholder]knxUltimate-config.ets.ga_list_help" ></textarea > "
|
|
19
|
+
|
|
20
|
+
RED.actions.add("HAImporterTab:show-custom-tab", function () {
|
|
21
|
+
RED.sidebar.show("HAImporterTab");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (RED.sidebar.containsTab('HAImporterTab')) RED.sidebar.removeTab("HAImporterTab");
|
|
25
|
+
RED.sidebar.addTab({
|
|
26
|
+
id: "HAImporterTab",
|
|
27
|
+
label: "custom",
|
|
28
|
+
name: "Home Assistant importer",
|
|
29
|
+
iconClass: "fa fa-database",
|
|
30
|
+
content: content,
|
|
31
|
+
action: "HAImporterTab:show-custom-tab"
|
|
32
|
+
});
|
|
33
|
+
//#endregion
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
})();
|
|
38
|
+
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Utility function
|
|
2
|
+
// until node-red 3.1.0, there is a bug creating a plugin, so for backward compatibility, i must use a JS as a node.
|
|
3
|
+
const yaml = require('js-yaml');
|
|
4
|
+
module.exports = function (RED) {
|
|
5
|
+
|
|
6
|
+
//RED.log.error("###############################################################")
|
|
7
|
+
RED.httpAdmin.post("/banana", RED.auth.needsPermission("write"), (req, res) => {
|
|
8
|
+
var node = RED.nodes.getNode(req.params.id);
|
|
9
|
+
if (node != null) {
|
|
10
|
+
try {
|
|
11
|
+
if (req.body) {
|
|
12
|
+
console.log(body);
|
|
13
|
+
}
|
|
14
|
+
} catch (err) { }
|
|
15
|
+
}
|
|
16
|
+
res.json(req.body)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.2.
|
|
6
|
+
"version": "2.2.34",
|
|
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",
|
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
"path": "0.12.7",
|
|
18
18
|
"ping": "0.4.4",
|
|
19
19
|
"simple-get": "4.0.1",
|
|
20
|
-
"xml2js": "0.6.0"
|
|
20
|
+
"xml2js": "0.6.0",
|
|
21
|
+
"js-yaml": "4.1.0"
|
|
21
22
|
},
|
|
22
|
-
|
|
23
23
|
"node-red": {
|
|
24
24
|
"version": ">=2.0.0",
|
|
25
25
|
"nodes": {
|
|
26
|
+
"commonFunctions": "/nodes/utils/commonFunctions.js",
|
|
26
27
|
"knxUltimate": "/nodes/knxUltimate.js",
|
|
27
28
|
"knxUltimateSceneController": "/nodes/knxUltimateSceneController.js",
|
|
28
29
|
"knxUltimateWatchDog": "/nodes/knxUltimateWatchDog.js",
|
|
@@ -91,4 +92,4 @@
|
|
|
91
92
|
"editor.defaultFormatter": "vscode.html-language-features"
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
|
-
}
|
|
95
|
+
}
|
|
Binary file
|