node-red-contrib-knx-ultimate 2.1.39 → 2.1.41

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,9 +6,19 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ <p>
10
+ <b>Version 2.1.41</b> - August 2023<br/>
11
+ - NEW: HUE Light: you can now control ALL GROUPED LIGHT together.<br/>
12
+ - HUE Light: fixed an issue with the "Link brightness to on/off switch" option, when a json color is selected at daylight or nighttime<br/>
13
+ - HUE Light: New: now you can use both DPT 5.001 and 3.007 in the color temperature, at the same time.<br/>
14
+ </p>
15
+ <p>
16
+ <b>Version 2.1.40</b> - August 2023<br/>
17
+ - HUE Light: Bugfix: color cycle continues to cycle color, even if a FALSE is sent from the group address.<br/>
18
+ </p>
9
19
  <p>
10
20
  <b>Version 2.1.39</b> - August 2023<br/>
11
- - KNX-Ultimate Node: fidex an issue with the topic, in case of update the value without writing on the KNX bus.<br/>
21
+ - KNX-Ultimate Node: fixed an issue with the msg.topic sent to the flow.<br/>
12
22
  - NEW: HUE Light: now you can set the color temperature, using datapoint 5.001 as well.<br/>
13
23
  - NEW: HUE Light: the node will now disable parts of the UI, based on the capabilities of the HUE lamp.<br/>
14
24
  - HUE nodes now wait 15 seconds before getting status and updating KNX devices, after node-red restart. <br/>
