node-red-contrib-knx-ultimate 2.0.13 → 2.0.14
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.
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('knxUltimateHueTemperatureSensor', {
|
|
3
|
+
category: "KNX Ultimate",
|
|
4
|
+
color: '#C7E9C0',
|
|
5
|
+
defaults: {
|
|
6
|
+
//buttonState: {value: true},
|
|
7
|
+
server: { type: "knxUltimate-config", required: false },
|
|
8
|
+
serverHue: { type: "hue-config", required: true },
|
|
9
|
+
name: { value: "" },
|
|
10
|
+
|
|
11
|
+
nametemperaturesensor: { value: "" },
|
|
12
|
+
GAtemperaturesensor: { value: "" },
|
|
13
|
+
dpttemperaturesensor: { value: "" },
|
|
14
|
+
|
|
15
|
+
hueDevice: { value: "" }
|
|
16
|
+
},
|
|
17
|
+
inputs: 0,
|
|
18
|
+
outputs: 1,
|
|
19
|
+
icon: "node-hue-icon.svg",
|
|
20
|
+
label: function () {
|
|
21
|
+
return (this.name);
|
|
22
|
+
},
|
|
23
|
+
paletteLabel: "Hue Temperature Sensor (beta)",
|
|
24
|
+
// button: {
|
|
25
|
+
// enabled: function() {
|
|
26
|
+
// // return whether or not the button is enabled, based on the current
|
|
27
|
+
// // configuration of the node
|
|
28
|
+
// return !this.changed
|
|
29
|
+
// },
|
|
30
|
+
// visible: function() {
|
|
31
|
+
// // return whether or not the button is visible, based on the current
|
|
32
|
+
// // configuration of the node
|
|
33
|
+
// return this.hasButton
|
|
34
|
+
// },
|
|
35
|
+
// //toggle: "buttonState",
|
|
36
|
+
// onclick: function() {}
|
|
37
|
+
// },
|
|
38
|
+
oneditprepare: function () {
|
|
39
|
+
var node = this;
|
|
40
|
+
var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
|
|
41
|
+
var oNodeServerHue = RED.nodes.node($("#node-input-serverHue").val()); // Store the config-node
|
|
42
|
+
|
|
43
|
+
// 19/02/2020 Used to get the server sooner als deploy.
|
|
44
|
+
$("#node-input-server").change(function () {
|
|
45
|
+
try {
|
|
46
|
+
oNodeServer = RED.nodes.node($(this).val());
|
|
47
|
+
} catch (error) { }
|
|
48
|
+
});
|
|
49
|
+
// 19/02/2020 Used to get the server sooner als deploy.
|
|
50
|
+
$("#node-input-serverHue").change(function () {
|
|
51
|
+
try {
|
|
52
|
+
oNodeServerHue = RED.nodes.node($(this).val());
|
|
53
|
+
} catch (error) { }
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// 31/03/2020 Search Helper
|
|
57
|
+
function fullSearch(sourceText, searchString) {
|
|
58
|
+
// This searches for all words in a string
|
|
59
|
+
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
60
|
+
var i = 0;
|
|
61
|
+
for (let index = 0; index < aSearchWords.length; index++) {
|
|
62
|
+
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
63
|
+
}
|
|
64
|
+
return i == aSearchWords.length;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// DPT
|
|
68
|
+
// ########################
|
|
69
|
+
$.getJSON('knxUltimateDpts', (data) => {
|
|
70
|
+
data.forEach(dpt => {
|
|
71
|
+
if (dpt.value.startsWith("9.001")) {
|
|
72
|
+
$("#node-input-dpttemperaturesensor").append($("<option></option>")
|
|
73
|
+
.attr("value", dpt.value)
|
|
74
|
+
.text(dpt.text))
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
$("#node-input-dpttemperaturesensor").val(this.dpttemperaturesensor)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Autocomplete suggestion with ETS csv File
|
|
81
|
+
$("#node-input-GAtemperaturesensor").autocomplete({
|
|
82
|
+
minLength: 1,
|
|
83
|
+
source: function (request, response) {
|
|
84
|
+
//$.getJSON("csv", request, function( data, status, xhr ) {
|
|
85
|
+
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
86
|
+
response($.map(data, function (value, key) {
|
|
87
|
+
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
88
|
+
if (fullSearch(sSearch, request.term + " 9.001")) {
|
|
89
|
+
return {
|
|
90
|
+
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
91
|
+
value: value.ga // Value
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
});
|
|
98
|
+
}, select: function (event, ui) {
|
|
99
|
+
// Sets Datapoint and device name automatically
|
|
100
|
+
var sDevName = ui.item.label.split("#")[1].trim();
|
|
101
|
+
try {
|
|
102
|
+
sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
|
|
103
|
+
} catch (error) {
|
|
104
|
+
}
|
|
105
|
+
$('#node-input-nametemperaturesensor').val(sDevName);
|
|
106
|
+
var optVal = $("#node-input-dpttemperaturesensor option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
|
|
107
|
+
// Select the option value
|
|
108
|
+
$("#node-input-dpttemperaturesensor").val(optVal);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// ########################
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
// Autocomplete suggestion with HUE
|
|
117
|
+
$("#node-input-name").autocomplete({
|
|
118
|
+
minLength: 1,
|
|
119
|
+
source: function (request, response) {
|
|
120
|
+
$.getJSON("KNXUltimateGetDevicesHUE?rtype=temperature&nodeID=" + oNodeServerHue.id, (data) => {
|
|
121
|
+
response($.map(data.devices, function (value, key) {
|
|
122
|
+
//alert(JSON.stringify(value) + " "+ key)
|
|
123
|
+
var sSearch = (value.name);
|
|
124
|
+
if (fullSearch(sSearch, request.term)) {
|
|
125
|
+
return {
|
|
126
|
+
hueDevice: value.id, // Label for Display
|
|
127
|
+
value: value.name // Value
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}));
|
|
133
|
+
});
|
|
134
|
+
}, select: function (event, ui) {
|
|
135
|
+
// Sets the fields
|
|
136
|
+
$('#node-input-hueDevice').val(ui.item.hueDevice);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
// ########################
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
},
|
|
145
|
+
oneditsave: function () {
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
},
|
|
149
|
+
oneditcancel: function () {
|
|
150
|
+
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<script type="text/x-red" data-template-name="knxUltimateHueTemperatureSensor">
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
<div class="form-row">
|
|
160
|
+
<b>HUE Light Sensor node</b>  <span style="color:red"
|
|
161
|
+
 <i class="fa fa-question-circle"></i></span>
|
|
162
|
+
 <a target="_blank" href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/en-hue-configuration"><u>Configuration</u></a>
|
|
163
|
+
<br />
|
|
164
|
+
<p align="center"><img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/hueMotion.png'></p>
|
|
165
|
+
<br />
|
|
166
|
+
<label for="node-input-server" >
|
|
167
|
+
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1lAEZyIDYgQXVnIDIwMTAgMjE6NTI6MTkgKzAxMDD84aS8AAAAB3RJTUUH3gYYCicNV+4WIQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACUSURBVHjaY2CgFZg5c+Z/ZEyWAZ8+f/6/ZsWs/xoamqMGkGrA6Wla/1+fVARjEBuGsSoGmY4eZSCNL59d/g8DIDbIAHR14OgFGQByKjIGKX5+6/T///8gGMQGiV1+/B0Fg70GIkD+RMYgxf/O5/7//2MSmAZhkBi6OrgB6Bg5DGB4ajr3f2xqsYYLSDE2THJUDg0AAAqyDVd4tp4YAAAAAElFTkSuQmCC"></img>
|
|
168
|
+
KNX GW
|
|
169
|
+
</label>
|
|
170
|
+
<input type="text" id="node-input-server" />
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="form-row">
|
|
174
|
+
<label for="node-input-serverHue">
|
|
175
|
+
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEKADAAQAAAABAAAAEAAAAAA0VXHyAAABFUlEQVQ4EZWSsWoCQRCG1yiENEFEi6QSkjqWWoqFoBYJ+Br6JHkMn8Iibd4ihQpaJIhWNkry/ZtdGZY78Qa+m39nZ+dm9s4550awglNBluS/gVtAX6KgDclf68w2OThgfR9iT/jnoEv4TtByDThWTCDKW4SSZTf/zj9/eZbN+izTDuKGimu0vPF8B/YN8aC8LmcOj/AAn9CFTEs70Js/oGqy79C69bqJ5XbQI2kGO5N8QL9D08S8zBtBF5ZaVsznpCMoqJnVdjTpb1Db0fwIWmQV6BLXzFOYgA6/gDVfQN9bBWp2J2hdWDPoBV5FrKnAJutHikk/CHHR8i7x4iG7qQ720IYvu3GFbpHjx3pFrOFYkA354z/5bkK826phyAAAAABJRU5ErkJggg=="/>
|
|
176
|
+
HUE Bridge
|
|
177
|
+
</label>
|
|
178
|
+
<input type="text" id="node-input-serverHue" />
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<br/>
|
|
182
|
+
<p>
|
|
183
|
+
<b>Philips HUE</b>
|
|
184
|
+
</p>
|
|
185
|
+
|
|
186
|
+
<div class="form-row">
|
|
187
|
+
<label for="node-input-hueDevice" >
|
|
188
|
+
<i class="fa fa-play-circle"></i> Hue Sensor</label>
|
|
189
|
+
<input type="text" id="node-input-name" placeholder="Enter your hue device name" />
|
|
190
|
+
<input type="hidden" id="node-input-hueDevice" />
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<br/>
|
|
194
|
+
|
|
195
|
+
<p>
|
|
196
|
+
<b>PHILIPS HUE LIGHT EVENTS -> TO KNX</b>
|
|
197
|
+
</p>
|
|
198
|
+
|
|
199
|
+
<div class="form-row">
|
|
200
|
+
<label for="node-input-nametemperaturesensor" style="width:100px;"><i class="fa fa-play-circle-o"></i> Lux</span></label>
|
|
201
|
+
|
|
202
|
+
<label for="node-input-GAtemperaturesensor" style="width:20px;">GA</label>
|
|
203
|
+
<input type="text" id="node-input-GAtemperaturesensor" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
|
|
204
|
+
|
|
205
|
+
<label for="node-input-dpttemperaturesensor" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
|
|
206
|
+
<select id="node-input-dpttemperaturesensor" style="width:140px;"></select>
|
|
207
|
+
|
|
208
|
+
<label for="node-input-nametemperaturesensor" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
|
|
209
|
+
<input type="text" id="node-input-nametemperaturesensor" style="width:200px;margin-left: 5px; text-align: left;">
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
<br/>
|
|
216
|
+
<br/>
|
|
217
|
+
<br/>
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
<script type="text/markdown" data-help-name="knxUltimateHueTemperatureSensor">
|
|
223
|
+
<p> This node lets you get the events from your HUE motion device.<br/>
|
|
224
|
+
|
|
225
|
+
Here you can get the HUE Light Sensors light events, that represents a lux value, evetytime the ambient light changes.<br/>
|
|
226
|
+
Start typing in the GA field, the name or group address of your KNX device, the avaiable devices start showing up while you're typing.
|
|
227
|
+
|
|
228
|
+
**General**
|
|
229
|
+
|Property|Description|
|
|
230
|
+
|--|--|
|
|
231
|
+
| KNX GW | Select the KNX gateway to be used |
|
|
232
|
+
| HUE Bridge | Select the HUE Bridge to be used |
|
|
233
|
+
| Hue Sensor | HUE sensor to be used. The avaiable buttons start showing up while you're typing.|
|
|
234
|
+
|
|
235
|
+
**PHILIPS HUE LIGHT EVENTS -> TO KNX**
|
|
236
|
+
|Property|Description|
|
|
237
|
+
|--|--|
|
|
238
|
+
| Lux | Lux value |
|
|
239
|
+
|
|
240
|
+
### Outputs
|
|
241
|
+
|
|
242
|
+
1. Standard output
|
|
243
|
+
: payload (integer) : the standard output of the command.
|
|
244
|
+
|
|
245
|
+
### Details
|
|
246
|
+
|
|
247
|
+
`msg.payload` is used as the payload of the published message.
|
|
248
|
+
It contains the detailed event sent by your Hue devicem so you can use it for whatever you want.
|
|
249
|
+
|
|
250
|
+
<br/>
|
|
251
|
+
|
|
252
|
+
[Find it useful?](https://www.paypal.me/techtoday)
|
|
253
|
+
|
|
254
|
+
<br/>
|
|
255
|
+
|
|
256
|
+
</script>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function knxUltimateHueLightSensor(config) {
|
|
5
|
+
RED.nodes.createNode(this, config)
|
|
6
|
+
const node = this
|
|
7
|
+
node.server = RED.nodes.getNode(config.server)
|
|
8
|
+
node.serverHue = RED.nodes.getNode(config.serverHue)
|
|
9
|
+
node.topic = node.name
|
|
10
|
+
node.name = config.name === undefined ? 'Hue' : config.name
|
|
11
|
+
node.dpt = ''
|
|
12
|
+
node.notifyreadrequest = false
|
|
13
|
+
node.notifyreadrequestalsorespondtobus = 'false'
|
|
14
|
+
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
|
|
15
|
+
node.notifyresponse = false
|
|
16
|
+
node.notifywrite = true
|
|
17
|
+
node.initialread = true
|
|
18
|
+
node.listenallga = true // Don't remove
|
|
19
|
+
node.outputtype = 'write'
|
|
20
|
+
node.outputRBE = false // Apply or not RBE to the output (Messages coming from flow)
|
|
21
|
+
node.inputRBE = false // Apply or not RBE to the input (Messages coming from BUS)
|
|
22
|
+
node.currentPayload = '' // Current value for the RBE input and for the .previouspayload msg
|
|
23
|
+
node.passthrough = 'no'
|
|
24
|
+
node.formatmultiplyvalue = 1
|
|
25
|
+
node.formatnegativevalue = 'leave'
|
|
26
|
+
node.formatdecimalsvalue = 2
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
// Used to call the status update from the config node.
|
|
31
|
+
node.setNodeStatus = ({ fill, shape, text, payload }) => {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
36
|
+
node.handleSend = msg => {
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
node.handleSendHUE = _event => {
|
|
40
|
+
try {
|
|
41
|
+
if (_event.id === config.hueDevice) {
|
|
42
|
+
const knxMsgPayload = {}
|
|
43
|
+
knxMsgPayload.topic = config.GAlightsensor
|
|
44
|
+
knxMsgPayload.dpt = config.dptlightsensor
|
|
45
|
+
|
|
46
|
+
if (_event.hasOwnProperty('light') && _event.light.hasOwnProperty('light_level')) {
|
|
47
|
+
knxMsgPayload.payload = Math.round(10 ** ((_event.light.light_level - 1) / 10000))
|
|
48
|
+
// Send to KNX bus
|
|
49
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
50
|
+
node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
51
|
+
|
|
52
|
+
// Setup the output msg
|
|
53
|
+
knxMsgPayload.name = node.name
|
|
54
|
+
knxMsgPayload.event = 'light_level'
|
|
55
|
+
|
|
56
|
+
// Send payload
|
|
57
|
+
knxMsgPayload.rawEvent = _event
|
|
58
|
+
node.send(knxMsgPayload)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// On each deploy, unsubscribe+resubscribe
|
|
67
|
+
if (node.server) {
|
|
68
|
+
node.server.removeClient(node)
|
|
69
|
+
node.server.addClient(node)
|
|
70
|
+
}
|
|
71
|
+
if (node.serverHue) {
|
|
72
|
+
node.serverHue.removeClient(node)
|
|
73
|
+
node.serverHue.addClient(node)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
node.on('input', function (msg) {
|
|
77
|
+
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
node.on('close', function (done) {
|
|
81
|
+
if (node.server) {
|
|
82
|
+
node.server.removeClient(node)
|
|
83
|
+
}
|
|
84
|
+
done()
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
RED.nodes.registerType('knxUltimateHueLightSensor', knxUltimateHueLightSensor)
|
|
88
|
+
}
|
package/nodes/utils/hueUtils.js
CHANGED
|
@@ -48,7 +48,10 @@ class classHUE extends EventEmitter {
|
|
|
48
48
|
if (_rtype === 'light_level') {
|
|
49
49
|
retArray.push({ name: 'Light Level: ' + linkedDevName + (Room !== undefined ? ', room ' + Room.metadata.name : ''), id: device.id })
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
if (_rtype === 'temperature') {
|
|
52
|
+
retArray.push({ name: 'Temp: ' + linkedDevName + (Room !== undefined ? ', room ' + Room.metadata.name : ''), id: device.id })
|
|
53
|
+
}
|
|
54
|
+
|
|
52
55
|
})
|
|
53
56
|
return { devices: retArray }
|
|
54
57
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=14.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.14",
|
|
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",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"knxUltimateHueButton": "/nodes/knxUltimateHueButton.js",
|
|
38
38
|
"knxUltimateHueMotion": "/nodes/knxUltimateHueMotion.js",
|
|
39
39
|
"knxUltimateHueTapDial": "/nodes/knxUltimateHueTapDial.js",
|
|
40
|
-
"knxUltimateHueLightSensor": "/nodes/knxUltimateHueLightSensor.js"
|
|
40
|
+
"knxUltimateHueLightSensor": "/nodes/knxUltimateHueLightSensor.js",
|
|
41
|
+
"knxUltimateHueTemperatureSensor": "/nodes/knxUltimateHueTemperatureSensor.js"
|
|
41
42
|
}
|
|
42
43
|
},
|
|
43
44
|
"repository": {
|