node-red-contrib-knx-ultimate 2.1.18 → 2.1.19
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 +5 -2
- package/KNXEngine/src/KNXClient.js +5 -5
- package/nodes/knxUltimate-config.js +8 -3
- package/nodes/knxUltimateHueButton.js +46 -36
- package/nodes/knxUltimateHueLight.js +55 -42
- package/nodes/knxUltimateHueLightSensor.js +3 -2
- package/nodes/knxUltimateHueMotion.js +3 -2
- package/nodes/knxUltimateHueScene.js +3 -2
- package/nodes/knxUltimateHueTapDial.js +4 -3
- package/nodes/knxUltimateHueTemperatureSensor.js +4 -3
- package/nodes/utils/hueUtils.js +4 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
<p>
|
|
10
|
+
<b>Version 2.1.19</b> - July 2023<br/>
|
|
11
|
+
- Hue light and Hue button optimization.<br/>
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
9
14
|
<p>
|
|
10
15
|
<b>Version 2.1.18</b> - July 2023<br/>
|
|
11
16
|
- Quick fix for MDT and Wienzler interfaces.<br/>
|
|
12
|
-
- HUE light: added "invert" option to the Day/Night sensor.<br/>
|
|
13
|
-
- More verbose status for all nodes.<br/>
|
|
14
17
|
</p>
|
|
15
18
|
<p>
|
|
16
19
|
<b>Version 2.1.17</b> - July 2023<br/>
|
|
@@ -139,7 +139,7 @@ class KNXClient extends EventEmitter {
|
|
|
139
139
|
this._clientSocket.bind({ port: null, address: this._options.localIPAddress }, function () {
|
|
140
140
|
try {
|
|
141
141
|
conn._clientSocket.setTTL(250)
|
|
142
|
-
|
|
142
|
+
if (conn._options.localSocketAddress === undefined) conn._options.localSocketAddress = conn._clientSocket.address()
|
|
143
143
|
} catch (error) {
|
|
144
144
|
if (conn.sysLogger !== undefined && conn.sysLogger !== null) conn.sysLogger.error('UDP: Error setting SetTTL ' + error.message || '')
|
|
145
145
|
}
|
|
@@ -325,7 +325,7 @@ class KNXClient extends EventEmitter {
|
|
|
325
325
|
cEMIMessage.control.broadcast = 1
|
|
326
326
|
cEMIMessage.control.priority = 3
|
|
327
327
|
cEMIMessage.control.addressType = 1
|
|
328
|
-
cEMIMessage.control.hopCount = 6
|
|
328
|
+
cEMIMessage.control.hopCount = 6
|
|
329
329
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXRoutingIndication(cEMIMessage)
|
|
330
330
|
this.send(knxPacketRequest)
|
|
331
331
|
// 06/12/2021 Multivast automaticalli echoes telegrams
|
|
@@ -337,7 +337,7 @@ class KNXClient extends EventEmitter {
|
|
|
337
337
|
cEMIMessage.control.broadcast = 1
|
|
338
338
|
cEMIMessage.control.priority = 3
|
|
339
339
|
cEMIMessage.control.addressType = 1
|
|
340
|
-
cEMIMessage.control.hopCount =
|
|
340
|
+
cEMIMessage.control.hopCount = 6
|
|
341
341
|
const seqNum = this._incSeqNumber() // 26/12/2021
|
|
342
342
|
const knxPacketRequest = KNXProtocol.KNXProtocol.newKNXTunnelingRequest(this._channelID, seqNum, cEMIMessage)
|
|
343
343
|
if (!this._options.suppress_ack_ldatareq) this._setTimerWaitingForACK(knxPacketRequest)
|
|
@@ -1003,11 +1003,11 @@ class KNXClient extends EventEmitter {
|
|
|
1003
1003
|
_sendConnectRequestMessage(cri) {
|
|
1004
1004
|
// try {
|
|
1005
1005
|
// const oHPAI = new HPAI.HPAI(this._options.localSocketAddress.address, this._options.localSocketAddress.port, this._options.hostProtocol === 'TunnelTCP' ? KNXConstants.KNX_CONSTANTS.IPV4_TCP : KNXConstants.KNX_CONSTANTS.IPV4_UDP)
|
|
1006
|
-
// this.send(KNXProtocol.KNXProtocol.newKNXConnectRequest(cri,
|
|
1006
|
+
// this.send(KNXProtocol.KNXProtocol.newKNXConnectRequest(cri, null, oHPAI))
|
|
1007
1007
|
// } catch (error) {
|
|
1008
1008
|
// this.send(KNXProtocol.KNXProtocol.newKNXConnectRequest(cri))
|
|
1009
1009
|
// }
|
|
1010
|
-
|
|
1010
|
+
this.send(KNXProtocol.KNXProtocol.newKNXConnectRequest(cri))
|
|
1011
1011
|
}
|
|
1012
1012
|
|
|
1013
1013
|
_sendConnectionStateRequestMessage(channelID) {
|
|
@@ -171,9 +171,14 @@ return msg;`,
|
|
|
171
171
|
|
|
172
172
|
node.setAllClientsStatus = (_status, _color, _text) => {
|
|
173
173
|
function nextStatus(_oClient) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
try {
|
|
175
|
+
let oClient = RED.nodes.getNode(_oClient.id)
|
|
176
|
+
oClient.setNodeStatus({ fill: _color, shape: 'dot', text: _status + ' ' + _text, payload: '', GA: oClient.topic, dpt: '', devicename: '' })
|
|
177
|
+
oClient = null
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.warn('Wow setAllClientsStatus error ' + error.message)
|
|
180
|
+
}
|
|
181
|
+
|
|
177
182
|
}
|
|
178
183
|
node.nodeClients.map(nextStatus)
|
|
179
184
|
}
|
|
@@ -33,9 +33,10 @@ module.exports = function (RED) {
|
|
|
33
33
|
}
|
|
34
34
|
// Used to call the status update from the HUE config node.
|
|
35
35
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
36
|
+
if (payload === undefined) return
|
|
36
37
|
const dDate = new Date()
|
|
37
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
38
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
38
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
39
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -46,24 +47,18 @@ module.exports = function (RED) {
|
|
|
46
47
|
case config.GAshort_releaseStatus:
|
|
47
48
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptshort_release))
|
|
48
49
|
node.short_releaseValue = msg.payload
|
|
49
|
-
|
|
50
|
-
node.status({ fill: 'blue', shape: 'dot', text: 'Updated Switch ' + msg.knx.destination + ' ' + JSON.stringify(msg.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
51
|
-
}, 500)
|
|
52
|
-
node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: msg.payload })
|
|
50
|
+
node.setNodeStatusHue({ fill: 'blue', shape: 'dot', text: 'KNX->HUE Short Release Status', payload: msg.payload })
|
|
53
51
|
break
|
|
54
52
|
case config.GArepeatStatus:
|
|
55
53
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptrepeat))
|
|
56
54
|
node.toggleGArepeat = msg.payload.decr_incr === 1
|
|
57
|
-
|
|
58
|
-
node.status({ fill: 'blue', shape: 'dot', text: 'Updated Dim ' + msg.knx.destination + ' ' + JSON.stringify(msg.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
59
|
-
}, 500)
|
|
60
|
-
node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: msg.payload })
|
|
55
|
+
node.setNodeStatusHue({ fill: 'blue', shape: 'dot', text: 'KNX->HUE Repeat Status', payload: msg.payload })
|
|
61
56
|
break
|
|
62
57
|
default:
|
|
63
58
|
break
|
|
64
59
|
}
|
|
65
60
|
} catch (error) {
|
|
66
|
-
node.
|
|
61
|
+
node.setNodeStatusHue({ fill: 'red', shape: 'dot', text: 'KNX->HUE error ' + error.message, payload: '' })
|
|
67
62
|
}
|
|
68
63
|
}
|
|
69
64
|
|
|
@@ -84,6 +79,12 @@ module.exports = function (RED) {
|
|
|
84
79
|
break
|
|
85
80
|
case 'long_release':
|
|
86
81
|
flowMsgPayload = node.long_pressValue
|
|
82
|
+
// if the dimmer was running, send the STOP telegram to the KNX bus wires, using the GArepeat Group address and dpt.
|
|
83
|
+
if (node.isTimerDimStopRunning) {
|
|
84
|
+
knxMsgPayload.topic = config.GArepeat
|
|
85
|
+
knxMsgPayload.dpt = config.dptrepeat
|
|
86
|
+
node.stopDIM(knxMsgPayload)
|
|
87
|
+
}
|
|
87
88
|
break
|
|
88
89
|
case 'double_short_release':
|
|
89
90
|
if (node.double_short_releaseValue === undefined) node.double_short_releaseValue = false
|
|
@@ -98,25 +99,29 @@ module.exports = function (RED) {
|
|
|
98
99
|
case 'short_release':
|
|
99
100
|
node.short_releaseValue = config.toggleValues ? !node.short_releaseValue : true
|
|
100
101
|
flowMsgPayload = node.short_releaseValue
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
if (config.GAshort_release !== undefined && config.GAshort_release !== '') {
|
|
103
|
+
knxMsgPayload.topic = config.GAshort_release
|
|
104
|
+
knxMsgPayload.dpt = config.dptshort_release
|
|
105
|
+
knxMsgPayload.payload = node.short_releaseValue
|
|
106
|
+
// Send to KNX bus
|
|
107
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
108
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + _event.button.last_event, payload: knxMsgPayload.payload })
|
|
109
|
+
}
|
|
107
110
|
break
|
|
108
111
|
case 'repeat':
|
|
109
112
|
flowMsgPayload = true
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
if (config.GArepeat !== undefined && config.GArepeat !== '') {
|
|
114
|
+
if (node.isTimerDimStopRunning === false) {
|
|
115
|
+
// Set KNX Dim up/down start
|
|
116
|
+
knxMsgPayload.topic = config.GArepeat
|
|
117
|
+
knxMsgPayload.dpt = config.dptrepeat
|
|
118
|
+
knxMsgPayload.payload = node.long_pressValue ? { decr_incr: 0, data: 3 } : { decr_incr: 1, data: 3 } // If the light is turned on, the initial DIM direction must be down, otherwise, up
|
|
119
|
+
// Send to KNX bus
|
|
120
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
121
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'HUE->KNX START DIM', payload: '' })
|
|
122
|
+
}
|
|
123
|
+
node.startDimStopper(knxMsgPayload)
|
|
118
124
|
}
|
|
119
|
-
node.startDimStopper(knxMsgPayload)
|
|
120
125
|
break
|
|
121
126
|
default:
|
|
122
127
|
break
|
|
@@ -129,25 +134,30 @@ module.exports = function (RED) {
|
|
|
129
134
|
flowMsg.rawEvent = _event
|
|
130
135
|
flowMsg.payload = flowMsgPayload
|
|
131
136
|
node.send(flowMsg)
|
|
132
|
-
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: flowMsg.payload })
|
|
137
|
+
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: flowMsg.rawEvent + ' ' + flowMsg.payload })
|
|
133
138
|
}
|
|
134
139
|
} catch (error) {
|
|
135
|
-
node.
|
|
140
|
+
node.setNodeStatusHue({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message, payload: '' })
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
// Timer to stop the dimming sequence
|
|
140
145
|
node.startDimStopper = function (knxMsgPayload) {
|
|
141
|
-
if (node.timerDimStop !== undefined)
|
|
146
|
+
if (node.timerDimStop !== undefined) clearTimeout(node.timerDimStop)
|
|
142
147
|
node.isTimerDimStopRunning = true
|
|
143
148
|
node.timerDimStop = setTimeout(() => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
node.stopDIM(knxMsgPayload)
|
|
150
|
+
}, 2000)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
node.stopDIM = function (knxMsgPayload) {
|
|
154
|
+
// KNX Stop DIM
|
|
155
|
+
if (node.timerDimStop !== undefined) clearTimeout(node.timerDimStop)
|
|
156
|
+
node.isTimerDimStopRunning = false
|
|
157
|
+
knxMsgPayload.payload = { decr_incr: 0, data: 0 } // Payload for the output msg
|
|
158
|
+
// Send to KNX bus
|
|
159
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
160
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.setNodeStatusHue({ fill: 'grey', shape: 'ring', text: 'HUE->KNX STOP DIM', payload: knxMsgPayload.payload })
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
// On each deploy, unsubscribe+resubscribe
|
|
@@ -35,8 +35,9 @@ module.exports = function (RED) {
|
|
|
35
35
|
}
|
|
36
36
|
// Used to call the status update from the HUE config node.
|
|
37
37
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
38
|
+
if (payload === undefined) return
|
|
38
39
|
const dDate = new Date()
|
|
39
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
40
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
40
41
|
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -171,8 +172,11 @@ module.exports = function (RED) {
|
|
|
171
172
|
node.dimDirection = {}
|
|
172
173
|
node.timeoutDim = 0
|
|
173
174
|
node.startDimStopper = function (_direction) {
|
|
175
|
+
node.timeoutDim = 0
|
|
174
176
|
if (node.timerDim !== undefined) clearInterval(node.timerDim)
|
|
175
|
-
if (_direction === 'stop')
|
|
177
|
+
if (_direction === 'stop') {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
176
180
|
switch (_direction) {
|
|
177
181
|
case 'up':
|
|
178
182
|
node.dimDirection = { dimming_delta: { action: 'up', brightness_delta: 10 } }
|
|
@@ -185,16 +189,18 @@ module.exports = function (RED) {
|
|
|
185
189
|
}
|
|
186
190
|
node.timerDim = setInterval(() => {
|
|
187
191
|
node.timeoutDim += 1
|
|
188
|
-
if (node.timeoutDim >
|
|
192
|
+
if (node.timeoutDim > 150) { node.timeoutDim = 0; clearInterval(node.timerDim) }
|
|
189
193
|
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirection, 'setLight')
|
|
190
|
-
},
|
|
194
|
+
}, 700)
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
// Start dimming tunable white
|
|
194
198
|
// mirek: required(integer – minimum: 153 – maximum: 500)
|
|
195
199
|
node.timerDimTunableWhite = undefined
|
|
196
200
|
node.dimDirectionTunableWhite = {}
|
|
201
|
+
node.timeoutDimTunableWhite = 0
|
|
197
202
|
node.startDimStopperTunableWhite = function (_direction) {
|
|
203
|
+
node.timeoutDimTunableWhite = 0
|
|
198
204
|
if (node.timerDimTunableWhite !== undefined) clearInterval(node.timerDimTunableWhite)
|
|
199
205
|
if (_direction === 'stop') return
|
|
200
206
|
switch (_direction) {
|
|
@@ -208,9 +214,10 @@ module.exports = function (RED) {
|
|
|
208
214
|
break
|
|
209
215
|
}
|
|
210
216
|
node.timerDimTunableWhite = setInterval(() => {
|
|
217
|
+
node.timeoutDimTunableWhite += 1
|
|
218
|
+
if (node.timeoutDimTunableWhite > 150) { node.timeoutDimTunableWhite = 0; clearInterval(node.timerDimTunableWhite) }
|
|
211
219
|
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirectionTunableWhite, 'setLight')
|
|
212
|
-
},
|
|
213
|
-
|
|
220
|
+
}, 700)
|
|
214
221
|
}
|
|
215
222
|
|
|
216
223
|
node.handleSendHUE = _event => {
|
|
@@ -218,49 +225,55 @@ module.exports = function (RED) {
|
|
|
218
225
|
if (_event.id === config.hueDevice) {
|
|
219
226
|
const knxMsgPayload = {}
|
|
220
227
|
if (_event.hasOwnProperty('on')) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
if (config.GALightState !== undefined && config.GALightState !== '') {
|
|
229
|
+
knxMsgPayload.topic = config.GALightState
|
|
230
|
+
knxMsgPayload.dpt = config.dptLightState
|
|
231
|
+
knxMsgPayload.payload = _event.on.on
|
|
232
|
+
// Send to KNX bus
|
|
233
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
234
|
+
// ISE Connect Hue emulation, send brightness
|
|
235
|
+
knxMsgPayload.topic = config.GALightBrightnessState
|
|
236
|
+
knxMsgPayload.dpt = config.dptLightBrightnessState
|
|
237
|
+
knxMsgPayload.payload = _event.on.on === true ? 100 : 0
|
|
238
|
+
// Send to KNX bus
|
|
239
|
+
//if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
240
|
+
}
|
|
232
241
|
}
|
|
233
242
|
if (_event.hasOwnProperty('color')) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
243
|
+
if (config.GALightColorState !== undefined && config.GALightColorState !== '') {
|
|
244
|
+
knxMsgPayload.topic = config.GALightColorState
|
|
245
|
+
knxMsgPayload.dpt = config.dptLightColorState
|
|
246
|
+
knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(_event.color.xy.x, _event.color.xy.y, (node.currentHUEDevice !== undefined ? node.currentHUEDevice.dimming.brightness : 100))
|
|
247
|
+
// Send to KNX bus
|
|
248
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
249
|
+
}
|
|
239
250
|
}
|
|
240
251
|
if (_event.hasOwnProperty('dimming')) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
if (config.GALightBrightnessState !== undefined && config.GALightBrightnessState !== '') {
|
|
253
|
+
knxMsgPayload.topic = config.GALightBrightnessState
|
|
254
|
+
knxMsgPayload.dpt = config.dptLightBrightnessState
|
|
255
|
+
knxMsgPayload.payload = _event.dimming.brightness
|
|
256
|
+
// Send to KNX bus
|
|
257
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
258
|
+
// ISE Connect Hue emulation, send true/false to switch state
|
|
259
|
+
knxMsgPayload.topic = config.GALightState
|
|
260
|
+
knxMsgPayload.dpt = config.dptLightState
|
|
261
|
+
knxMsgPayload.payload = _event.dimming.brightness > 0
|
|
262
|
+
// Send to KNX bus
|
|
263
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
264
|
+
}
|
|
252
265
|
}
|
|
253
266
|
if (_event.hasOwnProperty('color_temperature')) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
267
|
+
if (config.GALightHSVState !== undefined && config.GALightHSVState !== '') {
|
|
268
|
+
knxMsgPayload.topic = config.GALightHSVState
|
|
269
|
+
knxMsgPayload.dpt = config.dptLightHSVState
|
|
270
|
+
if (config.dptLightHSVState === '5.001') {
|
|
271
|
+
const retPercent = hueColorConverter.ColorConverter.scale(_event.color_temperature.mirek, [153, 500], [0, 100])
|
|
272
|
+
knxMsgPayload.payload = 100 - retPercent
|
|
273
|
+
}
|
|
274
|
+
// Send to KNX bus
|
|
275
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
261
276
|
}
|
|
262
|
-
// Send to KNX bus
|
|
263
|
-
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
264
277
|
}
|
|
265
278
|
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX State', payload: knxMsgPayload.payload })
|
|
266
279
|
}
|
|
@@ -29,9 +29,10 @@ module.exports = function (RED) {
|
|
|
29
29
|
}
|
|
30
30
|
// Used to call the status update from the HUE config node.
|
|
31
31
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
32
|
+
if (payload === undefined) return
|
|
32
33
|
const dDate = new Date()
|
|
33
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
34
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
34
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
35
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -29,9 +29,10 @@ module.exports = function (RED) {
|
|
|
29
29
|
}
|
|
30
30
|
// Used to call the status update from the HUE config node.
|
|
31
31
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
32
|
+
if (payload === undefined) return
|
|
32
33
|
const dDate = new Date()
|
|
33
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
34
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
34
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
35
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -31,9 +31,10 @@ module.exports = function (RED) {
|
|
|
31
31
|
}
|
|
32
32
|
// Used to call the status update from the HUE config node.
|
|
33
33
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
34
|
+
if (payload === undefined) return
|
|
34
35
|
const dDate = new Date()
|
|
35
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
36
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
36
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
37
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
// This function is called by the knx-hue config node
|
|
@@ -31,9 +31,10 @@ module.exports = function (RED) {
|
|
|
31
31
|
}
|
|
32
32
|
// Used to call the status update from the HUE config node.
|
|
33
33
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
34
|
+
if (payload === undefined) return
|
|
34
35
|
const dDate = new Date()
|
|
35
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
36
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
36
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
37
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -102,7 +103,7 @@ module.exports = function (RED) {
|
|
|
102
103
|
knxMsgPayload.event = 'rotation ' + _event.relative_rotary.last_event.rotation.direction
|
|
103
104
|
knxMsgPayload.payload = _event
|
|
104
105
|
node.send(knxMsgPayload)
|
|
105
|
-
node.setNodeStatusHue({ fill: 'blue', shape: '
|
|
106
|
+
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload })
|
|
106
107
|
}
|
|
107
108
|
} catch (error) {
|
|
108
109
|
node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
@@ -29,9 +29,10 @@ module.exports = function (RED) {
|
|
|
29
29
|
}
|
|
30
30
|
// Used to call the status update from the HUE config node.
|
|
31
31
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
32
|
+
if (payload === undefined) return
|
|
32
33
|
const dDate = new Date()
|
|
33
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
34
|
-
node.status({ fill, shape, text: text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
34
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
|
|
35
|
+
node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -58,7 +59,7 @@ module.exports = function (RED) {
|
|
|
58
59
|
// Send payload
|
|
59
60
|
knxMsgPayload.rawEvent = _event
|
|
60
61
|
node.send(knxMsgPayload)
|
|
61
|
-
node.setNodeStatusHue({ fill: 'blue', shape: '
|
|
62
|
+
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload })
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
} catch (error) {
|
package/nodes/utils/hueUtils.js
CHANGED
|
@@ -203,7 +203,7 @@ class classHUE extends EventEmitter {
|
|
|
203
203
|
const linkedLight = allResources.find(res => res.id === jScene.group.rid).children || ''
|
|
204
204
|
linkedLight.forEach(light => {
|
|
205
205
|
this.writeHueQueueAdd(light.rid, jRet._state, 'setLight')
|
|
206
|
-
});
|
|
206
|
+
});
|
|
207
207
|
} catch (error) {
|
|
208
208
|
console.log('KNXUltimateHUEConfig: classHUE: handleQueue: stopScene: ' + error.message)
|
|
209
209
|
}
|
|
@@ -213,10 +213,11 @@ class classHUE extends EventEmitter {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
// The Hue bridge allows about 10 telegram per second, so i need to make a queue manager
|
|
216
|
-
setTimeout(this.handleQueue,
|
|
216
|
+
setTimeout(this.handleQueue, 100)
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
writeHueQueueAdd = async (_lightID, _state, _operation, _callback) => {
|
|
220
|
+
// Add the new item
|
|
220
221
|
this.commandQueue.push({ _lightID, _state, _operation, _callback })
|
|
221
222
|
}
|
|
222
223
|
// ######################################
|
|
@@ -284,7 +285,7 @@ class classHUE extends EventEmitter {
|
|
|
284
285
|
this.es = null;
|
|
285
286
|
setTimeout(() => {
|
|
286
287
|
resolve(true)
|
|
287
|
-
},
|
|
288
|
+
}, 500)
|
|
288
289
|
} catch (error) {
|
|
289
290
|
reject(error)
|
|
290
291
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.1.
|
|
6
|
+
"version": "2.1.19",
|
|
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",
|