@@ -69,7 +69,7 @@ module.exports = (RED) => {
69
69
  // Event clip V2
70
70
  node.hueManager.on('event', _event => {
71
71
  node.nodeClients.forEach(_oClient => {
72
- const oClient = RED.nodes.getNode(_oClient.id)
72
+ const oClient = _oClient
73
73
  try {
74
74
  if (oClient.handleSendHUE !== undefined) oClient.handleSendHUE(_event)
75
75
  } catch (error) {
@@ -103,11 +103,7 @@ module.exports = (RED) => {
103
103
  if (node.nodeClients.filter(x => x.id === _Node.id).length === 0) {
104
104
  // Add _Node to the clients array
105
105
  _Node.setNodeStatusHue({ fill: 'grey', shape: 'ring', text: 'Hue initialized.' })
106
- // 01/06/2023 Add node to the array
107
- const jNode = {}
108
- jNode.id = _Node.id
109
- jNode.topic = _Node.topic
110
- node.nodeClients.push(jNode)
106
+ node.nodeClients.push(_Node)
111
107
  }
112
108
  }
113
109
 
@@ -32,6 +32,10 @@
32
32
  GALightHSV: { value: "" },
33
33
  dptLightHSV: { value: "" },
34
34
 
35
+ nameLightHSVPercentage: { value: "" },
36
+ GALightHSVPercentage: { value: "" },
37
+ dptLightHSVPercentage: { value: "" },
38
+
35
39
  nameLightHSVState: { value: "" },
36
40
  GALightHSVState: { value: "" },
37
41
  dptLightHSVState: { value: "" },
@@ -117,268 +121,32 @@
117
121
  return i == aSearchWords.length;
118
122
  }
119
123
 
120
- // DPT Switch command
121
- // ########################
122
- $.getJSON('knxUltimateDpts', (data) => {
123
- data.forEach(dpt => {
124
- if (dpt.value.startsWith("1.")) {
125
- $("#node-input-dptLightSwitch").append($("<option></option>")
126
- .attr("value", dpt.value)
127
- .text(dpt.text))
128
- }
129
- });
130
- $("#node-input-dptLightSwitch").val(this.dptLightSwitch)
131
- })
132
124
 
133
- // Autocomplete suggestion with ETS csv File
134
- $("#node-input-GALightSwitch").autocomplete({
135
- minLength: 1,
136
- source: function (request, response) {
137
- //$.getJSON("csv", request, function( data, status, xhr ) {
138
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
139
- response($.map(data, function (value, key) {
140
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
141
- if (fullSearch(sSearch, request.term + " 1.")) {
142
- return {
143
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
144
- value: value.ga // Value
145
- }
146
- } else {
147
- return null;
148
- }
149
- }));
125
+ function getDPT(_dpt, _destinationWidget) {
126
+ // DPT Switch command
127
+ // ########################
128
+ $.getJSON('knxUltimateDpts', (data) => {
129
+ data.forEach(dpt => {
130
+ if (dpt.value.startsWith(_dpt)) {
131
+ $(_destinationWidget).append($("<option></option>")
132
+ .attr("value", dpt.value)
133
+ .text(dpt.text))
134
+ }
150
135
  });
151
- }, select: function (event, ui) {
152
- // Sets Datapoint and device name automatically
153
- var sDevName = ui.item.label.split("#")[1].trim();
154
- try {
155
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
156
- } catch (error) {
157
- }
158
- $('#node-input-nameLightSwitch').val(sDevName);
159
- var optVal = $("#node-input-dptLightSwitch option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
160
- // Select the option value
161
- $("#node-input-dptLightSwitch").val(optVal);
162
- }
163
- });
164
- // ########################
165
-
166
-
167
-
168
- // DPT State
169
- // ########################
170
- $.getJSON('knxUltimateDpts', (data) => {
171
- data.forEach(dpt => {
172
- if (dpt.value.startsWith("1.")) {
173
- $("#node-input-dptLightState").append($("<option></option>")
174
- .attr("value", dpt.value)
175
- .text(dpt.text))
176
- }
177
- });
178
-
179
- $("#node-input-dptLightState").val(this.dptLightState)
180
- })
181
-
182
- // Autocomplete suggestion with ETS csv File
183
- $("#node-input-GALightState").autocomplete({
184
- minLength: 1,
185
- source: function (request, response) {
186
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
187
- response($.map(data, function (value, key) {
188
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
189
- if (fullSearch(sSearch, request.term + " 1.")) {
190
- return {
191
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
192
- value: value.ga // Value
193
- }
194
- } else {
195
- return null;
196
- }
197
- }));
198
- });
199
- }, select: function (event, ui) {
200
- // Sets Datapoint and device name automatically
201
- var sDevName = ui.item.label.split("#")[1].trim();
202
- try {
203
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
204
- } catch (error) {
205
- }
206
- $('#node-input-nameLightState').val(sDevName);
207
- var optVal = $("#node-input-dptLightState option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
208
- // Select the option value
209
- $("#node-input-dptLightState").val(optVal);
210
- }
211
- });
212
-
213
-
214
- // DPT dptLightDIM
215
- // ########################
216
- $.getJSON('knxUltimateDpts', (data) => {
217
- data.forEach(dpt => {
218
- if (dpt.value === "3.007") {
219
- $("#node-input-dptLightDIM").append($("<option></option>")
220
- .attr("value", dpt.value)
221
- .text(dpt.text))
222
- }
223
- });
224
-
225
- $("#node-input-dptLightDIM").val(this.dptLightDIM)
226
-
227
- })
228
-
229
- // Autocomplete suggestion with ETS csv File
230
- $("#node-input-GALightDIM").autocomplete({
231
- minLength: 1,
232
- source: function (request, response) {
233
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
234
- response($.map(data, function (value, key) {
235
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
236
- if (fullSearch(sSearch, request.term + " 3.007")) {
237
- return {
238
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
239
- value: value.ga // Value
240
- }
241
- } else {
242
- return null;
243
- }
244
- }));
245
- });
246
- }, select: function (event, ui) {
247
- // Sets Datapoint and device name automatically
248
- var sDevName = ui.item.label.split("#")[1].trim();
249
- try {
250
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
251
- } catch (error) {
252
- }
253
- $('#node-input-nameLightDIM').val(sDevName);
254
- var optVal = $("#node-input-dptLightDIM option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
255
- // Select the option value
256
- $("#node-input-dptLightDIM").val(optVal);
257
- }
258
- });
259
-
260
-
261
- // DPT dptLightColor and dptLightColorState
262
- // ########################
263
- $.getJSON('knxUltimateDpts', (data) => {
264
- data.forEach(dpt => {
265
- if (dpt.value === "232.600") {
266
- $("#node-input-dptLightColor").append($("<option></option>")
267
- .attr("value", dpt.value)
268
- .text(dpt.text))
269
- $("#node-input-dptLightColorState").append($("<option></option>")
270
- .attr("value", dpt.value)
271
- .text(dpt.text))
272
- }
273
- });
274
-
275
- $("#node-input-dptLightColor").val(this.dptLightColor)
276
- $("#node-input-dptLightColorState").val(this.dptLightColorState)
277
-
278
- })
279
-
280
- // Autocomplete suggestion with ETS csv File
281
- $("#node-input-GALightColor").autocomplete({
282
- minLength: 1,
283
- source: function (request, response) {
284
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
285
- response($.map(data, function (value, key) {
286
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
287
- if (fullSearch(sSearch, request.term + " 232.600")) {
288
- return {
289
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
290
- value: value.ga // Value
291
- }
292
- } else {
293
- return null;
294
- }
295
- }));
296
- });
297
- }, select: function (event, ui) {
298
- // Sets Datapoint and device name automatically
299
- var sDevName = ui.item.label.split("#")[1].trim();
300
- try {
301
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
302
- } catch (error) {
303
- }
304
- $('#node-input-nameLightColor').val(sDevName);
305
- var optVal = $("#node-input-dptLightColor option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
306
- // Select the option value
307
- $("#node-input-dptLightColor").val(optVal);
308
- }
309
- });
310
-
311
- // Autocomplete suggestion with ETS csv File
312
- $("#node-input-GALightColorState").autocomplete({
313
- minLength: 1,
314
- source: function (request, response) {
315
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
316
- response($.map(data, function (value, key) {
317
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
318
- if (fullSearch(sSearch, request.term + " 232.600")) {
319
- return {
320
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
321
- value: value.ga // Value
322
- }
323
- } else {
324
- return null;
325
- }
326
- }));
327
- });
328
- }, select: function (event, ui) {
329
- // Sets Datapoint and device name automatically
330
- var sDevName = ui.item.label.split("#")[1].trim();
331
- try {
332
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
333
- } catch (error) {
334
- }
335
- $('#node-input-nameLightColorState').val(sDevName);
336
- var optVal = $("#node-input-dptLightColorState option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
337
- // Select the option value
338
- $("#node-input-dptLightColorState").val(optVal);
339
- }
340
- });
341
-
342
-
343
-
344
-
345
-
346
-
347
- // DPT dptLightTunableWhite
348
- // ########################
349
- $.getJSON('knxUltimateDpts', (data) => {
350
- data.forEach(dpt => {
351
- if (dpt.value === "3.007" || dpt.value === "5.001") {
352
- $("#node-input-dptLightHSV").append($("<option></option>")
353
- .attr("value", dpt.value)
354
- .text(dpt.text))
355
- }
356
- });
357
-
358
- $("#node-input-dptLightHSV").val(this.dptLightHSV)
359
- })
136
+ $(_destinationWidget).val(this + "." + _destinationWidget-replace("#node-input-",""))
137
+ })
138
+ }
360
139
 
361
- // DPT dptLightTunableWhiteState
362
- $.getJSON('knxUltimateDpts', (data) => {
363
- data.forEach(dpt => {
364
- if (dpt.value === "5.001") {
365
- $("#node-input-dptLightHSVState").append($("<option></option>")
366
- .attr("value", dpt.value)
367
- .text(dpt.text))
368
- }
369
- });
370
- $("#node-input-dptLightHSVState").val(this.dptLightHSVState)
371
- })
372
140
 
373
- // Autocomplete suggestion with ETS csv File
374
- $("#node-input-GALightHSV").autocomplete({
375
- minLength: 1,
376
- source: function (request, response) {
377
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
378
- response($.map(data, function (value, key) {
379
- if (value.dpt === "3.007" || value.dpt === "5.001") {
141
+ function getGroupAddress(_sourceWidgetAutocomplete, _destinationWidgetName, _destinationWidgetDPT, _additionalSearchTerm) {
142
+ $(_sourceWidgetAutocomplete).autocomplete({
143
+ minLength: 1,
144
+ source: function (request, response) {
145
+ //$.getJSON("csv", request, function( data, status, xhr ) {
146
+ $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
147
+ response($.map(data, function (value, key) {
380
148
  var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
381
- if (fullSearch(sSearch, request.term)) {
149
+ if (fullSearch(sSearch, request.term + _additionalSearchTerm)) {
382
150
  return {
383
151
  label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
384
152
  value: value.ga // Value
@@ -386,283 +154,62 @@
386
154
  } else {
387
155
  return null;
388
156
  }
389
- }
390
- }));
391
- });
392
- }, select: function (event, ui) {
393
- // Sets Datapoint and device name automatically
394
- var sDevName = ui.item.label.split("#")[1].trim();
395
- try {
396
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
397
- } catch (error) {
398
- }
399
- $('#node-input-nameLightHSV').val(sDevName);
400
- var optVal = $("#node-input-dptLightHSV option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
401
- // Select the option value
402
- $("#node-input-dptLightHSV").val(optVal);
403
- }
404
- });
405
-
406
- // Autocomplete suggestion with ETS csv File
407
- $("#node-input-GALightHSVState").autocomplete({
408
- minLength: 1,
409
- source: function (request, response) {
410
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
411
- response($.map(data, function (value, key) {
412
- if (value.dpt === "5.001") {
413
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
414
- if (fullSearch(sSearch, request.term)) {
415
- return {
416
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
417
- value: value.ga // Value
418
- }
419
- } else {
420
- return null;
421
- }
422
- }
423
- }));
424
- });
425
- }, select: function (event, ui) {
426
- // Sets Datapoint and device name automatically
427
- var sDevName = ui.item.label.split("#")[1].trim();
428
- try {
429
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
430
- } catch (error) {
431
- }
432
- $('#node-input-nameLightHSVState').val(sDevName);
433
- var optVal = $("#node-input-dptLightHSVState option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
434
- // Select the option value
435
- $("#node-input-dptLightHSVState").val(optVal);
436
- }
437
- });
438
- // ########################
439
-
440
-
441
-
442
-
443
- // DPT dptLightBrightness and dptLightBrightnessState
444
- // ########################
445
- $.getJSON('knxUltimateDpts', (data) => {
446
- data.forEach(dpt => {
447
- if (dpt.value === "5.001") {
448
- $("#node-input-dptLightBrightness").append($("<option></option>")
449
- .attr("value", dpt.value)
450
- .text(dpt.text))
451
- $("#node-input-dptLightBrightnessState").append($("<option></option>")
452
- .attr("value", dpt.value)
453
- .text(dpt.text))
157
+ }));
158
+ });
159
+ }, select: function (event, ui) {
160
+ // Sets Datapoint and device name automatically
161
+ var sDevName = ui.item.label.split("#")[1].trim();
162
+ try {
163
+ sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
164
+ } catch (error) {
165
+ }
166
+ $(_destinationWidgetName).val(sDevName);
167
+ var optVal = $(_destinationWidgetDPT + " option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
168
+ // Select the option value
169
+ $(_destinationWidgetDPT).val(optVal);
454
170
  }
455
171
  });
172
+ }
456
173
 
457
- $("#node-input-dptLightBrightness").val(this.dptLightBrightness)
458
- $("#node-input-dptLightBrightnessState").val(this.dptLightBrightnessState)
459
-
460
- })
461
-
462
- // Autocomplete suggestion with ETS csv File
463
- $("#node-input-GALightBrightness").autocomplete({
464
- minLength: 1,
465
- source: function (request, response) {
466
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
467
- response($.map(data, function (value, key) {
468
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
469
- if (fullSearch(sSearch, request.term + " 5.001")) {
470
- return {
471
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
472
- value: value.ga // Value
473
- }
474
- } else {
475
- return null;
476
- }
477
- }));
478
- });
479
- }, select: function (event, ui) {
480
- // Sets Datapoint and device name automatically
481
- var sDevName = ui.item.label.split("#")[1].trim();
482
- try {
483
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
484
- } catch (error) {
485
- }
486
- $('#node-input-nameLightBrightness').val(sDevName);
487
- var optVal = $("#node-input-dptLightBrightness option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
488
- // Select the option value
489
- $("#node-input-dptLightBrightness").val(optVal);
490
- }
491
- });
492
-
493
- // Autocomplete suggestion with ETS csv File
494
- $("#node-input-GALightBrightnessState").autocomplete({
495
- minLength: 1,
496
- source: function (request, response) {
497
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
498
- response($.map(data, function (value, key) {
499
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
500
- if (fullSearch(sSearch, request.term + " 5.001")) {
501
- return {
502
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
503
- value: value.ga // Value
504
- }
505
- } else {
506
- return null;
507
- }
508
- }));
509
- });
510
- }, select: function (event, ui) {
511
- // Sets Datapoint and device name automatically
512
- var sDevName = ui.item.label.split("#")[1].trim();
513
- try {
514
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
515
- } catch (error) {
516
- }
517
- $('#node-input-nameLightBrightnessState').val(sDevName);
518
- var optVal = $("#node-input-dptLightBrightnessState option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
519
- // Select the option value
520
- $("#node-input-dptLightBrightnessState").val(optVal);
521
- }
522
- });
523
-
524
-
174
+ getDPT("1.", "#node-input-dptLightSwitch")
175
+ getGroupAddress("#node-input-GALightSwitch", "#node-input-nameLightSwitch", "#node-input-dptLightSwitch", " 1.")
176
+
177
+ getDPT("1.", "#node-input-dptLightState")
178
+ getGroupAddress("#node-input-GALightState", "#node-input-nameLightState", "#node-input-dptLightState", " 1.")
525
179
 
526
- // DPT Blink command
527
- // ########################
528
- $.getJSON('knxUltimateDpts', (data) => {
529
- data.forEach(dpt => {
530
- if (dpt.value.startsWith("1.")) {
531
- $("#node-input-dptLightBlink").append($("<option></option>")
532
- .attr("value", dpt.value)
533
- .text(dpt.text))
534
- }
535
- });
536
- $("#node-input-dptLightBlink").val(this.dptLightSwitch)
537
- })
180
+ getDPT("3.007", "#node-input-dptLightDIM")
181
+ getGroupAddress("#node-input-GALightDIM", "#node-input-nameLightDIM", "#node-input-dptLightDIM", " 3.007")
182
+
183
+ getDPT("5.001", "#node-input-dptLightBrightness")
184
+ getGroupAddress("#node-input-GALightBrightness", "#node-input-nameLightBrightness", "#node-input-dptLightBrightness", " 5.001")
185
+
186
+ getDPT("5.001", "#node-input-dptLightBrightnessState")
187
+ getGroupAddress("#node-input-GALightBrightnessState", "#node-input-nameLightBrightnessState", "#node-input-dptLightBrightnessState", " 5.001")
538
188
 
539
- // Autocomplete suggestion with ETS csv File
540
- $("#node-input-GALightBlink").autocomplete({
541
- minLength: 1,
542
- source: function (request, response) {
543
- //$.getJSON("csv", request, function( data, status, xhr ) {
544
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
545
- response($.map(data, function (value, key) {
546
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
547
- if (fullSearch(sSearch, request.term + " 1.")) {
548
- return {
549
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
550
- value: value.ga // Value
551
- }
552
- } else {
553
- return null;
554
- }
555
- }));
556
- });
557
- }, select: function (event, ui) {
558
- // Sets Datapoint and device name automatically
559
- var sDevName = ui.item.label.split("#")[1].trim();
560
- try {
561
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
562
- } catch (error) {
563
- }
564
- $('#node-input-nameLightBlink').val(sDevName);
565
- var optVal = $("#node-input-dptLightBlink option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
566
- // Select the option value
567
- $("#node-input-dptLightBlink").val(optVal);
568
- }
569
- });
570
- // ########################
189
+ getDPT("232.600", "#node-input-dptLightColor")
190
+ getGroupAddress("#node-input-GALightColor", "#node-input-nameLightColor", "#node-input-dptLightColor", " 232.600")
571
191
 
192
+ getDPT("232.600", "#node-input-dptLightColorState")
193
+ getGroupAddress("#node-input-GALightColorState", "#node-input-nameLightColorState", "#node-input-dptLightColorState", " 232.600")
572
194
 
195
+ getDPT("3.007", "#node-input-dptLightHSV")
196
+ getGroupAddress("#node-input-GALightHSV", "#node-input-nameLightHSV", "#node-input-dptLightHSV", " 3.007")
573
197
 
574
- // DPT Cycle Colors
575
- // ########################
576
- $.getJSON('knxUltimateDpts', (data) => {
577
- data.forEach(dpt => {
578
- if (dpt.value.startsWith("1.")) {
579
- $("#node-input-dptLightColorCycle").append($("<option></option>")
580
- .attr("value", dpt.value)
581
- .text(dpt.text))
582
- }
583
- });
584
- $("#node-input-dptLightColorCycle").val(this.dptLightColorCycle)
585
- })
198
+ getDPT("5.001", "#node-input-dptLightHSVPercentage")
199
+ getGroupAddress("#node-input-GALightHSVPercentage", "#node-input-nameLightHSVPercentage", "#node-input-dptLightHSVPercentage", " 5.001")
586
200
 
587
- // Autocomplete suggestion with ETS csv File
588
- $("#node-input-GALightColorCycle").autocomplete({
589
- minLength: 1,
590
- source: function (request, response) {
591
- //$.getJSON("csv", request, function( data, status, xhr ) {
592
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
593
- response($.map(data, function (value, key) {
594
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
595
- if (fullSearch(sSearch, request.term + " 1.")) {
596
- return {
597
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
598
- value: value.ga // Value
599
- }
600
- } else {
601
- return null;
602
- }
603
- }));
604
- });
605
- }, select: function (event, ui) {
606
- // Sets Datapoint and device name automatically
607
- var sDevName = ui.item.label.split("#")[1].trim();
608
- try {
609
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
610
- } catch (error) {
611
- }
612
- $('#node-input-nameLightColorCycle').val(sDevName);
613
- var optVal = $("#node-input-dptLightColorCycle option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
614
- // Select the option value
615
- $("#node-input-dptLightColorCycle").val(optVal);
616
- }
617
- });
618
- // ########################
201
+ getDPT("5.001", "#node-input-dptLightHSVState")
202
+ getGroupAddress("#node-input-GALightHSVState", "#node-input-nameLightHSVState", "#node-input-dptLightHSVState", " 5.001")
619
203
 
