node-red-contrib-knx-ultimate 2.4.5-beta.1 → 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 +7 -0
- package/nodes/commonFunctions.js +1 -1
- package/nodes/hue-config.js +20 -20
- package/nodes/knxUltimateHueBattery.js +1 -1
- package/nodes/knxUltimateHueLight.html +2 -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,13 @@
|
|
|
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
|
+
|
|
13
|
+
**Version 2.4.5-beta.2 PUBLIC BETA** - Feb 2024<br/>
|
|
14
|
+
- Fix the listing of ethernet interfaces in the gateway config window.<br/>
|
|
15
|
+
|
|
9
16
|
**Version 2.4.5-beta.1 PUBLIC BETA** - Feb 2024<br/>
|
|
10
17
|
- WARNING: this version uses the Node-Red plugin system; the Node-Red version must be **equals or major than 3.1.1**<br/>
|
|
11
18
|
- HUE: Optimized color translation between xyBri and RGB.<br/>
|
package/nodes/commonFunctions.js
CHANGED
|
@@ -237,9 +237,9 @@ module.exports = (RED) => {
|
|
|
237
237
|
|
|
238
238
|
// 14/08/2019 Endpoint for retrieving the ethernet interfaces
|
|
239
239
|
RED.httpAdmin.get("/knxUltimateETHInterfaces", (req, res) => {
|
|
240
|
+
const jListInterfaces = [];
|
|
240
241
|
try {
|
|
241
242
|
const oiFaces = oOS.networkInterfaces();
|
|
242
|
-
const jListInterfaces = [];
|
|
243
243
|
Object.keys(oiFaces).forEach((ifname) => {
|
|
244
244
|
// Interface with single IP
|
|
245
245
|
if (Object.keys(oiFaces[ifname]).length === 1) {
|
package/nodes/hue-config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
1
2
|
/* eslint-disable no-underscore-dangle */
|
|
2
3
|
/* eslint-disable no-lonely-if */
|
|
3
4
|
/* eslint-disable no-param-reassign */
|
|
@@ -120,24 +121,6 @@ module.exports = (RED) => {
|
|
|
120
121
|
// °°°°°° Load ALL resources
|
|
121
122
|
try {
|
|
122
123
|
node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
|
|
123
|
-
|
|
124
|
-
// // DEBUG
|
|
125
|
-
// try {
|
|
126
|
-
// const fs = require('fs');
|
|
127
|
-
// const { resolve } = require('path');
|
|
128
|
-
// const content = JSON.stringify(node.hueAllResources);
|
|
129
|
-
// try {
|
|
130
|
-
// fs.writeFileSync('resources.json', content);
|
|
131
|
-
// RED.log.info("******************************* FILE WROTE IN resources.json " + resolve("resources.json"))
|
|
132
|
-
// // file written successfully
|
|
133
|
-
// } catch (error) {
|
|
134
|
-
// RED.log.error("********************************************* const content = JSON.stringify(node.hueAllResources)2222: " + error.message)
|
|
135
|
-
// }
|
|
136
|
-
// } catch (error) {
|
|
137
|
-
// RED.log.error("********************************************* const content = JSON.stringify(node.hueAllResources): " + error.message)
|
|
138
|
-
// }
|
|
139
|
-
|
|
140
|
-
|
|
141
124
|
if (node.hueAllResources !== undefined) {
|
|
142
125
|
node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
|
|
143
126
|
// Update all KNX State of the nodes with the new hue device values
|
|
@@ -149,10 +132,12 @@ module.exports = (RED) => {
|
|
|
149
132
|
_node.setNodeStatusHue({
|
|
150
133
|
fill: "green",
|
|
151
134
|
shape: "ring",
|
|
152
|
-
text: "Ready
|
|
135
|
+
text: "Ready",
|
|
153
136
|
});
|
|
154
137
|
_node.currentHUEDevice = cloneDeep(oHUEDevice); // Copy by Value and not by ref
|
|
155
|
-
if (_node.initializingAtStart === true)
|
|
138
|
+
if (_node.initializingAtStart === true) {
|
|
139
|
+
_node.handleSendHUE(oHUEDevice); // Pass by value
|
|
140
|
+
}
|
|
156
141
|
}
|
|
157
142
|
}
|
|
158
143
|
});
|
|
@@ -317,6 +302,21 @@ module.exports = (RED) => {
|
|
|
317
302
|
id: resource.id,
|
|
318
303
|
});
|
|
319
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
|
+
}
|
|
320
320
|
} catch (error) {
|
|
321
321
|
retArray.push({
|
|
322
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.
|
|
@@ -1498,7 +1498,8 @@ Start typing in the GA field, the name or group address of your KNX device, the
|
|
|
1498
1498
|
| Status H %| Status of the HSV chromatic circle.|
|
|
1499
1499
|
| Control S dim | Changes the light's color saturation, using DPT 3.007 dimming. You can set the dimming speed in the **_Behaviour_** tab.|
|
|
1500
1500
|
| Status S %| The light color saturation status group address.|
|
|
1501
|
-
| Dim Speed (ms) | The dimming speed, in Milliseconds, from bottom to top scale. |
|
|
1501
|
+
| Dim Speed (ms) | The dimming speed, in Milliseconds, from bottom to top scale. |
|
|
1502
|
+
|
|
1502
1503
|
For controlling the "V" (brightness) of the HSV, please use the standard controls of the **DIM** tab.
|
|
1503
1504
|
|
|
1504
1505
|
|
|
@@ -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": {
|