node-red-contrib-knx-ultimate 2.2.25 → 2.2.27

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,107 +1,14 @@
1
1
  <!-- <script type="application/javascript;charset=utf-8" src="https://kit.fontawesome.com/11f26b4500.js" crossorigin="anonymous"></script>
2
2
  <script type="application/javascript;charset=utf-8" src="https://cdn.jsdelivr.net/npm/@jaames/iro@5"></script> -->
3
+
4
+ 'use strict'
3
5
  <script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/11f26b4500.js"></script>
4
6
 
5
7
  <script type="text/javascript">
8
+ (function () {
6
9
 
7
- RED.nodes.registerType("knxUltimateHueLight", {
8
- category: "KNX Ultimate",
9
- color: "#C0C7E9",
10
- defaults: {
11
- //buttonState: {value: true},
12
- server: { type: "knxUltimate-config", required: false },
13
- serverHue: { type: "hue-config", required: true },
14
- name: { value: "" },
15
-
16
- nameLightSwitch: { value: "" },
17
- GALightSwitch: { value: "" },
18
- dptLightSwitch: { value: "" },
19
-
20
- nameLightState: { value: "" },
21
- GALightState: { value: "" },
22
- dptLightState: { value: "" },
23
-
24
- nameLightDIM: { value: "" },
25
- GALightDIM: { value: "" },
26
- dptLightDIM: { value: "" },
27
-
28
- nameLightColor: { value: "" },
29
- GALightColor: { value: "" },
30
- dptLightColor: { value: "" },
31
-
32
- nameLightColorState: { value: "" },
33
- GALightColorState: { value: "" },
34
- dptLightColorState: { value: "" },
35
-
36
- nameLightHSV: { value: "" },
37
- GALightHSV: { value: "" },
38
- dptLightHSV: { value: "" },
39
-
40
- nameLightHSVPercentage: { value: "" },
41
- GALightHSVPercentage: { value: "" },
42
- dptLightHSVPercentage: { value: "" },
43
-
44
- nameLightHSVState: { value: "" },
45
- GALightHSVState: { value: "" },
46
- dptLightHSVState: { value: "" },
47
-
48
- nameLightBrightness: { value: "" },
49
- GALightBrightness: { value: "" },
50
- dptLightBrightness: { value: "" },
51
-
52
- nameLightBrightnessState: { value: "" },
53
- GALightBrightnessState: { value: "" },
54
- dptLightBrightnessState: { value: "" },
55
-
56
- nameLightBlink: { value: "" },
57
- GALightBlink: { value: "" },
58
- dptLightBlink: { value: "" },
59
-
60
- nameLightColorCycle: { value: "" },
61
- GALightColorCycle: { value: "" },
62
- dptLightColorCycle: { value: "" },
63
-
64
- nameDaylightSensor: { value: "" },
65
- GADaylightSensor: { value: "" },
66
- dptDaylightSensor: { value: "" },
67
-
68
- nameLightKelvin: { value: "" },
69
- GALightKelvin: { value: "" },
70
- dptLightKelvin: { value: "" },
71
-
72
- nameLightKelvinState: { value: "" },
73
- GALightKelvinState: { value: "" },
74
- dptLightKelvinState: { value: "" },
75
-
76
- specifySwitchOnBrightness: { value: "temperature" },
77
- colorAtSwitchOnDayTime: { value: '{"kelvin":3000, "brightness":100 }' },
78
-
79
- enableDayNightLighting: { value: "no" },
80
- colorAtSwitchOnNightTime: { value: '{ "kelvin":2700, "brightness":20 }' },
81
-
82
- invertDayNight: { value: false },
83
-
84
- updateKNXBrightnessStatusOnHUEOnOff: { value: "no" },
85
- dimSpeed: { value: 5000, required: false },
86
- minDimLevelLight: { value: 10, required: false },
87
- maxDimLevelLight: { value: 100, required: false },
88
- readStatusAtStartup: { value: "yes" },
89
- enableNodePINS: { value: "no" },
90
-
91
- outputs: { value: 0 },
92
- inputs: { value: 0 },
93
-
94
- hueDevice: { value: "" },
95
- },
96
- inputs: 0,
97
- outputs: 0,
98
- icon: "node-hue-icon.svg",
99
- label: function () {
100
- return this.name;
101
- },
102
- paletteLabel: "Hue Light",
103
- oneditprepare: function () {
104
- var node = this;
10
+ function onEditPrepare(node) {
11
+ // var node = node;
105
12
  var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
106
13
  var oNodeServerHue = RED.nodes.node($("#node-input-serverHue").val()); // Store the config-node
107
14
 
@@ -126,24 +33,26 @@
126
33
  }
127
34
  // ################################################################
128
35
 
36
+
129
37
  $("#tabs").tabs(); // Tabs gestione KNX
130
38
 
39
+
131
40
  // 19/02/2020 Used to get the server sooner als deploy.
132
41
  $("#node-input-server").change(function () {
133
42
  try {
134
- oNodeServer = RED.nodes.node($(this).val());
43
+ oNodeServer = RED.nodes.node($(node).val());
135
44
  } catch (error) { }
136
45
  });
137
46
  // 19/02/2020 Used to get the server sooner als deploy.
138
47
  $("#node-input-serverHue").change(function () {
139
48
  try {
140
- oNodeServerHue = RED.nodes.node($(this).val());
49
+ oNodeServerHue = RED.nodes.node($(node).val());
141
50
  } catch (error) { }
142
51
  });
143
52
 
144
53
  // 31/03/2020 Search Helper
145
54
  function fullSearch(sourceText, searchString) {
146
- // This searches for all words in a string
55
+ // node searches for all words in a string
147
56
  var aSearchWords = searchString.toLowerCase().split(" ");
148
57
  var i = 0;
149
58
  for (let index = 0; index < aSearchWords.length; index++) {
@@ -155,6 +64,7 @@
155
64
  function getDPT(_dpt, _destinationWidget) {
156
65
  // DPT Switch command
157
66
  // ########################
67
+ $(_destinationWidget).empty();
158
68
  $.getJSON("knxUltimateDpts", (data) => {
159
69
  data.forEach((dpt) => {
160
70
  if (dpt.value.startsWith(_dpt)) {
@@ -264,11 +174,138 @@
264
174
  getGroupAddress("#node-input-GALightKelvinState", "#node-input-nameLightKelvinState", "#node-input-dptLightKelvinState", " 9.002");
265
175
 
266
176
 
177
+ // Get the HUE capabilities to enable/disable UI parts
178
+ $.getJSON("knxUltimateGetLightObject?id=" + $("#node-input-hueDevice").val().split("#")[0], (data) => {
179
+ let oLight = data;
180
+ // Check if grouped, to hide/show the "Get current" buttons
181
+ if (oLight.type === "grouped_light") {
182
+ $("#tabs").tabs("enable", "#tabs-4");
183
+ $("#tabs").tabs("enable", "#tabs-3");
184
+ $("#tabs").tabs("enable", "#tabs-2");
185
+ $("#getColorAtSwitchOnDayTimeButton").show();
186
+ $("#getColorAtSwitchOnNightTimeButton").show();
187
+ $("#node-input-specifySwitchOnBrightness").empty().append(
188
+ $("<option>")
189
+ .val("no")
190
+ .text("Last status")
191
+ ).append(
192
+ $("<option>")
193
+ .val("yes")
194
+ .text("Select color")
195
+ ).append(
196
+ $("<option>")
197
+ .val("temperature")
198
+ .text("Select temperature and brightness")
199
+ );
200
+ $("#node-input-enableDayNightLighting").empty().append(
201
+ $("<option>")
202
+ .val("no")
203
+ .text("No")
204
+ ).append(
205
+ $("<option>")
206
+ .val("yes")
207
+ .text("Select color")
208
+ ).append(
209
+ $("<option>")
210
+ .val("temperature")
211
+ .text("Select temperature and brightness")
212
+ );
213
+ $("#node-input-specifySwitchOnBrightness").val(node.specifySwitchOnBrightness).trigger('change');
214
+ $("#node-input-enableDayNightLighting").val(node.enableDayNightLighting).trigger('change');
215
+ return;
216
+ } else {
217
+
218
+ $("#getColorAtSwitchOnDayTimeButton").show();
219
+ $("#getColorAtSwitchOnNightTimeButton").show();
220
+ $("#node-input-specifySwitchOnBrightness").empty().append(
221
+ $("<option>")
222
+ .val("no")
223
+ .text("Last status")
224
+ );
225
+ $("#node-input-enableDayNightLighting").empty().append(
226
+ $("<option>")
227
+ .val("no")
228
+ .text("No")
229
+ );
230
+ }
231
+ $("#tabs").tabs("disable", "#tabs-4");
232
+ $("#tabs").tabs("disable", "#tabs-3");
233
+ $("#tabs").tabs("disable", "#tabs-2");
234
+ $("#divColorsAtSwitchOn").hide();
235
+ $("#divColorsAtSwitchOnNightTime").hide();
236
+ $("#divTemperatureAtSwitchOn").hide();
237
+ $("#divTemperatureAtSwitchOnNightTime").hide();
238
+ $("#divColorCycle").hide();
239
+ $("#divUpdateKNXBrightnessStatusOnHUEOnOff").hide();
240
+ $("#divMinMaxBrightness").hide();
241
+ $("#comboTemperatureAtSwitchOn").hide();
242
+ $("#comboTemperatureAtSwitchOnNightTime").hide();
243
+
244
+ // Enable options/tabs one by one
245
+ if (oLight.color !== undefined) {
246
+ $("#tabs").tabs("enable", "#tabs-4");
247
+ $("#divColorsAtSwitchOn").show();
248
+ $("#divColorsAtSwitchOnNightTime").show();
249
+ $("#divColorCycle").show();
250
+ $("#node-input-specifySwitchOnBrightness").append(
251
+ $("<option>")
252
+ .val("yes")
253
+ .text("Select color")
254
+ );
255
+ $("#node-input-enableDayNightLighting").append(
256
+ $("<option>")
257
+ .val("yes")
258
+ .text("Select color")
259
+ );
260
+ }
261
+ // Check temperature (if the light supports temperature, it support dimming as well)
262
+ if (oLight.color_temperature !== undefined) {
263
+ $("#tabs").tabs("enable", "#tabs-3");
264
+ $("#tabs").tabs("enable", "#tabs-2");
265
+ $("#node-input-specifySwitchOnBrightness").append(
266
+ $("<option>")
267
+ .val("temperature")
268
+ .text("Select temperature and brightness")
269
+ );
270
+ $("#node-input-enableDayNightLighting").append(
271
+ $("<option>")
272
+ .val("temperature")
273
+ .text("Select temperature and brightness")
274
+ );
275
+ $("#divTemperatureAtSwitchOn").show();
276
+ $("#divTemperatureAtSwitchOnNightTime").show();
277
+ $("#divUpdateKNXBrightnessStatusOnHUEOnOff").show();
278
+ $("#divMinMaxBrightness").show();
279
+ $("#comboTemperatureAtSwitchOn").show();
280
+ $("#comboTemperatureAtSwitchOnNightTime").show();
281
+ } else {
282
+ $("#tabs").tabs("enable", "#tabs-2");
283
+ $("#node-input-specifySwitchOnBrightness").append(
284
+ $("<option>")
285
+ .val("temperature")
286
+ .text("Select brightness")
287
+ );
288
+ $("#node-input-enableDayNightLighting").append(
289
+ $("<option>")
290
+ .val("temperature")
291
+ .text("Select brightness")
292
+ );
293
+ $("#comboTemperatureAtSwitchOn").val(0);
294
+ $("#comboTemperatureAtSwitchOnNightTime").val(0);
295
+ $("#divTemperatureAtSwitchOn").show();
296
+ $("#divTemperatureAtSwitchOnNightTime").show();
297
+ $("#divUpdateKNXBrightnessStatusOnHUEOnOff").show();
298
+ $("#divMinMaxBrightness").show();
299
+ }
300
+ $("#node-input-specifySwitchOnBrightness").val(node.specifySwitchOnBrightness).trigger('change');
301
+ $("#node-input-enableDayNightLighting").val(node.enableDayNightLighting).trigger('change');
302
+ });
303
+
267
304
  // Show/Hide the div of the color at swich on
268
- if (this.specifySwitchOnBrightness === "yes") {
305
+ if (node.specifySwitchOnBrightness === "yes") {
269
306
  $("#divColorsAtSwitchOn").show();
270
307
  $("#divTemperatureAtSwitchOn").hide();
271
- } else if (this.specifySwitchOnBrightness === "temperature") {
308
+ } else if (node.specifySwitchOnBrightness === "temperature") {
272
309
  $("#divColorsAtSwitchOn").hide();
273
310
  $("#divTemperatureAtSwitchOn").show();
274
311
  } else {
@@ -291,12 +328,12 @@
291
328
  });
292
329
 
293
330
  // Show/Hide and enable/disable day/night Lighting behaviour
294
- if (this.enableDayNightLighting === "yes") {
331
+ if (node.enableDayNightLighting === "yes") {
295
332
  $("#divEnableDayNightLighting").show();
296
333
  $("#divCCSBoxAtNightLighting").css({ border: "1px solid dimgrey", "border-radius": "12px", padding: "5px" }); // Add little box to better understand the property page
297
334
  $("#divColorsAtSwitchOnNightTime").show();
298
335
  $("#divTemperatureAtSwitchOnNightTime").hide();
299
- } else if (this.enableDayNightLighting === "temperature") {
336
+ } else if (node.enableDayNightLighting === "temperature") {
300
337
  $("#divEnableDayNightLighting").show();
301
338
  $("#divCCSBoxAtNightLighting").css({ border: "1px solid dimgrey", "border-radius": "12px", padding: "5px" }); // Add little box to better understand the property page
302
339
  $("#divColorsAtSwitchOnNightTime").hide();
@@ -313,7 +350,7 @@
313
350
  $("#divColorsAtSwitchOnNightTime").show();
314
351
  $("#divTemperatureAtSwitchOnNightTime").hide();
315
352
  blinkBackground("#colorPickerNight")
316
- $("#getColorAtSwitchOnDayTimeButton").text("Get again");
353
+ $("#getColorAtSwitchOnDayTimeButton").text("Get current");
317
354
  } else if ($("#node-input-enableDayNightLighting").val() === "temperature") {
318
355
  $("#divEnableDayNightLighting").show();
319
356
  $("#divCCSBoxAtNightLighting").css({ border: "1px solid dimgrey", "border-radius": "12px", padding: "5px" }); // Add little box to better understand the property page
@@ -325,81 +362,6 @@
325
362
  }
326
363
  });
327
364
 
328
-
329
-
330
- // Autocomplete suggestion with HUE Lights
331
- $("#node-input-name").autocomplete({
332
- minLength: 1,
333
- source: function (request, response) {
334
- $.getJSON("KNXUltimateGetResourcesHUE?rtype=light&nodeID=" + oNodeServerHue.id, (data) => {
335
- response(
336
- $.map(data.devices, function (value, key) {
337
- //alert(JSON.stringify(value) + " "+ key)
338
- var sSearch = value.name;
339
- if (!value.name.includes("I'm still connecting")) {
340
- if (fullSearch(sSearch, request.term)) {
341
- return {
342
- hueDevice: value.id,
343
- value: value.name,
344
- };
345
- } else {
346
- return null;
347
- }
348
- } else {
349
- return {
350
- hueDevice: value.id,
351
- value: value.name,
352
- };
353
- }
354
- })
355
- );
356
- });
357
- },
358
- select: function (event, ui) {
359
- // Distinguish between group of lights an single light.
360
- if (ui.item.value.toLowerCase().startsWith("grouped_light")) {
361
- $("#node-input-hueDevice").val(ui.item.hueDevice + "#grouped_light");
362
- $("#getColorAtSwitchOnDayTimeButton").hide();
363
- $("#getColorAtSwitchOnNightTimeButton").hide();
364
- } else {
365
- $("#node-input-hueDevice").val(ui.item.hueDevice + "#light");
366
- $("#getColorAtSwitchOnDayTimeButton").show();
367
- $("#getColorAtSwitchOnNightTimeButton").show();
368
- }
369
- $("#tabs").show();
370
- },
371
- });
372
-
373
- // Get the HUE capabilities to enable/disable UI parts
374
- $.getJSON("KNXUltimateGetResourcesHUE?rtype=light&nodeID=" + oNodeServerHue.id, (data) => {
375
- data.devices.forEach((element) => {
376
- if (element.id === this.hueDevice.split("#")[0] && element.deviceObject !== undefined) {
377
- // Check dimming
378
- if (element.deviceObject.dimming === undefined) {
379
- $("#tabs").tabs("disable", "#tabs-2");
380
- $("#divColorsAtSwitchOn").hide();
381
- $("#divColorCycle").hide();
382
- }
383
- // Check color
384
- if (element.deviceObject.color_temperature === undefined) $("#tabs").tabs("disable", "#tabs-3");
385
- if (element.deviceObject.color === undefined) {
386
- $("#tabs").tabs("disable", "#tabs-4");
387
- $("#divColorsAtSwitchOn").hide();
388
- $("#divColorCycle").hide();
389
- }
390
- // Check if grouped, to hide/show the "Get current" buttons
391
- if (element.deviceObject.type === "grouped_light") {
392
- $("#getColorAtSwitchOnDayTimeButton").hide();
393
- $("#getColorAtSwitchOnNightTimeButton").hide();
394
- } else {
395
- $("#getColorAtSwitchOnDayTimeButton").show();
396
- $("#getColorAtSwitchOnNightTimeButton").show();
397
- }
398
- return;
399
- }
400
- });
401
- });
402
-
403
365
  $("#getColorAtSwitchOnDayTimeButton").on("click", function () {
404
366
  $("#getColorAtSwitchOnDayTimeButton").text("Wait...");
405
367
  let jRet;
@@ -429,7 +391,7 @@
429
391
  });
430
392
 
431
393
  // Fill options for minDimLevel and maxDimLevel and comboBrightnessAtSwitchOn (for color brightness at switch on, with temperature toghedher)
432
- for (let index = 0; index <= 100; index += 5) {
394
+ for (let index = 100; index >= 0; index -= 5) {
433
395
  if (index === 0) {
434
396
  $("#node-input-minDimLevelLight").append($("<option>").val(index).text(index.toString() + "% (Switch Off)"));
435
397
  $("#comboBrightnessAtSwitchOn").append($("<option>").val(index).text(index.toString() + "% (Switch Off)"));
@@ -472,16 +434,18 @@
472
434
 
473
435
  // Calculate kelvin/color
474
436
  let json;
475
- this.colorAtSwitchOnDayTime = this.colorAtSwitchOnDayTime.replace("geen", "green"); // Old bug in "geen" property
476
- this.colorAtSwitchOnNightTime = this.colorAtSwitchOnNightTime.replace("geen", "green"); // Old bug in "geen" property
437
+ node.colorAtSwitchOnDayTime = node.colorAtSwitchOnDayTime.replace("geen", "green"); // Old bug in "geen" property
438
+ node.colorAtSwitchOnNightTime = node.colorAtSwitchOnNightTime.replace("geen", "green"); // Old bug in "geen" property
477
439
  try {
478
- json = JSON.parse(this.colorAtSwitchOnDayTime);
479
- } catch (error) { }
440
+ json = JSON.parse(node.colorAtSwitchOnDayTime);
441
+ } catch (error) {
442
+ console.log("json = JSON.parse(node.colorAtSwitchOnDayTime) in HTML: " + error.message)
443
+ }
480
444
  if (json !== undefined && json.kelvin !== undefined) {
481
445
  // Kelvin
482
446
  $("#comboTemperatureAtSwitchOn").val(json.kelvin);
483
447
  $("#comboBrightnessAtSwitchOn").val(json.brightness);
484
- if (this.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('temperature'); // Adjust in case of mismatch (from old geen bug)
448
+ if (node.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('temperature'); // Adjust in case of mismatch (from old geen bug)
485
449
  } else if (json !== undefined && json.red !== undefined) {
486
450
  // Must transform RGB into HTML HEX color
487
451
  try {
@@ -489,22 +453,22 @@
489
453
  } catch (error) {
490
454
  }
491
455
  $("#colorPickerDay").val($("#node-input-colorAtSwitchOnDayTime").val());
492
- if (this.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('yes'); // Adjust in case of mismatch (from old geen bug)
456
+ if (node.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('yes'); // Adjust in case of mismatch (from old geen bug)
493
457
  } else {
494
458
  // It's already an HEX color
495
- $("#colorPickerDay").val(this.colorAtSwitchOnDayTime);
496
- if (this.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('yes'); // Adjust in case of mismatch (from old geen bug)
459
+ $("#colorPickerDay").val(node.colorAtSwitchOnDayTime);
460
+ if (node.specifySwitchOnBrightness !== 'no') $("#node-input-specifySwitchOnBrightness").val('yes'); // Adjust in case of mismatch (from old geen bug)
497
461
  }
498
462
  //Night
499
463
  json = undefined;
500
464
  try {
501
- json = JSON.parse(this.colorAtSwitchOnNightTime);
465
+ json = JSON.parse(node.colorAtSwitchOnNightTime);
502
466
  } catch (error) { }
503
467
  if (json !== undefined && json.kelvin !== undefined) {
504
468
  // Kelvin
505
469
  $("#comboTemperatureAtSwitchOnNightTime").val(json.kelvin);
506
470
  $("#comboBrightnessAtSwitchOnNightTime").val(json.brightness);
507
- if (this.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('temperature'); // Adjust in case of mismatch (from old geen bug)
471
+ if (node.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('temperature'); // Adjust in case of mismatch (from old geen bug)
508
472
  } else if (json !== undefined && json.red !== undefined) {
509
473
  // Must transform RGB into HTML HEX color
510
474
  try {
@@ -512,11 +476,11 @@
512
476
  } catch (error) {
513
477
  }
514
478
  $("#colorPickerNight").val($("#node-input-colorAtSwitchOnNightTime").val());
515
- if (this.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('yes'); // Adjust in case of mismatch (from old geen bug)
479
+ if (node.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('yes'); // Adjust in case of mismatch (from old geen bug)
516
480
  } else {
517
481
  // It's already an HEX color
518
- $("#colorPickerNight").val(this.colorAtSwitchOnNightTime);
519
- if (this.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('yes'); // Adjust in case of mismatch (from old geen bug)
482
+ $("#colorPickerNight").val(node.colorAtSwitchOnNightTime);
483
+ if (node.enableDayNightLighting !== 'no') $("#node-input-enableDayNightLighting").val('yes'); // Adjust in case of mismatch (from old geen bug)
520
484
  }
521
485
 
522
486
 
@@ -536,7 +500,7 @@
536
500
  });
537
501
 
538
502
 
539
- $("#node-input-minDimLevelLight").val(this.minDimLevelLight);
503
+ $("#node-input-minDimLevelLight").val(node.minDimLevelLight);
540
504
  for (let index = 100; index >= 10; index--) {
541
505
  $("#node-input-maxDimLevelLight").append(
542
506
  $("<option>")
@@ -544,103 +508,248 @@
544
508
  .text(index.toString() + "%")
545
509
  );
546
510
  }
547
- $("#node-input-maxDimLevelLight").val(this.maxDimLevelLight);
511
+ $("#node-input-maxDimLevelLight").val(node.maxDimLevelLight);
548
512
 
549
- if (this.hueDevice !== "") $("#tabs").show(); // Light options
513
+ if (node.hueDevice !== "") $("#tabs").show(); // Light options
550
514
 
551
- },
552
- oneditsave: function () {
553
- //RED.sidebar.removeTab("tabNRColor");
554
- //RED.sidebar.show("help");
555
- if ($("#node-input-enableNodePINS").val() === "yes") {
556
- this.outputs = 1;
557
- this.inputs = 1;
558
- } else {
559
- this.outputs = 0;
560
- this.inputs = 0;
561
- }
562
- },
563
- oneditcancel: function () {
564
- //RED.sidebar.removeTab("tabNRColor");
565
- //RED.sidebar.show("help");
515
+
516
+
517
+ // Autocomplete suggestion with HUE Lights
518
+ $("#node-input-name").autocomplete({
519
+ minLength: 1,
520
+ source: function (request, response) {
521
+ $.getJSON("KNXUltimateGetResourcesHUE?rtype=light&nodeID=" + oNodeServerHue.id, (data) => {
522
+ response(
523
+ $.map(data.devices, function (value, key) {
524
+ //alert(JSON.stringify(value) + " "+ key)
525
+ var sSearch = value.name;
526
+ if (!value.name.includes("I'm still connecting")) {
527
+ if (fullSearch(sSearch, request.term)) {
528
+ return {
529
+ hueDevice: value.id,
530
+ value: value.name,
531
+ };
532
+ } else {
533
+ return null;
534
+ }
535
+ } else {
536
+ return {
537
+ hueDevice: value.id,
538
+ value: value.name,
539
+ };
540
+ }
541
+ })
542
+ );
543
+ });
544
+ },
545
+ select: function (event, ui) {
546
+ // Distinguish between group of lights an single light.
547
+ if (ui.item.value.toLowerCase().startsWith("grouped_light")) {
548
+ $("#node-input-hueDevice").val(ui.item.hueDevice + "#grouped_light");
549
+ } else {
550
+ $("#node-input-hueDevice").val(ui.item.hueDevice + "#light");
551
+ }
552
+ onEditPrepare(node);
553
+ $("#tabs").show();
554
+ },
555
+ });
566
556
  }
567
- });
568
-
569
- function rgbHex(red, green, blue, alpha) {
570
- const toHex = (red, green, blue, alpha) => ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1) + alpha;
571
- const parseCssRgbString = (input) => {
572
- const parts = input.replace(/rgba?\(([^)]+)\)/, '$1').split(/[,\s/]+/).filter(Boolean);
573
- if (parts.length < 3) {
574
- return;
557
+
558
+ RED.nodes.registerType("knxUltimateHueLight", {
559
+ category: "KNX Ultimate",
560
+ color: "#C0C7E9",
561
+ defaults: {
562
+ //buttonState: {value: true},
563
+ server: { type: "knxUltimate-config", required: false },
564
+ serverHue: { type: "hue-config", required: true },
565
+ name: { value: "" },
566
+
567
+ nameLightSwitch: { value: "" },
568
+ GALightSwitch: { value: "" },
569
+ dptLightSwitch: { value: "" },
570
+
571
+ nameLightState: { value: "" },
572
+ GALightState: { value: "" },
573
+ dptLightState: { value: "" },
574
+
575
+ nameLightDIM: { value: "" },
576
+ GALightDIM: { value: "" },
577
+ dptLightDIM: { value: "" },
578
+
579
+ nameLightColor: { value: "" },
580
+ GALightColor: { value: "" },
581
+ dptLightColor: { value: "" },
582
+
583
+ nameLightColorState: { value: "" },
584
+ GALightColorState: { value: "" },
585
+ dptLightColorState: { value: "" },
586
+
587
+ nameLightHSV: { value: "" },
588
+ GALightHSV: { value: "" },
589
+ dptLightHSV: { value: "" },
590
+
591
+ nameLightHSVPercentage: { value: "" },
592
+ GALightHSVPercentage: { value: "" },
593
+ dptLightHSVPercentage: { value: "" },
594
+
595
+ nameLightHSVState: { value: "" },
596
+ GALightHSVState: { value: "" },
597
+ dptLightHSVState: { value: "" },
598
+
599
+ nameLightBrightness: { value: "" },
600
+ GALightBrightness: { value: "" },
601
+ dptLightBrightness: { value: "" },
602
+
603
+ nameLightBrightnessState: { value: "" },
604
+ GALightBrightnessState: { value: "" },
605
+ dptLightBrightnessState: { value: "" },
606
+
607
+ nameLightBlink: { value: "" },
608
+ GALightBlink: { value: "" },
609
+ dptLightBlink: { value: "" },
610
+
611
+ nameLightColorCycle: { value: "" },
612
+ GALightColorCycle: { value: "" },
613
+ dptLightColorCycle: { value: "" },
614
+
615
+ nameDaylightSensor: { value: "" },
616
+ GADaylightSensor: { value: "" },
617
+ dptDaylightSensor: { value: "" },
618
+
619
+ nameLightKelvin: { value: "" },
620
+ GALightKelvin: { value: "" },
621
+ dptLightKelvin: { value: "" },
622
+
623
+ nameLightKelvinState: { value: "" },
624
+ GALightKelvinState: { value: "" },
625
+ dptLightKelvinState: { value: "" },
626
+
627
+ specifySwitchOnBrightness: { value: "temperature" },
628
+ colorAtSwitchOnDayTime: { value: '{"kelvin":3000, "brightness":100 }' },
629
+
630
+ enableDayNightLighting: { value: "no" },
631
+ colorAtSwitchOnNightTime: { value: '{ "kelvin":2700, "brightness":20 }' },
632
+
633
+ invertDayNight: { value: false },
634
+
635
+ updateKNXBrightnessStatusOnHUEOnOff: { value: "no" },
636
+ dimSpeed: { value: 5000, required: false },
637
+ minDimLevelLight: { value: 10, required: false },
638
+ maxDimLevelLight: { value: 100, required: false },
639
+ readStatusAtStartup: { value: "yes" },
640
+ enableNodePINS: { value: "no" },
641
+
642
+ outputs: { value: 0 },
643
+ inputs: { value: 0 },
644
+
645
+ hueDevice: { value: "" },
646
+ hueDeviceObject: { value: {} },
647
+ },
648
+ inputs: 0,
649
+ outputs: 0,
650
+ icon: "node-hue-icon.svg",
651
+ label: function () {
652
+ return this.name;
653
+ },
654
+ paletteLabel: "Hue Light (beta)",
655
+ oneditprepare: function () {
656
+ onEditPrepare(this);
657
+ },
658
+ oneditsave: function () {
659
+ //RED.sidebar.removeTab("tabNRColor");
660
+ //RED.sidebar.show("help");
661
+ if ($("#node-input-enableNodePINS").val() === "yes") {
662
+ this.outputs = 1;
663
+ this.inputs = 1;
664
+ } else {
665
+ this.outputs = 0;
666
+ this.inputs = 0;
667
+ }
668
+ },
669
+ oneditcancel: function () {
670
+ //RED.sidebar.removeTab("tabNRColor");
671
+ //RED.sidebar.show("help");
575
672
  }
673
+ });
674
+
675
+
576
676
 
577
- const parseValue = (value, max) => {
578
- value = value.trim();
579
677
 
580
- if (value.endsWith('%')) {
581
- return Math.min(Number.parseFloat(value) * max / 100, max);
678
+ function rgbHex(red, green, blue, alpha) {
679
+ const toHex = (red, green, blue, alpha) => ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1) + alpha;
680
+ const parseCssRgbString = (input) => {
681
+ const parts = input.replace(/rgba?\(([^)]+)\)/, '$1').split(/[,\s/]+/).filter(Boolean);
682
+ if (parts.length < 3) {
683
+ return;
582
684
  }
583
685
 
584
- return Math.min(Number.parseFloat(value), max);
585
- };
686
+ const parseValue = (value, max) => {
687
+ value = value.trim();
586
688
 
587
- const red = parseValue(parts[0], 255);
588
- const green = parseValue(parts[1], 255);
589
- const blue = parseValue(parts[2], 255);
590
- let alpha;
689
+ if (value.endsWith('%')) {
690
+ return Math.min(Number.parseFloat(value) * max / 100, max);
691
+ }
591
692
 
592
- if (parts.length === 4) {
593
- alpha = parseValue(parts[3], 1);
594
- }
693
+ return Math.min(Number.parseFloat(value), max);
694
+ };
595
695
 
596
- return [red, green, blue, alpha];
597
- };
696
+ const red = parseValue(parts[0], 255);
697
+ const green = parseValue(parts[1], 255);
698
+ const blue = parseValue(parts[2], 255);
699
+ let alpha;
598
700
 
599
- let isPercent = (red + (alpha || '')).toString().includes('%');
701
+ if (parts.length === 4) {
702
+ alpha = parseValue(parts[3], 1);
703
+ }
600
704
 
601
- if (typeof red === 'string' && !green) { // Single string parameter.
602
- const parsed = parseCssRgbString(red);
603
- if (!parsed) {
604
- throw new TypeError('Invalid or unsupported color format.');
705
+ return [red, green, blue, alpha];
706
+ };
707
+
708
+ let isPercent = (red + (alpha || '')).toString().includes('%');
709
+
710
+ if (typeof red === 'string' && !green) { // Single string parameter.
711
+ const parsed = parseCssRgbString(red);
712
+ if (!parsed) {
713
+ throw new TypeError('Invalid or unsupported color format.');
714
+ }
715
+
716
+ isPercent = false;
717
+ [red, green, blue, alpha] = parsed;
718
+ } else if (alpha !== undefined) {
719
+ alpha = Number.parseFloat(alpha);
605
720
  }
606
721
 
607
- isPercent = false;
608
- [red, green, blue, alpha] = parsed;
609
- } else if (alpha !== undefined) {
610
- alpha = Number.parseFloat(alpha);
611
- }
722
+ if (typeof red !== 'number'
723
+ || typeof green !== 'number'
724
+ || typeof blue !== 'number'
725
+ || red > 255
726
+ || green > 255
727
+ || blue > 255
728
+ ) {
729
+ throw new TypeError('Expected three numbers below 256');
730
+ }
612
731
 
613
- if (typeof red !== 'number'
614
- || typeof green !== 'number'
615
- || typeof blue !== 'number'
616
- || red > 255
617
- || green > 255
618
- || blue > 255
619
- ) {
620
- throw new TypeError('Expected three numbers below 256');
621
- }
732
+ if (typeof alpha === 'number') {
733
+ if (!isPercent && alpha >= 0 && alpha <= 1) {
734
+ alpha = Math.round(255 * alpha);
735
+ } else if (isPercent && alpha >= 0 && alpha <= 100) {
736
+ alpha = Math.round(255 * alpha / 100);
737
+ } else {
738
+ throw new TypeError(`Expected alpha value (${alpha}) as a fraction or percentage`);
739
+ }
622
740
 
623
- if (typeof alpha === 'number') {
624
- if (!isPercent && alpha >= 0 && alpha <= 1) {
625
- alpha = Math.round(255 * alpha);
626
- } else if (isPercent && alpha >= 0 && alpha <= 100) {
627
- alpha = Math.round(255 * alpha / 100);
741
+ alpha = (alpha | 1 << 8).toString(16).slice(1); // eslint-disable-line no-mixed-operators
628
742
  } else {
629
- throw new TypeError(`Expected alpha value (${alpha}) as a fraction or percentage`);
743
+ alpha = '';
630
744
  }
631
745
 
632
- alpha = (alpha | 1 << 8).toString(16).slice(1); // eslint-disable-line no-mixed-operators
633
- } else {
634
- alpha = '';
746
+ return toHex(red, green, blue, alpha);
635
747
  }
636
748
 
637
- return toHex(red, green, blue, alpha);
638
- }
639
-
749
+ }())
640
750
 
641
751
  </script>
642
752
 
643
-
644
753
  <script type="text/html" data-template-name="knxUltimateHueLight">
645
754
 
646
755
  <div class="form-row">
@@ -937,7 +1046,7 @@
937
1046
  <option value="yes">Yes, and emit KNX telegrams.</option>
938
1047
  </select>
939
1048
  </div>
940
- <div class="form-row">
1049
+ <div class="form-row" id="divUpdateKNXBrightnessStatusOnHUEOnOff">
941
1050
  <label style="width:260px;" for="node-input-updateKNXBrightnessStatusOnHUEOnOff">
942
1051
  <i class="fa fa-tag"></i> KNX Brightness Status
943
1052
  </label>
@@ -951,9 +1060,9 @@
951
1060
  <i class="fa fa-tag"></i> Switch on behaviour
952
1061
  </label>
953
1062
  <select id="node-input-specifySwitchOnBrightness">
954
- <option value="temperature">Select temperature and brightness</option>
955
- <option value="yes">Select color</option>
956
1063
  <option value="no">Last status</option>
1064
+ <!-- <option value="temperature">Select temperature and brightness</option>
1065
+ <option value="yes">Select color</option> -->
957
1066
  </select>
958
1067
  </div>
959
1068
 
@@ -967,8 +1076,8 @@
967
1076
  <div class="form-row" id="divTemperatureAtSwitchOn" hidden>
968
1077
  <label for="node-input-colorAtSwitchOnDayTime" style="width:260px">
969
1078
  </label>
970
- <select style="width:180px;" id="comboTemperatureAtSwitchOn"></select>
971
- <select style="width:180px;" id="comboBrightnessAtSwitchOn"></select>
1079
+ <select style="width:12%;" id="comboTemperatureAtSwitchOn"></select>
1080
+ <select style="width:25%;" id="comboBrightnessAtSwitchOn"></select>
972
1081
  </div>
973
1082
 
974
1083
  <div id="divCCSBoxAtNightLighting">
@@ -977,9 +1086,9 @@
977
1086
  <i class="fa fa-clone"></i> Night Lighting
978
1087
  </label>
979
1088
  <select id="node-input-enableDayNightLighting">
980
- <option value="temperature">Select temperature and brightness</option>
981
- <option value="yes">Select color</option>
982
1089
  <option value="no">No night lighting</option>
1090
+ <!-- <option value="temperature">Select temperature and brightness</option>
1091
+ <option value="yes">Select color</option> -->
983
1092
  </select>
984
1093
  </div>
985
1094
 
@@ -1027,19 +1136,21 @@
1027
1136
  </label>
1028
1137
  <input type="text" id="node-input-dimSpeed" placeholder='Default is 5000' style="width:260px">
1029
1138
  </div>
1030
- <div class="form-row">
1031
- <label for="node-input-minDimLevelLight" style="width:260px;">
1032
- <i class="fa fa-clone"></i> Min Dim Brightness
1033
- </label>
1034
- <select id="node-input-minDimLevelLight">
1035
- <option value="useHueLightLevel">Use minimum brightness specified in the HUE light</option>
1036
- </select>
1037
- </div>
1038
- <div class="form-row">
1039
- <label for="node-input-maxDimLevelLight" style="width:260px;">
1040
- <i class="fa fa-clone"></i> Max Dim Brightness
1041
- </label>
1042
- <select id="node-input-maxDimLevelLight"></select>
1139
+ <div id ="divMinMaxBrightness">
1140
+ <div class="form-row">
1141
+ <label for="node-input-minDimLevelLight" style="width:260px;">
1142
+ <i class="fa fa-clone"></i> Min Dim Brightness
1143
+ </label>
1144
+ <select id="node-input-minDimLevelLight">
1145
+ <option value="useHueLightLevel">Use minimum brightness specified in the HUE light</option>
1146
+ </select>
1147
+ </div>
1148
+ <div class="form-row">
1149
+ <label for="node-input-maxDimLevelLight" style="width:260px;">
1150
+ <i class="fa fa-clone"></i> Max Dim Brightness
1151
+ </label>
1152
+ <select id="node-input-maxDimLevelLight"></select>
1153
+ </div>
1043
1154
  </div>
1044
1155
  <div class="form-row">
1045
1156
  <label for="node-input-enableNodePINS" style="width:260px;">
@@ -1056,7 +1167,10 @@
1056
1167
  <br />
1057
1168
  </script>
1058
1169
 
1170
+
1059
1171
  <script type="text/markdown" data-help-name="knxUltimateHueLight">
1172
+
1173
+
1060
1174
  <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>
1061
1175
 
1062
1176
  **General**
@@ -1140,4 +1254,4 @@ The Dimming function works in **KNX mode `start` and `stop`**. To start dimming,
1140
1254
  [Find it useful?](https://www.paypal.me/techtoday)
1141
1255
 
1142
1256
  <br/>
1143
- </script>-
1257
+ </script>