204
+ getDPT("1.", "#node-input-dptLightBlink")
205
+ getGroupAddress("#node-input-GALightBlink", "#node-input-nameLightBlink", "#node-input-dptLightBlink", " 1.")
620
206
 
621
- // DPT Day/Time sensor
622
- // ########################
623
- $.getJSON('knxUltimateDpts', (data) => {
624
- data.forEach(dpt => {
625
- if (dpt.value.startsWith("1.")) {
626
- $("#node-input-dptDaylightSensor").append($("<option></option>")
627
- .attr("value", dpt.value)
628
- .text(dpt.text))
629
- }
630
- });
631
- $("#node-input-dptDaylightSensor").val(this.dptDaylightSensor)
632
- })
207
+ getDPT("1.", "#node-input-dptLightColorCycle")
208
+ getGroupAddress("#node-input-GALightColorCycle", "#node-input-nameLightColorCycle", "#node-input-dptLightColorCycle", " 1.")
209
+
210
+ getDPT("1.", "#node-input-dptDaylightSensor")
211
+ getGroupAddress("#node-input-GADaylightSensor", "#node-input-nameDaylightSensor", "#node-input-dptDaylightSensor", " 1.")
633
212
 
634
- // Autocomplete suggestion with ETS csv File
635
- $("#node-input-GADaylightSensor").autocomplete({
636
- minLength: 1,
637
- source: function (request, response) {
638
- //$.getJSON("csv", request, function( data, status, xhr ) {
639
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
640
- response($.map(data, function (value, key) {
641
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
642
- if (fullSearch(sSearch, request.term + " 1.")) {
643
- return {
644
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
645
- value: value.ga // Value
646
- }
647
- } else {
648
- return null;
649
- }
650
- }));
651
- });
652
- }, select: function (event, ui) {
653
- // Sets Datapoint and device name automatically
654
- var sDevName = ui.item.label.split("#")[1].trim();
655
- try {
656
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
657
- } catch (error) {
658
- }
659
- $('#node-input-nameDaylightSensor').val(sDevName);
660
- var optVal = $("#node-input-dptDaylightSensor option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
661
- // Select the option value
662
- $("#node-input-dptDaylightSensor").val(optVal);
663
- }
664
- });
665
- // ########################
666
213
 
