node-red-contrib-knx-ultimate 2.1.3 → 2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ <p>
10
+ <b>Version 2.1.5</b> - June 2023<br/>
11
+ - NEW: Hue light node: added random color cycle effect group address.<br/>
12
+ - Fixed destroying KNX nodes.<br/>
13
+ - Fixed destroying HUE nodes.<br/>
14
+ - Several HUE bugfixes.<br/>
15
+ </p>
9
16
  <p>
10
17
  <b>Version 2.1.3</b> - June 2023<br/>
11
18
  - Bugfix.<br/>
@@ -1,7 +1,7 @@
1
1
 
2
2
  const dptlib = require('./../KNXEngine/dptlib')
3
3
  const hueClass = require('./utils/hueUtils').classHUE
4
-
4
+ const loggerEngine = require('./utils/sysLogger.js')
5
5
  // Helpers
6
6
  const sortBy = (field) => (a, b) => {
7
7
  if (a[field] > b[field]) { return 1 } else { return -1 }
@@ -28,14 +28,6 @@ const convertSubtype = (baseType) => (kv) => {
28
28
  }
29
29
  }
30
30
 
31
- // 06/02/2020 To be tested
32
- // convertSubtype = (baseType) => (kv) => {
33
- // let value = `${baseType.base}.${kv[0]}`
34
- // return {
35
- // value: value
36
- // , text: value + ` (${kv[1].name}${kv[1].unit !== undefined?" - " + kv[1].unit:""})`
37
- // }
38
- // }
39
31
 
40
32
  const toConcattedSubtypes = (acc, baseType) => {
41
33
  const subtypes =
@@ -57,7 +49,7 @@ module.exports = (RED) => {
57
49
  .sort(sortBy('base'))
58
50
  .reduce(toConcattedSubtypes, [])
59
51
 
60
- res.json(dpts)
52
+ res.json(dpts)
61
53
  })
62
54
 
