node-red-contrib-knx-ultimate 2.1.4 → 2.1.6
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 +4 -0
- package/nodes/hue-config.js +0 -8
- package/nodes/knxUltimateHueLight.js +41 -41
- package/nodes/knxUltimateHueTapDial.html +1 -1
- package/nodes/knxUltimateHueTapDial.js +22 -41
- package/nodes/utils/hueUtils.js +24 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/nodes/hue-config.js
CHANGED
|
@@ -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 =
|
|
@@ -47,7 +47,7 @@ module.exports = function (RED) {
|
|
|
47
47
|
case config.GALightSwitch:
|
|
48
48
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
|
|
49
49
|
state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
|
|
50
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
|
|
50
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight')
|
|
51
51
|
break
|
|
52
52
|
case config.GALightDIM:
|
|
53
53
|
// { decr_incr: 1, data: 1 } : Start increasing until { decr_incr: 0, data: 0 } is received.
|
|
@@ -64,17 +64,16 @@ module.exports = function (RED) {
|
|
|
64
64
|
case config.GALightBrightness:
|
|
65
65
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightBrightness))
|
|
66
66
|
state = { dimming: { brightness: msg.payload } }
|
|
67
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
|
|
67
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight')
|
|
68
68
|
break
|
|
69
69
|
case config.GALightColor:
|
|
70
70
|
// Behavior like ISE HUE CONNECT, by setting the brightness and on/off as well
|
|
71
|
-
if (node.currentHUEDevice === undefined) return
|
|
72
71
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColor))
|
|
73
|
-
const gamut = node.currentHUEDevice.color.gamut_type
|
|
72
|
+
const gamut = node.currentHUEDevice !== undefined ? node.currentHUEDevice.color.gamut_type : null
|
|
74
73
|
const retXY = hueColorConverter.ColorConverter.rgbToXy(msg.payload.red, msg.payload.green, msg.payload.blue, gamut)
|
|
75
74
|
const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(msg.payload.red, msg.payload.green, msg.payload.blue)
|
|
76
75
|
state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } }
|
|
77
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
|
|
76
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight')
|
|
78
77
|
break
|
|
79
78
|
case config.GALightBlink:
|
|
80
79
|
const gaVal = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
|
|
@@ -85,36 +84,42 @@ module.exports = function (RED) {
|
|
|
85
84
|
msg.payload = node.blinkValue
|
|
86
85
|
//state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
|
|
87
86
|
state = msg.payload === true ? { on: { on: true }, dimming: { brightness: 100 } } : { on: { on: false } }
|
|
88
|
-
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
|
|
87
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight')
|
|
88
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight') // It's ok twice, so the light turns off immeridaley
|
|
90
89
|
}, 600);
|
|
91
90
|
} else {
|
|
92
91
|
if (node.timerBlink !== undefined) clearInterval(node.timerBlink)
|
|
93
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } })
|
|
92
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } }, 'setLight')
|
|
94
93
|
}
|
|
95
94
|
break
|
|
96
95
|
case config.GALightColorCycle:
|
|
97
96
|
const gaValColorCycle = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
|
|
98
97
|
if (gaValColorCycle) {
|
|
99
|
-
|
|
98
|
+
|
|
99
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: true } }, 'setLight')
|
|
100
100
|
node.timerColorCycle = setInterval(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
try {
|
|
102
|
+
function getRandomIntInclusive(min, max) {
|
|
103
|
+
min = Math.ceil(min);
|
|
104
|
+
max = Math.floor(max);
|
|
105
|
+
return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
|
106
|
+
}
|
|
107
|
+
const red = getRandomIntInclusive(0, 255)
|
|
108
|
+
const green = getRandomIntInclusive(0, 255)
|
|
109
|
+
const blue = getRandomIntInclusive(0, 255)
|
|
110
|
+
const gamut = node.currentHUEDevice !== undefined ? node.currentHUEDevice.color.gamut_type : null
|
|
111
|
+
const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut)
|
|
112
|
+
const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue)
|
|
113
|
+
state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } }
|
|
114
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setLight')
|
|
115
|
+
} catch (error) {
|
|
116
|
+
|
|
105
117
|
}
|
|
106
|
-
const red = getRandomIntInclusive(0, 255)
|
|
107
|
-
const green = getRandomIntInclusive(0, 255)
|
|
108
|
-
const blue = getRandomIntInclusive(0, 255)
|
|
109
|
-
const gamut = node.currentHUEDevice.color.gamut_type || null
|
|
110
|
-
const retXY = hueColorConverter.ColorConverter.rgbToXy(red, green, blue, gamut)
|
|
111
|
-
const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(red, green, blue)
|
|
112
|
-
state = bright > 0 ? { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : { on: { on: false } }
|
|
113
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state)
|
|
114
118
|
}, 10000);
|
|
119
|
+
|
|
115
120
|
} else {
|
|
116
121
|
if (node.timerColorCycle !== undefined) clearInterval(node.timerColorCycle)
|
|
117
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } })
|
|
122
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } }, 'setLight')
|
|
118
123
|
}
|
|
119
124
|
break
|
|
120
125
|
default:
|
|
@@ -144,7 +149,7 @@ module.exports = function (RED) {
|
|
|
144
149
|
node.timerDim = setInterval(() => {
|
|
145
150
|
node.timeoutDim += 1
|
|
146
151
|
if (node.timeoutDim > 100) { node.timeoutDim = 0; clearInterval(node.timerDim) }
|
|
147
|
-
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirection)
|
|
152
|
+
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirection, 'setLight')
|
|
148
153
|
}, 300);
|
|
149
154
|
}
|
|
150
155
|
|
|
@@ -168,10 +173,9 @@ module.exports = function (RED) {
|
|
|
168
173
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
169
174
|
}
|
|
170
175
|
if (_event.hasOwnProperty('color')) {
|
|
171
|
-
if (node.currentHUEDevice === undefined) return
|
|
172
176
|
knxMsgPayload.topic = config.GALightColorState
|
|
173
177
|
knxMsgPayload.dpt = config.dptLightColorState
|
|
174
|
-
knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(_event.color.xy.x, _event.color.xy.y, node.currentHUEDevice.dimming.brightness)
|
|
178
|
+
knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(_event.color.xy.x, _event.color.xy.y, (node.currentHUEDevice !== undefined ? node.currentHUEDevice.dimming.brightness : 100))
|
|
175
179
|
// Send to KNX bus
|
|
176
180
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
177
181
|
}
|
|
@@ -203,26 +207,22 @@ module.exports = function (RED) {
|
|
|
203
207
|
}
|
|
204
208
|
if (node.serverHue) {
|
|
205
209
|
node.serverHue.removeClient(node)
|
|
206
|
-
node.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
//console.log("retrieving node.currentHUEDevice" + node.currentHUEDevice.metadata.name)
|
|
210
|
+
// I must get the light object, to store it in the node.currentHUEDevice variable
|
|
211
|
+
// I queue the state request, by passing the callback to call whenever the HUE bridge send me the light status async
|
|
212
|
+
if (node !== null && node.serverHue !== null && node.serverHue.hueManager !== null) {
|
|
213
|
+
(async () => {
|
|
214
|
+
try {
|
|
215
|
+
await node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, null, 'getLight', (jLight) => {
|
|
216
|
+
node.currentHUEDevice = jLight
|
|
217
|
+
node.serverHue.addClient(node)
|
|
216
218
|
})
|
|
219
|
+
} catch (err) {
|
|
220
|
+
RED.log.error('Errore knxUltimateHueLight node.currentHUEDevice ' + err.message)
|
|
217
221
|
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
}, 5000);
|
|
222
|
-
|
|
222
|
+
})()
|
|
223
|
+
}
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
|
|
226
226
|
node.on('input', function (msg) {
|
|
227
227
|
|
|
228
228
|
})
|
|
@@ -249,7 +249,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
249
249
|
|
|
250
250
|
|Property|Description|
|
|
251
251
|
|--|--|
|
|
252
|
-
| Rotate | This command is used either to send DIM (increase/decrease), aboslute brightness, or a random color, depending on the selected datapoint. |
|
|
252
|
+
| Rotate | This command is used either to send DIM (increase/decrease), aboslute brightness, or a random color, depending on the selected datapoint. If the random color (datapoint 232.600) is selected, **clockwise rotation** changes random colors and **counterclockwise rotation** set the light to **white** |
|
|
253
253
|
|
|
254
254
|
### Outputs
|
|
255
255
|
|
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
module.exports = function (RED) {
|
|
2
2
|
|
|
3
|
-
async function getLightState(node, _lightID) {
|
|
4
|
-
return new Promise((resolve, reject) => {
|
|
5
|
-
try {
|
|
6
|
-
if (node !== null && node.serverHue !== null && node.serverHue.hueManager !== null) {
|
|
7
|
-
node.serverHue.hueManager.getLight(_lightID).then(ret => {
|
|
8
|
-
node.currentHUEDevice = ret[0]
|
|
9
|
-
resolve(ret)
|
|
10
|
-
})
|
|
11
|
-
}
|
|
12
|
-
} catch (error) {
|
|
13
|
-
reject(error)
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
3
|
|
|
18
4
|
function knxUltimateHueTapDial(config) {
|
|
19
5
|
RED.nodes.createNode(this, config)
|
|
@@ -41,14 +27,6 @@ module.exports = function (RED) {
|
|
|
41
27
|
node.brightnessState = 0
|
|
42
28
|
node.isTimerDimStopRunning = false
|
|
43
29
|
|
|
44
|
-
// Read the state of the light and store it in the holding object
|
|
45
|
-
try {
|
|
46
|
-
if (config.hueLight !== undefined && config.hueLight !== '') getLightState(node, config.hueLight)
|
|
47
|
-
} catch (error) {
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
30
|
// Used to call the status update from the config node.
|
|
53
31
|
node.setNodeStatus = ({ fill, shape, text, payload }) => {
|
|
54
32
|
|
|
@@ -58,7 +36,7 @@ module.exports = function (RED) {
|
|
|
58
36
|
const dDate = new Date()
|
|
59
37
|
node.status({ fill: fill, shape: shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
60
38
|
}
|
|
61
|
-
|
|
39
|
+
|
|
62
40
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
63
41
|
node.handleSend = msg => {
|
|
64
42
|
}
|
|
@@ -84,16 +62,20 @@ module.exports = function (RED) {
|
|
|
84
62
|
node.brightnessState < 100 ? node.brightnessState += 20 : node.brightnessState = 100
|
|
85
63
|
knxMsgPayload.payload = node.brightnessState
|
|
86
64
|
} else if (knxMsgPayload.dpt.startsWith('232.600')) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
65
|
+
|
|
66
|
+
if (_event.relative_rotary.last_event.action === 'start') {
|
|
67
|
+
// Random color
|
|
68
|
+
knxMsgPayload.payload = { red: getRandomIntInclusive(0, 255), green: getRandomIntInclusive(0, 255), blue: getRandomIntInclusive(0, 255) }
|
|
69
|
+
function getRandomIntInclusive(min, max) {
|
|
70
|
+
min = Math.ceil(min);
|
|
71
|
+
max = Math.floor(max);
|
|
72
|
+
return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
|
73
|
+
}
|
|
74
|
+
// Send to KNX bus
|
|
75
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
76
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX Change color clockwise' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
93
77
|
}
|
|
94
|
-
|
|
95
|
-
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
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() + ')' })
|
|
78
|
+
|
|
97
79
|
}
|
|
98
80
|
} else if (_event.relative_rotary.last_event.rotation.direction === 'counter_clock_wise') {
|
|
99
81
|
if (knxMsgPayload.dpt.startsWith('3.007')) {
|
|
@@ -108,16 +90,15 @@ module.exports = function (RED) {
|
|
|
108
90
|
node.brightnessState > 0 ? node.brightnessState -= 20 : node.brightnessState = 0
|
|
109
91
|
knxMsgPayload.payload = node.brightnessState
|
|
110
92
|
} else if (knxMsgPayload.dpt.startsWith('232.600')) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
93
|
+
|
|
94
|
+
if (_event.relative_rotary.last_event.action === 'start') {
|
|
95
|
+
// Set white color
|
|
96
|
+
knxMsgPayload.payload = { red: 255, green: 255, blue: 255 }
|
|
97
|
+
// Send to KNX bus
|
|
98
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
99
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX Change color counterclockwise' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
117
100
|
}
|
|
118
|
-
|
|
119
|
-
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
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() + ')' })
|
|
101
|
+
|
|
121
102
|
}
|
|
122
103
|
}
|
|
123
104
|
|
package/nodes/utils/hueUtils.js
CHANGED
|
@@ -75,6 +75,7 @@ class classHUE extends EventEmitter {
|
|
|
75
75
|
console.log('KNXUltimateHUEConfig: classHUE: request.on(error): ' + error.message)
|
|
76
76
|
// Restart the connection
|
|
77
77
|
setTimeout(() => {
|
|
78
|
+
this.commandQueue = []
|
|
78
79
|
req();
|
|
79
80
|
}, 2000);
|
|
80
81
|
});
|
|
@@ -89,19 +90,33 @@ class classHUE extends EventEmitter {
|
|
|
89
90
|
handleQueue = async () => {
|
|
90
91
|
if (this.commandQueue.length > 0) {
|
|
91
92
|
const jRet = this.commandQueue.shift()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
switch (jRet._operation) {
|
|
94
|
+
case 'setLight':
|
|
95
|
+
try {
|
|
96
|
+
const hue = hueApiV2.connect({ host: this.hueBridgeIP, key: this.username })
|
|
97
|
+
const ok = await hue.setLight(jRet._lightID, jRet._state)
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.log('KNXUltimateHUEConfig: classHUE: handleQueue: setLight: ' + error.message)
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case 'getLight':
|
|
103
|
+
try {
|
|
104
|
+
const hue = hueApiV2.connect({ host: this.hueBridgeIP, key: this.username })
|
|
105
|
+
const jReturn = await hue.getLight(jRet._lightID)
|
|
106
|
+
jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.log('KNXUltimateHUEConfig: classHUE: handleQueue: getLight: ' + error.message)
|
|
109
|
+
}
|
|
110
|
+
break
|
|
111
|
+
default:
|
|
112
|
+
break;
|
|
98
113
|
}
|
|
99
114
|
}
|
|
100
115
|
// The Hue bridge allows about 10 telegram per second, so i need to make a queue manager
|
|
101
116
|
setTimeout(this.handleQueue, 100)
|
|
102
117
|
}
|
|
103
|
-
writeHueQueueAdd = async (_lightID, _state) => {
|
|
104
|
-
this.commandQueue.push({ _lightID, _state })
|
|
118
|
+
writeHueQueueAdd = async (_lightID, _state, _operation = 'setLight', _callback) => {
|
|
119
|
+
this.commandQueue.push({ _lightID, _state, _operation, _callback })
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
|
|
@@ -153,15 +168,7 @@ class classHUE extends EventEmitter {
|
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
|
|
156
|
-
|
|
157
|
-
getLight = async (_LightID) => {
|
|
158
|
-
try {
|
|
159
|
-
const hue = hueApiV2.connect({ host: this.hueBridgeIP, key: this.username })
|
|
160
|
-
return await hue.getLight(_LightID)
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.log('KNXUltimateHUEConfig: classHUE: getLight: ' + error.message)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
171
|
+
|
|
165
172
|
|
|
166
173
|
close = async () => {
|
|
167
174
|
return new Promise((resolve, reject) => {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=14.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.1.
|
|
6
|
+
"version": "2.1.6",
|
|
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",
|