667
214
  // Show/Hide and enable/disable day/night Lighting behaviour
668
215
  if (this.enableDayNightLighting === true) {
@@ -711,18 +258,18 @@
711
258
  data.devices.forEach(element => {
712
259
  if (element.id === this.hueDevice.split('#')[0] && element.deviceObject !== undefined) {
713
260
  // Check dimming
714
- if (element.deviceObject.dimming === undefined){
261
+ if (element.deviceObject.dimming === undefined) {
715
262
  $('#tabs').tabs("disable", "#tabs-2");
716
263
  $('#divColorsAtSwitchOn').hide()
717
264
  $('#divColorCycle').hide()
718
- }
265
+ }
719
266
  // Check color
720
267
  if (element.deviceObject.color_temperature === undefined) $('#tabs').tabs("disable", "#tabs-3");
721
- if (element.deviceObject.color === undefined){
268
+ if (element.deviceObject.color === undefined) {
722
269
  $('#tabs').tabs("disable", "#tabs-4");
723
270
  $('#divColorsAtSwitchOn').hide()
724
271
  $('#divColorCycle').hide()
725
- }
272
+ }
726
273
  return
727
274
  }
728
275
  });
@@ -812,7 +359,7 @@
812
359
  <input type="text" id="node-input-nameLightSwitch" style="width:190px;margin-left: 5px; text-align: left;">
813
360
  </div>
814
361
  <div class="form-row">
815
- <label for="node-input-nameLightState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Switch Status</label>
362
+ <label for="node-input-nameLightState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Status</label>
816
363
 
817
364
  <label for="node-input-GALightState" style="width:20px;">GA</label>
818
365
  <input type="text" id="node-input-GALightState" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -871,7 +418,7 @@
871
418
  <div id="tabs-2">
872
419
  <p>
873
420
  <div class="form-row">
874
- <label for="node-input-nameLightDIM" style="width:110px;"><i class="fa fa-play-circle-o"></i>&nbspDimming</label>
421
+ <label for="node-input-nameLightDIM" style="width:110px;"><i class="fa fa-play-circle-o"></i> Dimming</label>
875
422
 
876
423
  <label for="node-input-GALightDIM" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
877
424
  <input type="text" id="node-input-GALightDIM" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -883,7 +430,7 @@
883
430
  <input type="text" id="node-input-nameLightDIM" style="width:190px;margin-left: 5px; text-align: left;">
884
431
  </div>
885
432
  <div class="form-row">
886
- <label for="node-input-nameLightBrightness" style="width:110px;"><i class="fa fa-play-circle-o"></i>&nbspBrightness</label>
433
+ <label for="node-input-nameLightBrightness" style="width:110px;"><i class="fa fa-play-circle-o"></i> Percentage</label>
887
434
 
888
435
  <label for="node-input-GALightBrightness" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
889
436
  <input type="text" id="node-input-GALightBrightness" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -896,7 +443,7 @@
896
443
  </div>
897
444
 
898
445
  <div class="form-row">
899
- <label for="node-input-nameLightBrightnessState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Brightness Status</label>
446
+ <label for="node-input-nameLightBrightnessState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Status</label>
900
447
 
901
448
  <label for="node-input-GALightBrightnessState" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
902
449
  <input type="text" id="node-input-GALightBrightnessState" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -912,19 +459,32 @@
912
459
  <div id="tabs-3">
913
460
  <p>
914
461
  <div class="form-row">
915
- <label for="node-input-nameLightHSV" style="width:110px;"><i class="fa fa-play-circle-o"></i> Tunable white</label>
462
+ <label for="node-input-nameLightHSV" style="width:110px;"><i class="fa fa-play-circle-o"></i> Dimming</label>
916
463
 
917
- <label for="node-input-GALightHSV" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
464
+ <label for="node-input-GALightHSV" style="width:20px;">GA</label>
918
465
  <input type="text" id="node-input-GALightHSV" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
919
466
 
920
467
  <label for="node-input-dptLightHSV" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
921
468
  <select id="node-input-dptLightHSV" style="width:140px;"></select>
922
469
 
923
- <label for="node-input-nameLightHSV" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
470
+ <label for="node-input-nameLightHSV" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
924
471
  <input type="text" id="node-input-nameLightHSV" style="width:190px;margin-left: 5px; text-align: left;">
925
472
  </div>
926
473
  <div class="form-row">
927
- <label for="node-input-nameLightHSVState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Tunable white Status</label>
474
+ <label for="node-input-nameLightHSVPercentage" style="width:110px;"><i class="fa fa-play-circle-o"></i> Percentage</label>
475
+
476
+ <label for="node-input-GALightHSVPercentage" style="width:20px;">GA</label>
477
+ <input type="text" id="node-input-GALightHSVPercentage" placeholder="Ex: 1/1/1"
478
+ style="width:70px;margin-left: 5px; text-align: left;">
479
+
480
+ <label for="node-input-dptLightHSVPercentage" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
481
+ <select id="node-input-dptLightHSVPercentage" style="width:140px;"></select>
482
+
483
+ <label for="node-input-nameLightHSVPercentage" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
484
+ <input type="text" id="node-input-nameLightHSVPercentage" style="width:190px;margin-left: 5px; text-align: left;">
485
+ </div>
486
+ <div class="form-row">
487
+ <label for="node-input-nameLightHSVState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Status</label>
928
488
 
929
489
  <label for="node-input-GALightHSVState" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
930
490
  <input type="text" id="node-input-GALightHSVState" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -952,7 +512,7 @@
952
512
  <input type="text" id="node-input-nameLightColor" style="width:190px;margin-left: 5px; text-align: left;">
953
513
  </div>
954
514
  <div class="form-row">
955
- <label for="node-input-nameLightColorState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Color Status</label>
515
+ <label for="node-input-nameLightColorState" style="width:110px;"><i class="fa fa-play-circle-o"></i> Status</label>
956
516
 
957
517
  <label for="node-input-GALightColorState" style="width:20px;"><span data-i18n="knxUltimateHueLight.node-input-GALightState"></span></label>
958
518
  <input type="text" id="node-input-GALightColorState" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
@@ -1034,7 +594,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
1034
594
  |Property|Description|
1035
595
  |--|--|
1036
596
  | Switch | This GA is used to turn on/off the HUE light via a boolean KNX value true/false|
1037
- | Switch Status | Link this to the light's switch status group address|
597
+ | Status | Link this to the light's switch status group address|
1038
598
  | Switch On - color/brightness | You can choose the color/brightness of your light, at switch on. Set it as JSON object, for example **{ "red": 255, "green": 255, "blue": 255 }**. Leave blank to disable. |
1039
599
  | Night Lighting | It allows to set a particular light color/brightness at nighttime. If **checked**, a further set of option shows up and the light changes the behaviour based on these options, everytime you switch the light *on*. |
1040
600
  | Switch On - color/brightness at Nighttime | You can choose the color/brightness of your light, at switch on, on night time. Set it as JSON object. Default value if you leave blank is **{ "red": 100, "green": 0, "blue": 0 }** |
@@ -1047,16 +607,17 @@ Start typing in the GA field, the name or group address of your KNX device, the
1047
607
  |Property|Description|
1048
608
  |--|--|
1049
609
  | Dimming | Relative DIM the HUE light |
1050
- | Brightness | This command is used to change the absolute HUE light's brightness |
1051
- | Brightness Status| Link this to the light's brightness status group address |
610
+ | Percentage | Changes the absolute HUE light's brightness (0-100%)|
611
+ | Status| Link this to the light's brightness status group address |
1052
612
 
1053
613
  <br/>
1054
614
 
1055
615
  **Tunable white**
1056
616
  |Property|Description|
1057
617
  |--|--|
1058
- | Tunable white | This command is used to change the HUE light's white temperature. Datapoint is 3.007 dimming or 5.001 percentage. When set to 5.001, a value of 0 is full warm, a value of 100 is full cold .|
1059
- | Tunable white Status | Link this to the light temperature status group address. Datapoint is 5.001 absolute value. 0 is full warm, 100 is full cold.|
618
+ | Dimming| Changes the HUE light's white temperature, using DPT 3.007 dimming.|
619
+ | Percentage | Changes the HUE light's white temperature, using the DPT 5.001. A value of 0 is full warm, a value of 100 is full cold.|
620
+ | Status | Link this to the light temperature status group address. Datapoint is 5.001 absolute value. 0 is full warm, 100 is full cold.|
1060
621
 
1061
622
  <br/>
1062
623
 
@@ -1064,7 +625,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
1064
625
  |Property|Description|
1065
626
  |--|--|
1066
627
  | Color | This command is used to change the HUE light's color. Accepted datapoint is RGB triplet (r,g,b). The node handles the gamut color correction. As soon as you send a color KNX telegran, the light turns on and sets color and brightness, derived from the brightness human perception. As soon as you send a KNX telegram with r,g,b set to zero, the light turns off |
1067
- | Color Status | Link this to the light's color status group address. Accepted datapoint is RGB triplet (r,g,b)|
628
+ | Status | Link this to the light's color status group address. Accepted datapoint is RGB triplet (r,g,b)|
1068
629
 
1069
630
  <br/>
1070
631
 
@@ -64,7 +64,11 @@ module.exports = function (RED) {
64
64
  }
65
65
  let dretXY = hueColorConverter.ColorConverter.rgbToXy(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue, gamut)
66
66
  let dbright = hueColorConverter.ColorConverter.getBrightnessFromRGB(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue)
67
- state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
67
+ if (config.linkBrightnessToSwitchStatus === undefined || config.linkBrightnessToSwitchStatus === 'yes') {
68
+ state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
69
+ } else {
70
+ state = dbright > 0 ? { on: { on: true }, color: { xy: dretXY } } : { on: { on: false } }
71
+ }
68
72
  } else {
69
73
  if (config.linkBrightnessToSwitchStatus === undefined || config.linkBrightnessToSwitchStatus === 'yes') {
70
74
  state = { on: { on: true }, dimming: { brightness: 100 } }
@@ -83,7 +87,11 @@ module.exports = function (RED) {
83
87
  }
84
88
  let dretXY = hueColorConverter.ColorConverter.rgbToXy(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue, gamut)
85
89
  let dbright = hueColorConverter.ColorConverter.getBrightnessFromRGB(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue)
86
- state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
90
+ if (config.linkBrightnessToSwitchStatus === undefined || config.linkBrightnessToSwitchStatus === 'yes') {
91
+ state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
92
+ } else {
93
+ state = dbright > 0 ? { on: { on: true }, color: { xy: dretXY } } : { on: { on: false } }
94
+ }
87
95
  }
88
96
  }