63
55
  function hueConfig(config) {
@@ -68,7 +60,7 @@ module.exports = (RED) => {
68
60
  node.loglevel = config.loglevel !== undefined ? config.loglevel : 'error' // 18/02/2020 Loglevel default error
69
61
  node.sysLogger = null // 20/03/2022 Default
70
62
  try {
71
- node.sysLogger = require('./utils/sysLogger.js').get({ loglevel: node.loglevel }) // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
63
+ node.sysLogger = loggerEngine.get({ loglevel: node.loglevel }) // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
72
64
  } catch (error) { }
73
65
  node.name = (config.name === undefined || config.name === '') ? node.host : config.name // 12/08/2021
74
66
 
@@ -80,7 +72,7 @@ module.exports = (RED) => {
80
72
  node.nodeClients.forEach(_oClient => {
81
73
  const oClient = RED.nodes.getNode(_oClient.id)
82
74
  try {
83
- oClient.handleSendHUE(_event)
75
+ if (oClient.handleSendHUE !== undefined) oClient.handleSendHUE(_event)
84
76
  } catch (error) {
85
77
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error('Errore node.hueManager.on(event): ' + error.message)
86
78
  }
@@ -112,7 +104,7 @@ module.exports = (RED) => {
112
104
  // Check if node already exists
113
105
  if (node.nodeClients.filter(x => x.id === _Node.id).length === 0) {
114
106
  // Add _Node to the clients array
115
- _Node.setNodeStatus({ fill: 'grey', shape: 'ring', text: 'Hue initialized.', payload: '', GA: '', dpt: '', devicename: '' })
107
+ _Node.setNodeStatusHue({ fill: 'grey', shape: 'ring', text: 'Hue initialized.' })
116
108
  // 01/06/2023 Add node to the array
117
109
  const jNode = {}
118
110
  jNode.id = _Node.id
@@ -130,10 +122,19 @@ module.exports = (RED) => {
130
122
 
131
123
  node.on('close', function (done) {
132
124
  try {
133
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.destroy()
125
+ if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger = null; loggerEngine.destroy()
134
126
  node.nodeClients = []
135
- } catch (error) { }
136
- done()
127
+ node.hueManager.removeAllListeners();
128
+ (async () => {
129
+ await node.hueManager.close()
130
+ node.hueManager = null;
131
+ delete node.hueManager;
132
+ done()
133
+ })()
134
+ } catch (error) {
135
+ done()
136
+ console.log(error.message)
137
+ }
137
138
  })
138
139
  }
139
140
 
@@ -11,6 +11,7 @@ const path = require('path')
11
11
  const fs = require('fs')
12
12
  // const { Server } = require('http')
13
13
  const payloadRounder = require('./utils/payloadManipulation')
14
+ const loggerEngine = require('./utils/sysLogger.js')
14
15
 
15
16
  // Helpers
16
17
  const sortBy = (field) => (a, b) => {
@@ -127,7 +128,7 @@ return msg;`,
127
128
  node.loglevel = config.loglevel !== undefined ? config.loglevel : 'error' // 18/02/2020 Loglevel default error
128
129
  node.sysLogger = null // 20/03/2022 Default
129
130
  try {
130
- node.sysLogger = require('./utils/sysLogger.js').get({ loglevel: node.loglevel }) // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
131
+ node.sysLogger = loggerEngine.get({ loglevel: node.loglevel }) // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
131
132
  } catch (error) { }
132
133
  // 12/11/2021 Connect at start delay
133
134
  node.autoReconnect = true // 20/03/2022 Default
@@ -1840,7 +1841,7 @@ return msg;`,
1840
1841
  node.telegramsQueue = []
1841
1842
  node.nodeClients = [] // 05/04/2022 Nullify
1842
1843
  try {
1843
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.destroy()
1844
+ if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger = null; loggerEngine.destroy()
1844
1845
  } catch (error) { }
1845
1846
  done()
1846
1847
  })
@@ -31,7 +31,12 @@ module.exports = function (RED) {
31
31
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
32
32
 
33
33
  }
34
-
34
+ // Used to call the status update from the HUE config node.
35
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
36
+ const dDate = new Date()
37
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
38
+ }
39
+
35
40
  // This function is called by the knx-ultimate config node, to output a msg.payload.
36
41
  node.handleSend = msg => {
37
42
  const state = {}
@@ -159,6 +164,9 @@ module.exports = function (RED) {
159
164
  if (node.server) {
160
165
  node.server.removeClient(node)
161
166
  }
167
+ if (node.serverHue) {
168
+ node.serverHue.removeClient(node)
169
+ }
162
170
  done()
163
171
  })
164
172
  }
@@ -40,6 +40,10 @@
40
40
  GALightBlink: { value: "" },
41
41
  dptLightBlink: { value: "" },
42
42
 
43
+ nameLightColorCycle: { value: "" },
44
+ GALightColorCycle: { value: "" },
45
+ dptLightColorCycle: { value: "" },
46
+
43
47
  hueDevice: { value: "" }
44
48
  },
45
49
  inputs: 0,
@@ -447,6 +451,54 @@
447
451
 
448
452
 
449
453
 
454
+ // DPT Cycle Colors
455
+ // ########################
456
+ $.getJSON('knxUltimateDpts', (data) => {
457
+ data.forEach(dpt => {
458
+ if (dpt.value.startsWith("1.")) {
459
+ $("#node-input-dptLightColorCycle").append($("<option></option>")
460
+ .attr("value", dpt.value)
461
+ .text(dpt.text))
462
+ }
463
+ });
464
+ $("#node-input-dptLightColorCycle").val(this.dptLightColorCycle)
465
+ })
466
+
467
+ // Autocomplete suggestion with ETS csv File
468
+ $("#node-input-GALightColorCycle").autocomplete({
469
+ minLength: 1,
470
+ source: function (request, response) {
471
+ //$.getJSON("csv", request, function( data, status, xhr ) {
472
+ $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
473
+ response($.map(data, function (value, key) {
474
+ var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
475
+ if (fullSearch(sSearch, request.term + " 1.")) {
476
+ return {
477
+ label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
478
+ value: value.ga // Value
479
+ }
480
+ } else {
481
+ return null;
482
+ }
483
+ }));
484
+ });
485
+ }, select: function (event, ui) {
486
+ // Sets Datapoint and device name automatically
487
+ var sDevName = ui.item.label.split("#")[1].trim();
488
+ try {
489
+ sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
490
+ } catch (error) {
491
+ }
492
+ $('#node-input-nameLightColorCycle').val(sDevName);
493
+ var optVal = $("#node-input-dptLightColorCycle option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
494
+ // Select the option value
495
+ $("#node-input-dptLightColorCycle").val(optVal);
496
+ }
497
+ });
498
+ // ########################
499
+
500
+
501
+
450
502
  // Autocomplete suggestion with HUE Lights
451
503
  $("#node-input-name").autocomplete({
452
504
  minLength: 1,
@@ -643,7 +695,19 @@
643
695
  <label for="node-input-nameLightBlink" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
644
696
  <input type="text" id="node-input-nameLightBlink" style="width:200px;margin-left: 5px; text-align: left;">
645
697
  </div>
698
+ </div>
699
+ <div class="form-row">
700
+ <label for="node-input-nameLightColorCycle" style="width:100px;"><i class="fa fa-play-circle-o"></i> Color Cycle</label>
646
701
 
702
+ <label for="node-input-GALightColorCycle" style="width:20px;">GA</label>
703
+ <input type="text" id="node-input-GALightColorCycle" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
704
+
705
+ <label for="node-input-dptLightColorCycle" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
706
+ <select id="node-input-dptLightColorCycle" style="width:140px;"></select>
707
+
708
+ <label for="node-input-nameLightColorCycle" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
709
+ <input type="text" id="node-input-nameLightColorCycle" style="width:200px;margin-left: 5px; text-align: left;">
710
+ </div>
647
711
  <br/>
648
712
  <br/>
649
713
  <br/>
@@ -676,7 +740,8 @@ Start typing in the GA field, the name or group address of your KNX device, the
676
740
  | Color Status | Link this to the light's color status group address. Accepted datapoint is RGB triplet (r,g,b)|
677
741
  | Brightness | This command is used to change the absolute HUE light's brightness |
678
742
  | Brightness Status| Link this to the light's brightness status group address |
679
- | Blink| *true* Blink the light, *false* Stop blinking. Blinks the light on and off. Useful for signalling. It is compatible with all HUE lights. |
743
+ | Blink| *true* Blink the light, *false* Stop blinking. Blinks the light on and off. Useful for signalling. Works with all HUE lights. |
744
+ | Color Cycle| *true* start cycle, *false* Stop cycle. Randomly changes the HUE light's color at regular interval. Works with all HUE lights having color capabilities. |
680
745
 
681
746
  <br/>
682
747
 
@@ -33,6 +33,11 @@ module.exports = function (RED) {
33
33
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
34
34
 
35
35
  }
36
+ // Used to call the status update from the HUE config node.
37
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
38
+ const dDate = new Date()
39
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
40
+ }
36
41
 
37
42
  // This function is called by the knx-ultimate config node, to output a msg.payload.
38
43
  node.handleSend = msg => {
@@ -81,13 +86,51 @@ module.exports = function (RED) {
81
86
  //state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
82
87
  state = msg.payload === true ? { on: { on: true }, dimming: { brightness: 100 } } : { on: { on: false } }
83
88
  node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
84
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
89
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state) // It's ok twice, so the light turns off immeridaley
85
90
  }, 600);
86
91
  } else {
87
92
  if (node.timerBlink !== undefined) clearInterval(node.timerBlink)
88
93
  node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } })
89
94
  }
90
95
  break
96
+ case config.GALightColorCycle:
97
+ const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
98
+ if (gaValColorCycle) {
99
+
100
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: true } })
101
+ node.timerColorCycle = setInterval(() => {
102
+ try {
103
+ function getRandomIntInclusive(min, max) {
104
+ min = Math.ceil(min);
105
+ max = Math.floor(max);
106
+ return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
107
+ }
108
+ const red = getRandomIntInclusive(0, 255)
109
+ const green = getRandomIntInclusive(0, 255)
110
+ const blue = getRandomIntInclusive(0, 255)
111
+ const gamut = node.currentHUEDevice.color.gamut_type || null
112
+ const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut)
113
+ const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue)
114
+ state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } }
115
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
116
+ } catch (error) {
117
+ (async () => {
118
+ try {
119
+ const retLight = await node.serverHue.hueManager.getLight(config.hueDevice)
120
+ node.currentHUEDevice = retLight[0]
121
+ RED.log.error('Errore knxUltimateHueLight node.currentHUEDevice Samba ' + error.message)
122
+ } catch (err) {
123
+ RED.log.error('Errore knxUltimateHueLight node.currentHUEDevice Banana ' + err.message)
124
+ }
125
+ })()
126
+ }
127
+ }, 10000);
128
+
129
+ } else {
130
+ if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
131
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } })
132
+ }
133
+ break
91
134
  default:
92
135
  break
93
136
  }
@@ -174,23 +217,17 @@ module.exports = function (RED) {
174
217
  }
175
218
  if (node.serverHue) {
176
219
  node.serverHue.removeClient(node)
177
- node.serverHue.addClient(node)
178
- setTimeout(() => {
179
- try {
180
- if (node !== null && node.serverHue !== null && node.serverHue.hueManager !== null) {
181
- node.serverHue.hueManager.getLight(config.hueDevice).then(ret => {
182
- try {
183
- if (ret !== undefined && ret.length > 0) node.currentHUEDevice = ret[0]
184
- } catch (error) {
185
- }
186
- //console.log("retrieving node.currentHUEDevice" + node.currentHUEDevice.metadata.name)
187
- })
220
+ if (node !== null && node.serverHue !== null && node.serverHue.hueManager !== null) {
221
+ (async () => {
222
+ try {
223
+ const retLight = await node.serverHue.hueManager.getLight(config.hueDevice)
224
+ node.currentHUEDevice = retLight[0]
225
+ node.serverHue.addClient(node)
226
+ } catch (err) {
227
+ RED.log.error('Errore knxUltimateHueLight node.currentHUEDevice ' + err.message)
188
228
  }
189
- } catch (error) {
190
- console.log('Error: knxUltimateHueLight: node.serverHue.hueManager.getLight: ' + error.message)
191
- }
192
- }, 1000);
193
-
229
+ })()
230
+ }
194
231
  }
195
232
 
196
233
 
@@ -202,6 +239,9 @@ module.exports = function (RED) {
202
239
  if (node.server) {
203
240
  node.server.removeClient(node)
204
241
  }
242
+ if (node.serverHue) {
243
+ node.serverHue.removeClient(node)
244
+ }
205
245
  done()
206
246
  })
207
247
  }
@@ -31,7 +31,12 @@ module.exports = function (RED) {
31
31
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
32
32
 
33
33
  }
34
-
34
+ // Used to call the status update from the HUE config node.
35
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
36
+ const dDate = new Date()
37
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
38
+ }
39
+
35
40
  // This function is called by the knx-ultimate config node, to output a msg.payload.
36
41
  node.handleSend = msg => {
37
42
  }
@@ -81,6 +86,9 @@ module.exports = function (RED) {
81
86
  if (node.server) {
82
87
  node.server.removeClient(node)
83
88
  }
89
+ if (node.serverHue) {
90
+ node.serverHue.removeClient(node)
91
+ }
84
92
  done()
85
93
  })
86
94
  }
@@ -31,7 +31,12 @@ module.exports = function (RED) {
31
31
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
32
32
 
33
33
  }
34
-
34
+ // Used to call the status update from the HUE config node.
35
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
36
+ const dDate = new Date()
37
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
38
+ }
39
+
35
40
  // This function is called by the knx-ultimate config node, to output a msg.payload.
36
41
  node.handleSend = msg => {
37
42
  }
@@ -81,6 +86,9 @@ module.exports = function (RED) {
81
86
  if (node.server) {
82
87
  node.server.removeClient(node)
83
88
  }
89
+ if (node.serverHue) {
90
+ node.serverHue.removeClient(node)
91
+ }
84
92
  done()
85
93
  })
