node-red-contrib-knx-ultimate 2.4.5-beta.2 → 2.4.5-beta.3
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 +19 -9
- package/nodes/knxUltimateHueBattery.js +1 -1
- package/nodes/knxUltimateHueLightSensor.js +1 -1
- package/nodes/knxUltimateHueScene.html +1 -1
- package/nodes/knxUltimateHueTemperatureSensor.js +1 -1
- package/nodes/knxUltimateHueZigbeeConnectivity.html +267 -0
- package/nodes/knxUltimateHueZigbeeConnectivity.js +134 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 2.4.5-beta.3 PUBLIC BETA** - Feb 2024<br/>
|
|
10
|
+
- HUE: Fixed "read at startup" option, not working for some HUE nodes.<br/>
|
|
11
|
+
- NEW: HUE: added node Zigbee Connectivity.<br/>
|
|
12
|
+
|
|
9
13
|
**Version 2.4.5-beta.2 PUBLIC BETA** - Feb 2024<br/>
|
|
10
14
|
- Fix the listing of ethernet interfaces in the gateway config window.<br/>
|
|
11
15
|
|
package/nodes/hue-config.js
CHANGED
|
@@ -123,13 +123,6 @@ module.exports = (RED) => {
|
|
|
123
123
|
node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
|
|
124
124
|
if (node.hueAllResources !== undefined) {
|
|
125
125
|
node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
|
|
126
|
-
|
|
127
|
-
// Get zigbee_connectivituy
|
|
128
|
-
// const bridgeId = node.hueAllResources.filter((a) => a.bridge_id === config.bridgeid).owner.rid;
|
|
129
|
-
// const zigbee_ConnectivityID = node.hueAllResources.filter((a) => a.id === bridgeId).services.filter((a) => a.rtype === "zigbee_connectivity").rid;
|
|
130
|
-
// // connected, disconnected, connectivity_issue, unidirectional_incoming
|
|
131
|
-
// const oZigbeeConnectivityStatus = node.hueAllResources.filter((a) => a.id === zigbee_ConnectivityID).status;
|
|
132
|
-
|
|
133
126
|
// Update all KNX State of the nodes with the new hue device values
|
|
134
127
|
node.nodeClients.forEach((_node) => {
|
|
135
128
|
if (_node.hueDevice !== undefined && node.hueAllResources !== undefined) {
|
|
@@ -139,10 +132,12 @@ module.exports = (RED) => {
|
|
|
139
132
|
_node.setNodeStatusHue({
|
|
140
133
|
fill: "green",
|
|
141
134
|
shape: "ring",
|
|
142
|
-
text: "Ready
|
|
135
|
+
text: "Ready",
|
|
143
136
|
});
|
|
144
137
|
_node.currentHUEDevice = cloneDeep(oHUEDevice); // Copy by Value and not by ref
|
|
145
|
-
if (_node.initializingAtStart === true)
|
|
138
|
+
if (_node.initializingAtStart === true) {
|
|
139
|
+
_node.handleSendHUE(oHUEDevice); // Pass by value
|
|
140
|
+
}
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
143
|
});
|
|
@@ -307,6 +302,21 @@ module.exports = (RED) => {
|
|
|
307
302
|
id: resource.id,
|
|
308
303
|
});
|
|
309
304
|
}
|
|
305
|
+
if (_rtype === "zigbee_connectivity") {
|
|
306
|
+
const Room = node.hueAllRooms.find((room) => room.children.find((child) => child.rid === resource.owner.rid));
|
|
307
|
+
const linkedDevName = node.hueAllResources.find((dev) => dev.type === "device" && dev.services.find((serv) => serv.rid === resource.id)).metadata.name || "";
|
|
308
|
+
retArray.push({
|
|
309
|
+
name: `Zigbee Connectivity: ${linkedDevName}${Room !== undefined ? `, room ${Room.metadata.name}` : ""}`,
|
|
310
|
+
id: resource.id,
|
|
311
|
+
});
|
|
312
|
+
// Get zigbee_connectivituy
|
|
313
|
+
// const bridgeId = node.hueAllResources.filter((a) => a.bridge_id === config.bridgeid).owner.rid;
|
|
314
|
+
// const zigbee_ConnectivityID = node.hueAllResources.filter((a) => a.id === bridgeId).services.filter((a) => a.rtype === "zigbee_connectivity").rid;
|
|
315
|
+
// // connected, disconnected, connectivity_issue, unidirectional_incoming
|
|
316
|
+
// const oZigbeeConnectivityStatus = node.hueAllResources.filter((a) => a.id === zigbee_ConnectivityID).status;
|
|
317
|
+
//const zigbee = node.hueAllResources.filter((a) => a.services !== undefined).find((a) => a.services.rtype === "zigbee_connectivity");
|
|
318
|
+
//const devs = zigbee.filter((a) => a.rtype === "zigbee_connectivity");
|
|
319
|
+
}
|
|
310
320
|
} catch (error) {
|
|
311
321
|
retArray.push({
|
|
312
322
|
name: `${_rtype}: ERROR ${error.message}`,
|
|
@@ -23,7 +23,7 @@ module.exports = function (RED) {
|
|
|
23
23
|
node.formatnegativevalue = 'leave';
|
|
24
24
|
node.formatdecimalsvalue = 2;
|
|
25
25
|
node.hueDevice = config.hueDevice;
|
|
26
|
-
node.initializingAtStart =
|
|
26
|
+
node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes");
|
|
27
27
|
node.currentDeviceValue = 0;
|
|
28
28
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
@@ -23,7 +23,7 @@ module.exports = function (RED) {
|
|
|
23
23
|
node.formatnegativevalue = 'leave';
|
|
24
24
|
node.formatdecimalsvalue = 2;
|
|
25
25
|
node.hueDevice = config.hueDevice;
|
|
26
|
-
node.initializingAtStart =
|
|
26
|
+
node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes");
|
|
27
27
|
node.currentDeviceValue = 0;
|
|
28
28
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
if (Number(this.selectedModeTabNumber) === 0) return this.name;
|
|
43
43
|
if (Number(this.selectedModeTabNumber) === 1) return this.namesceneMulti;
|
|
44
44
|
},
|
|
45
|
-
paletteLabel: "Hue Scene
|
|
45
|
+
paletteLabel: "Hue Scene",
|
|
46
46
|
// button: {
|
|
47
47
|
// enabled: function() {
|
|
48
48
|
// // return whether or not the button is enabled, based on the current
|
|
@@ -23,7 +23,7 @@ module.exports = function (RED) {
|
|
|
23
23
|
node.formatnegativevalue = 'leave';
|
|
24
24
|
node.formatdecimalsvalue = 2;
|
|
25
25
|
node.hueDevice = config.hueDevice;
|
|
26
|
-
node.initializingAtStart =
|
|
26
|
+
node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes");
|
|
27
27
|
node.currentDeviceValue = 0;
|
|
28
28
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/11f26b4500.js"></script>
|
|
2
|
+
|
|
3
|
+
<script type="text/javascript">
|
|
4
|
+
RED.nodes.registerType('knxUltimateHueZigbeeConnectivity', {
|
|
5
|
+
category: "KNX Ultimate",
|
|
6
|
+
color: '#C0C7E9',
|
|
7
|
+
defaults: {
|
|
8
|
+
//buttonState: {value: true},
|
|
9
|
+
server: { type: "knxUltimate-config", required: false },
|
|
10
|
+
serverHue: { type: "hue-config", required: true },
|
|
11
|
+
name: { value: "" },
|
|
12
|
+
|
|
13
|
+
namezigbeeconnectivity: { value: "" },
|
|
14
|
+
GAzigbeeconnectivity: { value: "" },
|
|
15
|
+
dptzigbeeconnectivity: { value: "" },
|
|
16
|
+
readStatusAtStartup: { value: "yes" },
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
hueDevice: { value: "" }
|
|
20
|
+
},
|
|
21
|
+
inputs: 0,
|
|
22
|
+
outputs: 1,
|
|
23
|
+
icon: "node-hue-icon.svg",
|
|
24
|
+
label: function () {
|
|
25
|
+
return (this.name);
|
|
26
|
+
},
|
|
27
|
+
paletteLabel: "Hue Zigbee Connectivity",
|
|
28
|
+
// button: {
|
|
29
|
+
// enabled: function() {
|
|
30
|
+
// // return whether or not the button is enabled, based on the current
|
|
31
|
+
// // configuration of the node
|
|
32
|
+
// return !this.changed
|
|
33
|
+
// },
|
|
34
|
+
// visible: function() {
|
|
35
|
+
// // return whether or not the button is visible, based on the current
|
|
36
|
+
// // configuration of the node
|
|
37
|
+
// return this.hasButton
|
|
38
|
+
// },
|
|
39
|
+
// //toggle: "buttonState",
|
|
40
|
+
// onclick: function() {}
|
|
41
|
+
// },
|
|
42
|
+
oneditprepare: function () {
|
|
43
|
+
var node = this;
|
|
44
|
+
var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
|
|
45
|
+
var oNodeServerHue = RED.nodes.node($("#node-input-serverHue").val()); // Store the config-node
|
|
46
|
+
|
|
47
|
+
// 19/02/2020 Used to get the server sooner als deploy.
|
|
48
|
+
$("#node-input-server").change(function () {
|
|
49
|
+
try {
|
|
50
|
+
oNodeServer = RED.nodes.node($(this).val());
|
|
51
|
+
} catch (error) { }
|
|
52
|
+
});
|
|
53
|
+
// 19/02/2020 Used to get the server sooner als deploy.
|
|
54
|
+
$("#node-input-serverHue").change(function () {
|
|
55
|
+
try {
|
|
56
|
+
oNodeServerHue = RED.nodes.node($(this).val());
|
|
57
|
+
} catch (error) { }
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 31/03/2020 Search Helper
|
|
61
|
+
function fullSearch(sourceText, searchString) {
|
|
62
|
+
// This searches for all words in a string
|
|
63
|
+
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
64
|
+
var i = 0;
|
|
65
|
+
for (let index = 0; index < aSearchWords.length; index++) {
|
|
66
|
+
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
67
|
+
}
|
|
68
|
+
return i == aSearchWords.length;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// DPT
|
|
72
|
+
// ########################
|
|
73
|
+
$.getJSON('knxUltimateDpts?serverId=' + $("#node-input-server").val(), (data) => {
|
|
74
|
+
data.forEach(dpt => {
|
|
75
|
+
if (dpt.value.startsWith("1.")) {
|
|
76
|
+
$("#node-input-dptzigbeeconnectivity").append($("<option></option>")
|
|
77
|
+
.attr("value", dpt.value)
|
|
78
|
+
.text(dpt.text))
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
$("#node-input-dptzigbeeconnectivity").val(this.dptzigbeeconnectivity)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Autocomplete suggestion with ETS csv File
|
|
85
|
+
$("#node-input-GAzigbeeconnectivity").autocomplete({
|
|
86
|
+
minLength: 1,
|
|
87
|
+
source: function (request, response) {
|
|
88
|
+
//$.getJSON("csv", request, function( data, status, xhr ) {
|
|
89
|
+
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
90
|
+
response($.map(data, function (value, key) {
|
|
91
|
+
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
92
|
+
if (fullSearch(sSearch, request.term + " 1.")) {
|
|
93
|
+
return {
|
|
94
|
+
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
95
|
+
value: value.ga // Value
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}));
|
|
101
|
+
});
|
|
102
|
+
}, select: function (event, ui) {
|
|
103
|
+
// Sets Datapoint and device name automatically
|
|
104
|
+
var sDevName = ui.item.label.split("#")[1].trim();
|
|
105
|
+
try {
|
|
106
|
+
sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
|
|
107
|
+
} catch (error) {
|
|
108
|
+
}
|
|
109
|
+
$('#node-input-namezigbeeconnectivity').val(sDevName);
|
|
110
|
+
var optVal = $("#node-input-dptzigbeeconnectivity option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
|
|
111
|
+
// Select the option value
|
|
112
|
+
$("#node-input-dptzigbeeconnectivity").val(optVal);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
// ########################
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
// Autocomplete suggestion with HUE
|
|
121
|
+
$("#node-input-name").autocomplete({
|
|
122
|
+
minLength: 1,
|
|
123
|
+
source: function (request, response) {
|
|
124
|
+
$.getJSON("KNXUltimateGetResourcesHUE?rtype=zigbee_connectivity&serverId=" + oNodeServerHue.id, (data) => {
|
|
125
|
+
response($.map(data.devices, function (value, key) {
|
|
126
|
+
//alert(JSON.stringify(value) + " "+ key)
|
|
127
|
+
var sSearch = (value.name);
|
|
128
|
+
if (fullSearch(sSearch, request.term)) {
|
|
129
|
+
return {
|
|
130
|
+
hueDevice: value.id, // Label for Display
|
|
131
|
+
value: value.name // Value
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}));
|
|
137
|
+
});
|
|
138
|
+
}, select: function (event, ui) {
|
|
139
|
+
// Sets the fields
|
|
140
|
+
$('#node-input-hueDevice').val(ui.item.hueDevice);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
// ########################
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
},
|
|
149
|
+
oneditsave: function () {
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
},
|
|
153
|
+
oneditcancel: function () {
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
</script>
|
|
159
|
+
|
|
160
|
+
<script type="text/html" data-template-name="knxUltimateHueZigbeeConnectivity">
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
<div class="form-row">
|
|
164
|
+
<b>HUE Zigbee Connectivity node</b>  <span style="color:red"
|
|
165
|
+
 
|
|
166
|
+
 <i class="fa fa-youtube"></i></span> <a target="_blank" href="https://youtu.be/jjEUI1J8bkA"><u>Youtube sample</u></a>
|
|
167
|
+
<br />
|
|
168
|
+
<br />
|
|
169
|
+
<p align="center">
|
|
170
|
+
<i class="fa-solid fa-tower-broadcast fa-beat fa-4x"></i>
|
|
171
|
+
</p>
|
|
172
|
+
<br />
|
|
173
|
+
<label for="node-input-server" >
|
|
174
|
+
<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>
|
|
175
|
+
KNX GW
|
|
176
|
+
</label>
|
|
177
|
+
<input type="text" id="node-input-server" />
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<div class="form-row">
|
|
181
|
+
<label for="node-input-serverHue">
|
|
182
|
+
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEKADAAQAAAABAAAAEAAAAAA0VXHyAAABFUlEQVQ4EZWSsWoCQRCG1yiENEFEi6QSkjqWWoqFoBYJ+Br6JHkMn8Iibd4ihQpaJIhWNkry/ZtdGZY78Qa+m39nZ+dm9s4550awglNBluS/gVtAX6KgDclf68w2OThgfR9iT/jnoEv4TtByDThWTCDKW4SSZTf/zj9/eZbN+izTDuKGimu0vPF8B/YN8aC8LmcOj/AAn9CFTEs70Js/oGqy79C69bqJ5XbQI2kGO5N8QL9D08S8zBtBF5ZaVsznpCMoqJnVdjTpb1Db0fwIWmQV6BLXzFOYgA6/gDVfQN9bBWp2J2hdWDPoBV5FrKnAJutHikk/CHHR8i7x4iG7qQ720IYvu3GFbpHjx3pFrOFYkA354z/5bkK826phyAAAAABJRU5ErkJggg=="/>
|
|
183
|
+
HUE Bridge
|
|
184
|
+
</label>
|
|
185
|
+
<input type="text" id="node-input-serverHue" />
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<br/>
|
|
189
|
+
<p>
|
|
190
|
+
<b>Philips HUE</b>
|
|
191
|
+
</p>
|
|
192
|
+
|
|
193
|
+
<div class="form-row">
|
|
194
|
+
<label for="node-input-hueDevice" >
|
|
195
|
+
<i class="fa fa-play-circle"></i> Hue Sensor</label>
|
|
196
|
+
<input type="text" id="node-input-name" placeholder="Enter your hue device name" />
|
|
197
|
+
<input type="hidden" id="node-input-hueDevice" />
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<br/>
|
|
201
|
+
|
|
202
|
+
<p>
|
|
203
|
+
<b>KNX</b>
|
|
204
|
+
</p>
|
|
205
|
+
|
|
206
|
+
<div class="form-row">
|
|
207
|
+
<label for="node-input-namezigbeeconnectivity" style="width:100px;"><i class="fa fa-play-circle-o"></i> Status</span></label>
|
|
208
|
+
|
|
209
|
+
<label for="node-input-GAzigbeeconnectivity" style="width:20px;">GA</label>
|
|
210
|
+
<input type="text" id="node-input-GAzigbeeconnectivity" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
|
|
211
|
+
|
|
212
|
+
<label for="node-input-dptzigbeeconnectivity" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
|
|
213
|
+
<select id="node-input-dptzigbeeconnectivity" style="width:140px;"></select>
|
|
214
|
+
|
|
215
|
+
<label for="node-input-namezigbeeconnectivity" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
|
|
216
|
+
<input type="text" id="node-input-namezigbeeconnectivity" style="width:200px;margin-left: 5px; text-align: left;">
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<div class="form-row">
|
|
220
|
+
<label style="width:180px" for="node-input-readStatusAtStartup"><i class="fa fa-play-circle"></i> Read status at startup</label>
|
|
221
|
+
<select id="node-input-readStatusAtStartup">
|
|
222
|
+
<option value="no">No</option>
|
|
223
|
+
<option value="yes">Yes, and emit KNX telegrams.</option>
|
|
224
|
+
</select>
|
|
225
|
+
</div>
|
|
226
|
+
<br/>
|
|
227
|
+
<br/>
|
|
228
|
+
<br/>
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
</script>
|
|
232
|
+
|
|
233
|
+
<script type="text/markdown" data-help-name="knxUltimateHueZigbeeConnectivity">
|
|
234
|
+
This node lets you get the zigbee connectivity status from your HUE device.
|
|
235
|
+
|
|
236
|
+
Start typing the name or group address of your KNX device in the GA field, the avaiable devices start showing up while
|
|
237
|
+
you're typing.
|
|
238
|
+
|
|
239
|
+
**General**
|
|
240
|
+
|Property|Description|
|
|
241
|
+
|--|--|
|
|
242
|
+
| KNX GW | Select the KNX gateway to be used |
|
|
243
|
+
| HUE Bridge | Select the HUE Bridge to be used |
|
|
244
|
+
| Hue Sensor | HUE sensor to be used. The avaiable devices start showing up while you're typing.|
|
|
245
|
+
|
|
246
|
+
|Property|Description|
|
|
247
|
+
|--|--|
|
|
248
|
+
| Status | The zigbee connectivity status KNX group address. The status of this KNX group address, will change in *true* if connected, otherwise *false* |
|
|
249
|
+
| Read status at startup | Read the status at startup and emit the event to the KNX bus at startup/reconnection. (Default "yes")|
|
|
250
|
+
|
|
251
|
+
### Outputs
|
|
252
|
+
|
|
253
|
+
1. Standard output
|
|
254
|
+
: payload (boolean) : the standard output of the command.
|
|
255
|
+
|
|
256
|
+
### Details
|
|
257
|
+
|
|
258
|
+
`msg.payload` is used as the payload of the published message (trus/false).
|
|
259
|
+
`msg.status` contains the text representing the status. It can be: **connected, disconnected, connectivity_issue, unidirectional_incoming**.
|
|
260
|
+
|
|
261
|
+
<br />
|
|
262
|
+
|
|
263
|
+
[Find it useful?](https://www.paypal.me/techtoday)
|
|
264
|
+
|
|
265
|
+
<br />
|
|
266
|
+
|
|
267
|
+
</script>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function knxUltimateHueZigbeeConnectivity(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
const node = this;
|
|
5
|
+
node.server = RED.nodes.getNode(config.server);
|
|
6
|
+
node.serverHue = RED.nodes.getNode(config.serverHue);
|
|
7
|
+
node.topic = node.name;
|
|
8
|
+
node.name = config.name === undefined ? 'Hue' : config.name;
|
|
9
|
+
node.dpt = '';
|
|
10
|
+
node.notifyreadrequest = true;
|
|
11
|
+
node.notifyreadrequestalsorespondtobus = 'false';
|
|
12
|
+
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = '';
|
|
13
|
+
node.notifyresponse = false;
|
|
14
|
+
node.notifywrite = true;
|
|
15
|
+
node.initialread = true;
|
|
16
|
+
node.listenallga = true; // Don't remove
|
|
17
|
+
node.outputtype = 'write';
|
|
18
|
+
node.outputRBE = false; // Apply or not RBE to the output (Messages coming from flow)
|
|
19
|
+
node.inputRBE = false; // Apply or not RBE to the input (Messages coming from BUS)
|
|
20
|
+
node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg
|
|
21
|
+
node.passthrough = 'no';
|
|
22
|
+
node.formatmultiplyvalue = 1;
|
|
23
|
+
node.formatnegativevalue = 'leave';
|
|
24
|
+
node.formatdecimalsvalue = 2;
|
|
25
|
+
node.hueDevice = config.hueDevice;
|
|
26
|
+
node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes");
|
|
27
|
+
node.currentDeviceValue = 0;
|
|
28
|
+
|
|
29
|
+
// Used to call the status update from the config node.
|
|
30
|
+
node.setNodeStatus = ({
|
|
31
|
+
fill, shape, text, payload,
|
|
32
|
+
}) => {
|
|
33
|
+
|
|
34
|
+
};
|
|
35
|
+
// Used to call the status update from the HUE config node.
|
|
36
|
+
node.setNodeStatusHue = ({
|
|
37
|
+
fill, shape, text, payload,
|
|
38
|
+
}) => {
|
|
39
|
+
if (payload === undefined) payload = '';
|
|
40
|
+
const dDate = new Date();
|
|
41
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
|
|
42
|
+
node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
46
|
+
node.handleSend = (msg) => {
|
|
47
|
+
// Respond to KNX read telegram, by sending the current value as response telegram.
|
|
48
|
+
if (msg.knx.event === "GroupValue_Read") {
|
|
49
|
+
switch (msg.knx.destination) {
|
|
50
|
+
case config.GAzigbeeconnectivity:
|
|
51
|
+
// To the KNX bus wires
|
|
52
|
+
node.sendResponseToKNX(node.currentDeviceValue);
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
node.handleSendHUE = (_event) => {
|
|
61
|
+
try {
|
|
62
|
+
// Event status: one of connected, disconnected, connectivity_issue, unidirectional_incoming
|
|
63
|
+
if (_event.id === config.hueDevice) {
|
|
64
|
+
if (!_event.hasOwnProperty("status") || _event.status === undefined) return;
|
|
65
|
+
|
|
66
|
+
const knxMsgPayload = {};
|
|
67
|
+
knxMsgPayload.topic = config.GAzigbeeconnectivity;
|
|
68
|
+
knxMsgPayload.dpt = config.dptzigbeeconnectivity;
|
|
69
|
+
|
|
70
|
+
knxMsgPayload.payload = (_event.status === "connected");
|
|
71
|
+
// Send to KNX bus
|
|
72
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
|
|
73
|
+
node.server.writeQueueAdd({
|
|
74
|
+
grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
node.currentDeviceValue = knxMsgPayload.payload;
|
|
78
|
+
// Setup the output msg
|
|
79
|
+
knxMsgPayload.name = node.name;
|
|
80
|
+
knxMsgPayload.status = _event.status;
|
|
81
|
+
knxMsgPayload.event = 'zigbee_connectivity';
|
|
82
|
+
// Send payload
|
|
83
|
+
knxMsgPayload.rawEvent = _event;
|
|
84
|
+
node.send(knxMsgPayload);
|
|
85
|
+
node.setNodeStatusHue({
|
|
86
|
+
fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
node.status({ fill: 'red', shape: 'dot', text: `HUE->KNX error ${error.message} (${new Date().getDate()}, ${new Date().toLocaleTimeString()})` });
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
node.sendResponseToKNX = (_level) => {
|
|
96
|
+
const knxMsgPayload = {};
|
|
97
|
+
knxMsgPayload.topic = config.GAzigbeeconnectivity;
|
|
98
|
+
knxMsgPayload.dpt = config.dptzigbeeconnectivity;
|
|
99
|
+
|
|
100
|
+
knxMsgPayload.payload = _level;
|
|
101
|
+
// Send to KNX bus
|
|
102
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
|
|
103
|
+
node.server.writeQueueAdd({
|
|
104
|
+
grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'response', nodecallerid: node.id,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// On each deploy, unsubscribe+resubscribe
|
|
110
|
+
if (node.server) {
|
|
111
|
+
node.server.removeClient(node);
|
|
112
|
+
node.server.addClient(node);
|
|
113
|
+
}
|
|
114
|
+
if (node.serverHue) {
|
|
115
|
+
node.serverHue.removeClient(node);
|
|
116
|
+
node.serverHue.addClient(node);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
node.on('input', (msg) => {
|
|
120
|
+
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
node.on('close', (done) => {
|
|
124
|
+
if (node.server) {
|
|
125
|
+
node.server.removeClient(node);
|
|
126
|
+
}
|
|
127
|
+
if (node.serverHue) {
|
|
128
|
+
node.serverHue.removeClient(node);
|
|
129
|
+
}
|
|
130
|
+
done();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
RED.nodes.registerType('knxUltimateHueZigbeeConnectivity', knxUltimateHueZigbeeConnectivity);
|
|
134
|
+
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.4.5-beta.
|
|
6
|
+
"version": "2.4.5-beta.3",
|
|
7
7
|
"description": "Control your KNX intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"binary-parser": "2.2.1",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"knxUltimateHueLightSensor": "/nodes/knxUltimateHueLightSensor.js",
|
|
44
44
|
"knxUltimateHueTemperatureSensor": "/nodes/knxUltimateHueTemperatureSensor.js",
|
|
45
45
|
"knxUltimateHueScene": "/nodes/knxUltimateHueScene.js",
|
|
46
|
-
"knxUltimateHueBattery": "/nodes/knxUltimateHueBattery.js"
|
|
46
|
+
"knxUltimateHueBattery": "/nodes/knxUltimateHueBattery.js",
|
|
47
|
+
"knxUltimateHueZigbeeConnectivity": "/nodes/knxUltimateHueZigbeeConnectivity.js"
|
|
47
48
|
}
|
|
48
49
|
},
|
|
49
50
|
"repository": {
|