89
97
  } else {
@@ -141,9 +149,13 @@ module.exports = function (RED) {
141
149
  node.startDimStopperTunableWhite('stop')
142
150
  }
143
151
  }
144
- if (config.dptLightHSV === '5.001') {
152
+ node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: msg.payload })
153
+ break
154
+ case config.GALightHSVPercentage:
155
+ if (config.dptLightHSVPercentage === '5.001') {
145
156
  // 0-100% tunable white
146
- msg.payload = 100 - dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightHSV))
157
+ msg.payload = 100 - dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightHSVPercentage))
158
+ //msg.payload = msg.payload <= 0 ? 1 : msg.payload
147
159
  const retMirek = hueColorConverter.ColorConverter.scale(msg.payload, [0, 100], [153, 500])
148
160
  msg.payload = retMirek
149
161
  state = { color_temperature: { mirek: msg.payload } }
@@ -231,6 +243,7 @@ module.exports = function (RED) {
231
243
  }
232
244
  }, 10000)
233
245
  } else {
246
+ if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
234
247
  node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } }, (node.isGrouped_light === false ? 'setLight' : 'setGroupedLight'))
235
248
  }
236
249
  node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: gaValColorCycle })
@@ -47,7 +47,9 @@ module.exports = function (RED) {
47
47
  knxMsgPayload.dpt = config.dptlightsensor
48
48
 
49
49
  if (_event.hasOwnProperty('light') && _event.light.hasOwnProperty('light_level')) {
50
- knxMsgPayload.payload = Math.round(10 ** ((_event.light.light_level - 1) / 10000))
50
+ //console.log(Math.round(10 ** ((_event.light.light_level - 1) / 10000)))
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))
51
53
  // Send to KNX bus
