node-red-contrib-knx-ultimate 2.1.18 → 2.1.20
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 +10 -2
- package/KNXEngine/src/KNXClient.js +5 -5
- package/nodes/knxUltimate-config.js +8 -3
- package/nodes/knxUltimateHueButton.js +46 -36
- package/nodes/knxUltimateHueLight.html +96 -47
- package/nodes/knxUltimateHueLight.js +67 -52
- package/nodes/knxUltimateHueLightSensor.js +3 -2
- package/nodes/knxUltimateHueMotion.js +3 -2
- package/nodes/knxUltimateHueScene.js +3 -2
- package/nodes/knxUltimateHueTapDial.js +9 -7
- 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,19 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
<p>
|
|
10
|
+
<b>Version 2.1.20</b> - July 2023<br/>
|
|
11
|
+
- NEW: Hue Light: you can choose to enable/disable the day/night behaviour.<br/>
|
|
12
|
+
- NEW: Hue Light: you can now choose some options in the new Behaviours configuration tab.<br/>
|
|
13
|
+
</p>
|
|
14
|
+
<p>
|
|
15
|
+
<b>Version 2.1.19</b> - July 2023<br/>
|
|
16
|
+
- Hue light and Hue button optimization.<br/>
|
|
17
|
+
</p>
|
|
18
|
+
<p>
|
|
9
19
|
<p>
|
|
10
20
|
<b>Version 2.1.18</b> - July 2023<br/>
|
|
11
21
|
- 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
22
|
</p>
|
|
15
23
|
<p>
|
|
16
24
|
<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: 'green', 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: 'green', 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: 'blue', 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: 'blue', 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
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
GALightColorCycle: { value: "" },
|
|
53
53
|
dptLightColorCycle: { value: "" },
|
|
54
54
|
|
|
55
|
+
enableDayNightLightning: { value: false },
|
|
55
56
|
colorAtSwitchOnDayTime: { value: '{"red":255, "green":255, "blue":255}' },
|
|
56
57
|
colorAtSwitchOnNightTime: { value: '{"red":23, "green":4, "blue":0}' },
|
|
57
58
|
invertDayNight: { value: false },
|
|
@@ -60,6 +61,9 @@
|
|
|
60
61
|
GADaylightSensor: { value: "" },
|
|
61
62
|
dptDaylightSensor: { value: "" },
|
|
62
63
|
|
|
64
|
+
updateSwitchStatusOnBrightness: { value: "no" },
|
|
65
|
+
updateBrightnessOnSwitchStatus: { value: "no" },
|
|
66
|
+
|
|
63
67
|
hueDevice: { value: "" }
|
|
64
68
|
},
|
|
65
69
|
inputs: 0,
|
|
@@ -661,7 +665,19 @@
|
|
|
661
665
|
});
|
|
662
666
|
// ########################
|
|
663
667
|
|
|
664
|
-
|
|
668
|
+
// Show/Hide and enable/disable day/night lightning behaviour
|
|
669
|
+
if (this.enableDayNightLightning === true) {
|
|
670
|
+
$("#DivEnableDayNightLightning").show()
|
|
671
|
+
} else {
|
|
672
|
+
$("#DivEnableDayNightLightning").hide()
|
|
673
|
+
}
|
|
674
|
+
$("#node-input-enableDayNightLightning").on('change', function () {
|
|
675
|
+
if ($("#node-input-enableDayNightLightning").is(":checked")) {
|
|
676
|
+
$("#DivEnableDayNightLightning").show()
|
|
677
|
+
} else {
|
|
678
|
+
$("#DivEnableDayNightLightning").hide()
|
|
679
|
+
}
|
|
680
|
+
})
|
|
665
681
|
|
|
666
682
|
// Autocomplete suggestion with HUE Lights
|
|
667
683
|
$("#node-input-name").autocomplete({
|
|
@@ -750,11 +766,12 @@
|
|
|
750
766
|
|
|
751
767
|
<div id="tabs">
|
|
752
768
|
<ul>
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
769
|
+
<li><a href="#tabs-1">Switching</a></li>
|
|
770
|
+
<li><a href="#tabs-2">Dim/Brightness</a></li>
|
|
771
|
+
<li><a href="#tabs-3">Tunable white</a></li>
|
|
772
|
+
<li><a href="#tabs-4">Colors</a></li>
|
|
773
|
+
<li><a href="#tabs-5">Effects</a></li>
|
|
774
|
+
<li><a href="#tabs-6">Behaviour</a></li>
|
|
758
775
|
</ul>
|
|
759
776
|
<div id="tabs-1">
|
|
760
777
|
<p>
|
|
@@ -781,40 +798,47 @@
|
|
|
781
798
|
|
|
782
799
|
<label for="node-input-nameLightState" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
|
|
783
800
|
<input type="text" id="node-input-nameLightState" style="width:200px;margin-left: 5px; text-align: left;">
|
|
784
|
-
</div>
|
|
785
|
-
|
|
801
|
+
</div>
|
|
786
802
|
<div class="form-row">
|
|
787
|
-
<label
|
|
788
|
-
|
|
789
|
-
<label for="node-input-GADaylightSensor" style="width:20px;">GA</label>
|
|
790
|
-
<input type="text" id="node-input-GADaylightSensor" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
|
|
791
|
-
|
|
792
|
-
<label for="node-input-dptDaylightSensor" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
|
|
793
|
-
<select id="node-input-dptDaylightSensor" style="width:140px;"></select>
|
|
794
|
-
|
|
795
|
-
<label for="node-input-nameDaylightSensor" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
|
|
796
|
-
<input type="text" id="node-input-nameDaylightSensor" style="width:200px;margin-left: 5px; text-align: left;">
|
|
797
|
-
</div>
|
|
798
|
-
<div class="form-row">
|
|
799
|
-
<label for="node-input-invertDayNight">
|
|
803
|
+
<label style="width:150px" for="node-input-enableDayNightLightning">
|
|
804
|
+
<i class="fa fa-clone"></i> Day/Night lightning
|
|
800
805
|
</label>
|
|
801
|
-
<input type="checkbox" id="node-input-
|
|
802
|
-
|
|
803
|
-
|
|
806
|
+
<input type="checkbox" id="node-input-enableDayNightLightning" style="display:inline-block; width:auto; vertical-align:top;" />
|
|
807
|
+
</div>
|
|
808
|
+
<div id="DivEnableDayNightLightning">
|
|
809
|
+
<div class="form-row">
|
|
810
|
+
<label for="node-input-nameDaylightSensor" style="width:100px;"><i class="fa fa-clock-o"></i> Day/Night</label>
|
|
804
811
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
812
|
+
<label for="node-input-GADaylightSensor" style="width:20px;">GA</label>
|
|
813
|
+
<input type="text" id="node-input-GADaylightSensor" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
|
|
814
|
+
|
|
815
|
+
<label for="node-input-dptDaylightSensor" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
|
|
816
|
+
<select id="node-input-dptDaylightSensor" style="width:140px;"></select>
|
|
817
|
+
|
|
818
|
+
<label for="node-input-nameDaylightSensor" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
|
|
819
|
+
<input type="text" id="node-input-nameDaylightSensor" style="width:200px;margin-left: 5px; text-align: left;">
|
|
820
|
+
</div>
|
|
821
|
+
<div class="form-row">
|
|
822
|
+
<label style="width:170px" for="node-input-invertDayNight">
|
|
823
|
+
<i class="fa fa-shuffle"></i> Invert day/night values
|
|
824
|
+
</label>
|
|
825
|
+
<input type="checkbox" id="node-input-invertDayNight" style="display:inline-block; width:auto; vertical-align:top;" />
|
|
826
|
+
|
|
827
|
+
</div>
|
|
828
|
+
|
|
829
|
+
<div class="form-row">
|
|
830
|
+
<label for="node-input-colorAtSwitchOnDayTime" style="width:200px">
|
|
831
|
+
<i class="fa fa-sun-o"></i> Switch on color at Daytime
|
|
832
|
+
</label>
|
|
833
|
+
<input type="text" id="node-input-colorAtSwitchOnDayTime" placeholder='{"red":255, "green":255, "blue":255}' style="width:250px">
|
|
834
|
+
</div>
|
|
835
|
+
<div class="form-row">
|
|
836
|
+
<label for="node-input-colorAtSwitchOnNightTime" style="width:200px">
|
|
837
|
+
<i class="fa fa-moon-o"></i> Switch on color at Nighttime
|
|
838
|
+
</label>
|
|
839
|
+
<input type="text" id="node-input-colorAtSwitchOnNightTime" placeholder='{"red":100, "green":0, "blue":50}' style="width:250px">
|
|
840
|
+
</div>
|
|
816
841
|
</div>
|
|
817
|
-
|
|
818
842
|
</p>
|
|
819
843
|
</div>
|
|
820
844
|
<div id="tabs-2">
|
|
@@ -928,7 +952,7 @@
|
|
|
928
952
|
|
|
929
953
|
<label for="node-input-nameLightBlink" style="width:50px; margin-left: 0px; text-align: right;"><span data-i18n="knxUltimateHueLight.node-input-name"></span></label>
|
|
930
954
|
<input type="text" id="node-input-nameLightBlink" style="width:200px;margin-left: 5px; text-align: left;">
|
|
931
|
-
|
|
955
|
+
</div>
|
|
932
956
|
|
|
933
957
|
<div class="form-row">
|
|
934
958
|
<label for="node-input-nameLightColorCycle" style="width:100px;"><i class="fa fa-play-circle-o"></i> Color Cycle</label>
|
|
@@ -944,11 +968,25 @@
|
|
|
944
968
|
</div>
|
|
945
969
|
</p>
|
|
946
970
|
</div>
|
|
947
|
-
|
|
971
|
+
|
|
972
|
+
<div id="tabs-6">
|
|
973
|
+
<p>
|
|
974
|
+
<br/>
|
|
975
|
+
<b> HUE to KNX</b>
|
|
976
|
+
<div class="form-row">
|
|
977
|
+
<label for="node-input-updateSwitchStatusOnBrightness" style="width:50%;">
|
|
978
|
+
<i class="fa fa-tag"></i> Update Switch Status on brightness change
|
|
979
|
+
</label>
|
|
980
|
+
<select id="node-input-updateSwitchStatusOnBrightness">
|
|
981
|
+
<option value="no">No</option>
|
|
982
|
+
<option value="yes">Yes</option>
|
|
983
|
+
</select>
|
|
984
|
+
</div>
|
|
985
|
+
</p>
|
|
986
|
+
</div>
|
|
948
987
|
<br/>
|
|
949
988
|
</script>
|
|
950
989
|
|
|
951
|
-
|
|
952
990
|
<script type="text/markdown" data-help-name="knxUltimateHueLight">
|
|
953
991
|
<p>This node lets you control your Philips HUE light and also get the states of this lights, to be sent to the KNX bus.</p>
|
|
954
992
|
|
|
@@ -970,15 +1008,16 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
970
1008
|
|Property|Description|
|
|
971
1009
|
|--|--|
|
|
972
1010
|
| Switch | This GA is used to turn on/off the HUE light via a boolean KNX value true/false|
|
|
973
|
-
| Switch Status| Link this to the light's switch status group address|
|
|
974
|
-
| Day/Night |
|
|
975
|
-
|
|
|
976
|
-
|
|
|
977
|
-
| Switch on color at
|
|
1011
|
+
| Switch Status | Link this to the light's switch status group address|
|
|
1012
|
+
| Day/Night lightning | It allows to set a particular light color/brightness based on daytime and 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*. If **unchecked**, the light behaviour and brightness/color values remain unchanged. |
|
|
1013
|
+
| Day/Night | Select the group address used to set the day/night behaviour. The group address value is *true* if daytime, *false* if nighttime. |
|
|
1014
|
+
| Invert day/night values | Invert the values of *Day/Night* group address. Default value is **unchecked**.|
|
|
1015
|
+
| Switch on color at Daytime | You can choose the color/brightness of your light, at switch on, on night time. Set it as JSON object. Default value is **{ "red": 255, "green": 255, "blue": 255 }** |
|
|
1016
|
+
| Switch on color at Nighttime | You can choose the color/brightness of your light, at switch on, on night time. Set it as JSON object. Default value is **{ "red": 100, "green": 0, "blue": 0 }** |
|
|
978
1017
|
|
|
979
1018
|
<br/>
|
|
980
1019
|
|
|
981
|
-
**
|
|
1020
|
+
**Dim/Brightness**
|
|
982
1021
|
|Property|Description|
|
|
983
1022
|
|--|--|
|
|
984
1023
|
| Dimming | Relative DIM the HUE light |
|
|
@@ -1006,8 +1045,18 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
1006
1045
|
**Effects**
|
|
1007
1046
|
|Property|Description|
|
|
1008
1047
|
|--|--|
|
|
1009
|
-
| Blink| *true* Blink the light, *false* Stop blinking. Blinks the light on and off. Useful for signalling. Works with all HUE lights. |
|
|
1010
|
-
| 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. |
|
|
1048
|
+
| Blink | *true* Blink the light, *false* Stop blinking. Blinks the light on and off. Useful for signalling. Works with all HUE lights. |
|
|
1049
|
+
| 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. |
|
|
1050
|
+
|
|
1051
|
+
<br/>
|
|
1052
|
+
|
|
1053
|
+
**Behaviour**
|
|
1054
|
+
|
|
1055
|
+
HUE to KNX
|
|
1056
|
+
|
|
1057
|
+
|Property|Description|
|
|
1058
|
+
|--|--|
|
|
1059
|
+
| Update Switch Status on brightness change | It updates the *Switch Status* group address on every brightness change. If the brighness is > 0, it sends *true*, otherwise, *false*. Default value is **No**. |
|
|
1011
1060
|
|
|
1012
1061
|
<br/>
|
|
1013
1062
|
|
|
@@ -35,29 +35,34 @@ 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
|
|
|
43
|
-
// This function is called by the
|
|
44
|
+
// This function is called by the hue-config.js
|
|
44
45
|
node.handleSend = msg => {
|
|
45
46
|
let state = {}
|
|
46
47
|
try {
|
|
47
48
|
switch (msg.knx.destination) {
|
|
48
49
|
case config.GALightSwitch:
|
|
49
50
|
msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
|
|
50
|
-
if (msg.payload) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
if (msg.payload === true) {
|
|
52
|
+
if (config.enableDayNightLightning === true) {
|
|
53
|
+
let jColorChoosen = { red: 255, green: 255, blue: 255 }
|
|
54
|
+
if (node.DayTime) {
|
|
55
|
+
jColorChoosen = JSON.parse(config.colorAtSwitchOnDayTime || '{ "red": 255, "green": 255, "blue": 255 }')
|
|
56
|
+
} else {
|
|
57
|
+
jColorChoosen = JSON.parse(config.colorAtSwitchOnNightTime || '{ "red": 255, "green": 255, "blue": 255 }')
|
|
58
|
+
}
|
|
59
|
+
let dgamut = node.currentHUEDevice !== undefined ? node.currentHUEDevice.color.gamut_type : null
|
|
60
|
+
let dretXY = hueColorConverter.ColorConverter.rgbToXy(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue, dgamut)
|
|
61
|
+
let dbright = hueColorConverter.ColorConverter.getBrightnessFromRGB(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue)
|
|
62
|
+
state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
|
|
54
63
|
} else {
|
|
55
|
-
|
|
64
|
+
state = { on: { on: true } }
|
|
56
65
|
}
|
|
57
|
-
let dgamut = node.currentHUEDevice !== undefined ? node.currentHUEDevice.color.gamut_type : null
|
|
58
|
-
let dretXY = hueColorConverter.ColorConverter.rgbToXy(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue, dgamut)
|
|
59
|
-
let dbright = hueColorConverter.ColorConverter.getBrightnessFromRGB(jColorChoosen.red, jColorChoosen.green, jColorChoosen.blue)
|
|
60
|
-
state = dbright > 0 ? { on: { on: true }, dimming: { brightness: dbright }, color: { xy: dretXY } } : { on: { on: false } }
|
|
61
66
|
} else {
|
|
62
67
|
state = { on: { on: false } }
|
|
63
68
|
}
|
|
@@ -171,8 +176,11 @@ module.exports = function (RED) {
|
|
|
171
176
|
node.dimDirection = {}
|
|
172
177
|
node.timeoutDim = 0
|
|
173
178
|
node.startDimStopper = function (_direction) {
|
|
179
|
+
node.timeoutDim = 0
|
|
174
180
|
if (node.timerDim !== undefined) clearInterval(node.timerDim)
|
|
175
|
-
if (_direction === 'stop')
|
|
181
|
+
if (_direction === 'stop') {
|
|
182
|
+
return
|
|
183
|
+
}
|
|
176
184
|
switch (_direction) {
|
|
177
185
|
case 'up':
|
|
178
186
|
node.dimDirection = { dimming_delta: { action: 'up', brightness_delta: 10 } }
|
|
@@ -185,16 +193,18 @@ module.exports = function (RED) {
|
|
|
185
193
|
}
|
|
186
194
|
node.timerDim = setInterval(() => {
|
|
187
195
|
node.timeoutDim += 1
|
|
188
|
-
if (node.timeoutDim >
|
|
196
|
+
if (node.timeoutDim > 150) { node.timeoutDim = 0; clearInterval(node.timerDim) }
|
|
189
197
|
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirection, 'setLight')
|
|
190
|
-
},
|
|
198
|
+
}, 700)
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
// Start dimming tunable white
|
|
194
202
|
// mirek: required(integer – minimum: 153 – maximum: 500)
|
|
195
203
|
node.timerDimTunableWhite = undefined
|
|
196
204
|
node.dimDirectionTunableWhite = {}
|
|
205
|
+
node.timeoutDimTunableWhite = 0
|
|
197
206
|
node.startDimStopperTunableWhite = function (_direction) {
|
|
207
|
+
node.timeoutDimTunableWhite = 0
|
|
198
208
|
if (node.timerDimTunableWhite !== undefined) clearInterval(node.timerDimTunableWhite)
|
|
199
209
|
if (_direction === 'stop') return
|
|
200
210
|
switch (_direction) {
|
|
@@ -208,9 +218,10 @@ module.exports = function (RED) {
|
|
|
208
218
|
break
|
|
209
219
|
}
|
|
210
220
|
node.timerDimTunableWhite = setInterval(() => {
|
|
221
|
+
node.timeoutDimTunableWhite += 1
|
|
222
|
+
if (node.timeoutDimTunableWhite > 150) { node.timeoutDimTunableWhite = 0; clearInterval(node.timerDimTunableWhite) }
|
|
211
223
|
node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, node.dimDirectionTunableWhite, 'setLight')
|
|
212
|
-
},
|
|
213
|
-
|
|
224
|
+
}, 700)
|
|
214
225
|
}
|
|
215
226
|
|
|
216
227
|
node.handleSendHUE = _event => {
|
|
@@ -218,49 +229,53 @@ module.exports = function (RED) {
|
|
|
218
229
|
if (_event.id === config.hueDevice) {
|
|
219
230
|
const knxMsgPayload = {}
|
|
220
231
|
if (_event.hasOwnProperty('on')) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
knxMsgPayload.dpt = config.dptLightBrightnessState
|
|
229
|
-
knxMsgPayload.payload = _event.on.on === true ? 100 : 0
|
|
230
|
-
// Send to KNX bus
|
|
231
|
-
//if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
232
|
+
if (config.GALightState !== undefined && config.GALightState !== '') {
|
|
233
|
+
knxMsgPayload.topic = config.GALightState
|
|
234
|
+
knxMsgPayload.dpt = config.dptLightState
|
|
235
|
+
knxMsgPayload.payload = _event.on.on
|
|
236
|
+
// Send to KNX bus
|
|
237
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
238
|
+
}
|
|
232
239
|
}
|
|
233
240
|
if (_event.hasOwnProperty('color')) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
241
|
+
if (config.GALightColorState !== undefined && config.GALightColorState !== '') {
|
|
242
|
+
knxMsgPayload.topic = config.GALightColorState
|
|
243
|
+
knxMsgPayload.dpt = config.dptLightColorState
|
|
244
|
+
knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(_event.color.xy.x, _event.color.xy.y, (node.currentHUEDevice !== undefined ? node.currentHUEDevice.dimming.brightness : 100))
|
|
245
|
+
// Send to KNX bus
|
|
246
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
247
|
+
}
|
|
239
248
|
}
|
|
240
249
|
if (_event.hasOwnProperty('dimming')) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
if (config.GALightBrightnessState !== undefined && config.GALightBrightnessState !== '') {
|
|
251
|
+
knxMsgPayload.topic = config.GALightBrightnessState
|
|
252
|
+
knxMsgPayload.dpt = config.dptLightBrightnessState
|
|
253
|
+
knxMsgPayload.payload = _event.dimming.brightness
|
|
254
|
+
// Send to KNX bus
|
|
255
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
256
|
+
|
|
257
|
+
if (config.updateSwitchStatusOnBrightness === 'yes') {
|
|
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
|
+
}
|
|
265
|
+
|
|
266
|
+
}
|
|
252
267
|
}
|
|
253
268
|
if (_event.hasOwnProperty('color_temperature')) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
if (config.GALightHSVState !== undefined && config.GALightHSVState !== '') {
|
|
270
|
+
knxMsgPayload.topic = config.GALightHSVState
|
|
271
|
+
knxMsgPayload.dpt = config.dptLightHSVState
|
|
272
|
+
if (config.dptLightHSVState === '5.001') {
|
|
273
|
+
const retPercent = hueColorConverter.ColorConverter.scale(_event.color_temperature.mirek, [153, 500], [0, 100])
|
|
274
|
+
knxMsgPayload.payload = 100 - retPercent
|
|
275
|
+
}
|
|
276
|
+
// Send to KNX bus
|
|
277
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
261
278
|
}
|
|
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
279
|
}
|
|
265
280
|
node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX State', payload: knxMsgPayload.payload })
|
|
266
281
|
}
|
|
@@ -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.
|
|
@@ -51,7 +52,7 @@ module.exports = function (RED) {
|
|
|
51
52
|
if (knxMsgPayload.dpt.startsWith('3.007')) {
|
|
52
53
|
if (node.isTimerDimStopRunning === false) {
|
|
53
54
|
// Set KNX Dim up/down start
|
|
54
|
-
knxMsgPayload.payload = { decr_incr: 1, data:
|
|
55
|
+
knxMsgPayload.payload = { decr_incr: 1, data: 5 } // Send to KNX bus
|
|
55
56
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
56
57
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX start Dim' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
57
58
|
}
|
|
@@ -78,7 +79,7 @@ module.exports = function (RED) {
|
|
|
78
79
|
if (knxMsgPayload.dpt.startsWith('3.007')) {
|
|
79
80
|
if (node.isTimerDimStopRunning === false) {
|
|
80
81
|
// Set KNX Dim up/down start
|
|
81
|
-
knxMsgPayload.payload = { decr_incr: 0, data:
|
|
82
|
+
knxMsgPayload.payload = { decr_incr: 0, data: 5 } // Send to KNX bus
|
|
82
83
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
83
84
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX start Dim' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
84
85
|
}
|
|
@@ -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() + ')' })
|
|
@@ -111,16 +112,17 @@ module.exports = function (RED) {
|
|
|
111
112
|
|
|
112
113
|
// Timer to stop the dimming sequence
|
|
113
114
|
node.startDimStopper = function (knxMsgPayload) {
|
|
114
|
-
if (node.timerDimStop !== undefined)
|
|
115
|
+
if (node.timerDimStop !== undefined) clearTimeout(node.timerDimStop)
|
|
115
116
|
node.isTimerDimStopRunning = true
|
|
116
117
|
node.timerDimStop = setTimeout(() => {
|
|
118
|
+
console.log("Stop banana")
|
|
117
119
|
// KNX Stop DIM
|
|
118
120
|
knxMsgPayload.payload = { decr_incr: 0, data: 0 } // Payload for the output msg
|
|
119
121
|
// Send to KNX bus
|
|
120
122
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
121
123
|
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX Stop DIM' + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
122
124
|
node.isTimerDimStopRunning = false
|
|
123
|
-
},
|
|
125
|
+
}, 1500)
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
// On each deploy, unsubscribe+resubscribe
|
|
@@ -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.20",
|
|
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",
|