86
94
  }
@@ -53,7 +53,12 @@ module.exports = function (RED) {
53
53
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
54
54
 
55
55
  }
56
-
56
+ // Used to call the status update from the HUE config node.
57
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
58
+ const dDate = new Date()
59
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
60
+ }
61
+
57
62
  // This function is called by the knx-ultimate config node, to output a msg.payload.
58
63
  node.handleSend = msg => {
59
64
  }
@@ -88,7 +93,7 @@ module.exports = function (RED) {
88
93
  }
89
94
  // Send to KNX bus
90
95
  if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
91
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX start Dim' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
96
+ if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX Change color clockwise' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
92
97
  }
93
98
  } else if (_event.relative_rotary.last_event.rotation.direction === 'counter_clock_wise') {
94
99
  if (knxMsgPayload.dpt.startsWith('3.007')) {
@@ -112,7 +117,7 @@ module.exports = function (RED) {
112
117
  }
113
118
  // Send to KNX bus
114
119
  if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
115
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX start Dim' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
120
+ if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX Change color counterclockwise' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
116
121
  }
117
122
  }
118
123
 
@@ -159,6 +164,9 @@ module.exports = function (RED) {
159
164
  if (node.server) {
160
165
  node.server.removeClient(node)
161
166
  }
167
+ if (node.serverHue) {
168
+ node.serverHue.removeClient(node)
169
+ }
162
170
  done()
163
171
  })
164
172
  }
@@ -31,6 +31,12 @@ module.exports = function (RED) {
31
31
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
32
32
 
33
33
  }
34
+ // Used to call the status update from the HUE config node.
35
+ node.setNodeStatusHue = ({ fill, shape, text }) => {
36
+ const dDate = new Date()
37
+ node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
38
+ }
39
+
34
40
 
35
41
  // This function is called by the knx-ultimate config node, to output a msg.payload.
36
42
  node.handleSend = msg => {
@@ -81,6 +87,9 @@ module.exports = function (RED) {
81
87
  if (node.server) {
82
88
  node.server.removeClient(node)
83
89
  }
90
+ if (node.serverHue) {
91
+ node.serverHue.removeClient(node)
92
+ }
84
93
  done()
85
94
  })
86
95
  }
@@ -23,6 +23,7 @@ class classHUE extends EventEmitter {
23
23
  this.clientkey = _clientkey
24
24
  this.bridgeid = _bridgeid
25
25
  this.commandQueue = []
26
+ this.closePushEventStream = false
26
27
  this.timerwriteQueueAdd = setTimeout(this.handleQueue, 3000) // First start
27
28
 
28
29
  // start the SSE Stream Receiver
@@ -68,6 +69,7 @@ class classHUE extends EventEmitter {
68
69
  };
69
70
  // Funzione per richiedere gli eventi
70
71
  const req = () => {
72
+ if (this.closePushEventStream) return // I'm destroying the class
71
73
  const request = https.request(options, handleResponse);
72
74
  request.on('error', (error) => {
73
75
  console.log('KNXUltimateHUEConfig: classHUE: request.on(error): ' + error.message)
@@ -160,6 +162,20 @@ class classHUE extends EventEmitter {
160
162
  console.log('KNXUltimateHUEConfig: classHUE: getLight: ' + error.message)
161
163
  }
162
164
  }
163
-
165
+
166
+ close = async () => {
167
+ return new Promise((resolve, reject) => {
168
+ try {
169
+ this.closePushEventStream = true
170
+ setTimeout(() => {
171
+ resolve(true)
172
+ }, 1000);
173
+ } catch (error) {
174
+ reject(error)
175
+ }
176
+ })
177
+
178
+
179
+ }
164
180
  }
165
181
  module.exports.classHUE = classHUE
@@ -57,7 +57,7 @@ module.exports = {
57
57
  }
58
58
  }
59
59
  })
60
- }
60
+ }
61
61
  return (logger)
62
62
  },
63
63
  destroy: function () {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=14.0.0"
5
5
  },
6
- "version": "2.1.3",
6
+ "version": "2.1.5",
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": "1.0.4",