52
54
  if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
53
55
  node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
@@ -232,10 +232,13 @@ getResources = async (_rtype, _host, _username) => {
232
232
  const owners = await this.hueAllResources.filter(a => a.id === resource.owner.rid)
233
233
  for (let index = 0; index < owners.length; index++) {
234
234
  const owner = owners[index];
235
- //resourceName += (owner.metadata !== undefined && owner.metadata.name !== undefined) ? owner.metadata.name + ' and ' : ' and '
236
- resourceName += owner.metadata.name + ' and '
237
- const room = await this.hueAllRooms.find(child => child.children.find(a => a.rid === owner.id))
238
- sRoom += room !== undefined ? room.metadata.name + ' + ' : ' + '
235
+ if (owner.type === 'bridge_home') {
236
+ resourceName += 'ALL GROUPS and '
237
+ } else {
238
+ resourceName += owner.metadata.name + ' and '
239
+ const room = await this.hueAllRooms.find(child => child.children.find(a => a.rid === owner.id))
240
+ sRoom += room !== undefined ? room.metadata.name + ' + ' : ' + '
241
+ }
239
242
  }
240
243
  sRoom = sRoom.slice(0, -(' + '.length))
241
244
  resourceName = resourceName.slice(0, -(' and '.length))
@@ -278,7 +281,7 @@ getResources = async (_rtype, _host, _username) => {
278
281
  retArray.push({ name: 'Battery: ' + linkedDevName + (Room !== undefined ? ', room ' + Room.metadata.name : ''), id: resource.id })
279
282
  }
280
283
  } catch (error) {
281
- //retArray.push({ name: _rtype + ': ERROR ' + error.message, id: resource.id })
284
+ retArray.push({ name: _rtype + ': ERROR ' + error.message, id: resource.id })
282
285
  }
283
286
  }
284
287
  return { devices: retArray }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=16.0.0"
5
5
  },
6
- "version": "2.1.39",
6
+ "version": "2.1.41",
7
7
  "description": "Control your KNX intallation via Node-Red! Single Node KNX IN/OUT with optional ETS group address importer. Easy to use and highly configurable. With integrated Philips HUE devices handling.",
8
8
  "dependencies": {
9
9
  "mkdirp": "3.0.1",