node-red-contrib-knx-ultimate 2.2.1 → 2.2.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/.eslintrc.json +12 -12
- package/CHANGELOG.md +13 -1
- package/nodes/hue-config.js +60 -71
- package/nodes/knxUltimate-config.js +6 -4
- package/nodes/knxUltimateHueBattery.js +69 -68
- package/nodes/knxUltimateHueLight.html +844 -835
- package/nodes/knxUltimateHueLight.js +147 -115
- package/nodes/knxUltimateHueLightSensor.js +53 -62
- package/nodes/knxUltimateHueMotion.html +3 -4
- package/nodes/knxUltimateHueMotion.js +73 -61
- package/nodes/knxUltimateHueScene.js +1 -1
- package/nodes/knxUltimateHueTemperatureSensor.js +70 -71
- package/nodes/knxUltimateViewer.html +28 -0
- package/nodes/utils/hueEngine.js +57 -42
- package/package.json +25 -4
package/.eslintrc.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"commonjs": true,
|
|
5
|
+
"es2021": true
|
|
6
|
+
},
|
|
7
|
+
"extends": "airbnb-base",
|
|
8
|
+
"parserOptions": {
|
|
9
|
+
"ecmaVersion": "latest"
|
|
10
|
+
},
|
|
11
|
+
"rules": {
|
|
12
|
+
"quotes": "off"
|
|
13
|
+
}
|
|
14
14
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
-
[](https://www.paypal.me/techtoday)
|
|
3
|
+
[](https://www.paypal.me/techtoday)
|
|
4
4
|
|
|
5
5
|
<br/>
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
|
+
|
|
9
|
+
<b>Version 2.2.3</b> - October 2023<br/>
|
|
10
|
+
- HUE Light: Again, rewrite of the DIM function to get rid of the dimming_delta.<br/>
|
|
11
|
+
</p>
|
|
12
|
+
<p>
|
|
13
|
+
<b>Version 2.2.2</b> - October 2023<br/>
|
|
14
|
+
- NEW: HUE Motion: support HUE Camera motion events via the HUE Motion node.<br/>
|
|
15
|
+
- HUE Light: some tweaking to the GUI.<br/>
|
|
16
|
+
- HUE Grouped Light: Fixed relative dimming function.<br/>
|
|
17
|
+
- KNK Alerter node: <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/SampleAlerter">fixed the wiki sample page</a>.<br/>
|
|
18
|
+
- KNX Viewer: added the help pane in Node-Red.<br/>
|
|
19
|
+
</p>
|
|
8
20
|
<p>
|
|
9
21
|
<b>Version 2.2.1</b> - October 2023<br/>
|
|
10
22
|
- Massive rewrite of the DIM function, for brightness and for color temperature.<br/>
|
package/nodes/hue-config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
1
2
|
/* eslint-disable no-inner-declarations */
|
|
2
3
|
/* eslint-disable max-len */
|
|
3
4
|
const dptlib = require("../KNXEngine/src/dptlib");
|
|
@@ -5,6 +6,12 @@ const HueClass = require("./utils/hueEngine").classHUE;
|
|
|
5
6
|
const loggerEngine = require("./utils/sysLogger");
|
|
6
7
|
const hueColorConverter = require("./utils/hueColorConverter");
|
|
7
8
|
|
|
9
|
+
function getRandomIntInclusive(min, max) {
|
|
10
|
+
min = Math.ceil(min);
|
|
11
|
+
max = Math.floor(max);
|
|
12
|
+
return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
// Helpers
|
|
9
16
|
const sortBy = (field) => (a, b) => {
|
|
10
17
|
if (a[field] > b[field]) {
|
|
@@ -85,67 +92,49 @@ module.exports = (RED) => {
|
|
|
85
92
|
(async () => {
|
|
86
93
|
try {
|
|
87
94
|
await node.loadResourcesFromHUEBridge(); // Then, you can use node.getResources, that works locally and doesn't query the HUE Bridge.
|
|
88
|
-
} catch (error) {
|
|
95
|
+
} catch (error) {
|
|
96
|
+
/* empty */
|
|
97
|
+
}
|
|
89
98
|
})();
|
|
90
99
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("node.hueManager connected event");
|
|
91
100
|
});
|
|
92
101
|
};
|
|
93
102
|
|
|
94
103
|
// Query the HUE Bridge to return the resources
|
|
95
|
-
node.loadResourcesFromHUEBridge = (
|
|
104
|
+
node.loadResourcesFromHUEBridge = () => {
|
|
96
105
|
(async () => {
|
|
97
|
-
//
|
|
106
|
+
// °°°°°° Load ALL resources
|
|
98
107
|
try {
|
|
99
|
-
if (_callerNode === undefined) {
|
|
100
108
|
node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
|
|
101
109
|
node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
|
|
102
110
|
// Update all KNX State of the nodes with the new hue device values
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (oHUEDevice !== undefined) {
|
|
107
|
-
nodeClient.currentHUEDevice = oHUEDevice;
|
|
108
|
-
for (const [key, value] of Object.entries(oHUEDevice)) {
|
|
109
|
-
// Update KNX State
|
|
110
|
-
let oProperty = { id: oHUEDevice.id }
|
|
111
|
-
oProperty[key] = value;
|
|
112
|
-
nodeClient.handleSendHUE(oProperty);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
} else {
|
|
118
|
-
// Update only one node. The node is requesting an update because it has beeb edited by the user
|
|
119
|
-
try {
|
|
120
|
-
// Please KEEP THE AWAIT, otherwise al posto dell'oggetto, a Promisse will be returned.
|
|
121
|
-
const oHUEDevice = await node.hueAllResources.filter((a) => a.id === _callerNode.hueDevice)[0];
|
|
111
|
+
node.nodeClients.forEach((nodeClient) => {
|
|
112
|
+
if (nodeClient.hueDevice !== undefined) {
|
|
113
|
+
const oHUEDevice = node.hueAllResources.filter((a) => a.id === nodeClient.hueDevice)[0];
|
|
122
114
|
if (oHUEDevice !== undefined) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
} catch (error) {
|
|
132
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
133
|
-
this.sysLogger.error(`KNXUltimatehueEngine: loadResourcesFromHUEBridge, from a single node that has been edited: ${error.message}`);
|
|
134
|
-
reject(error.message);
|
|
115
|
+
nodeClient.currentHUEDevice = oHUEDevice;
|
|
116
|
+
nodeClient.handleSendHUE(oHUEDevice);
|
|
117
|
+
// for (const [key, value] of Object.entries(oHUEDevice)) {
|
|
118
|
+
// // Update KNX State
|
|
119
|
+
// const oProperty = { id: oHUEDevice.id };
|
|
120
|
+
// oProperty[key] = value;
|
|
121
|
+
// nodeClient.handleSendHUE(oProperty);
|
|
122
|
+
// }
|
|
135
123
|
}
|
|
136
124
|
}
|
|
137
|
-
}
|
|
138
|
-
resolve(true);
|
|
125
|
+
});
|
|
139
126
|
} catch (error) {
|
|
140
127
|
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
141
128
|
this.sysLogger.error(`KNXUltimatehueEngine: loadResourcesFromHUEBridge: ${error.message}`);
|
|
142
|
-
|
|
129
|
+
return (error.message);
|
|
143
130
|
}
|
|
144
131
|
}
|
|
132
|
+
return true;
|
|
145
133
|
})();
|
|
146
|
-
}
|
|
134
|
+
};
|
|
135
|
+
|
|
147
136
|
// Returns the cached devices (node.hueAllResources) by type.
|
|
148
|
-
node.getResources = (_rtype)
|
|
137
|
+
node.getResources = function getResources(_rtype) {
|
|
149
138
|
try {
|
|
150
139
|
if (node.hueAllResources === undefined) return;
|
|
151
140
|
// Returns capitalized string
|
|
@@ -175,14 +164,14 @@ module.exports = (RED) => {
|
|
|
175
164
|
resourceName += "ALL GROUPS and ";
|
|
176
165
|
} else {
|
|
177
166
|
resourceName += `${owner.metadata.name} and `;
|
|
178
|
-
//const room = node.hueAllRooms.find((child) => child.children.find((a) => a.rid === owner.id));
|
|
179
|
-
//sRoom += room !== undefined ? `${room.metadata.name} + ` : " + ";
|
|
180
|
-
sType += capStr(owner.type) +
|
|
167
|
+
// const room = node.hueAllRooms.find((child) => child.children.find((a) => a.rid === owner.id));
|
|
168
|
+
// sRoom += room !== undefined ? `${room.metadata.name} + ` : " + ";
|
|
169
|
+
sType += `${capStr(owner.type)} + `;
|
|
181
170
|
}
|
|
182
171
|
}
|
|
183
172
|
sType = sType.slice(0, -" + ".length);
|
|
184
173
|
resourceName = resourceName.slice(0, -" and ".length);
|
|
185
|
-
resourceName += sType !== "" ?
|
|
174
|
+
resourceName += sType !== "" ? ` (${sType})` : "";
|
|
186
175
|
retArray.push({
|
|
187
176
|
name: `${capStr(resource.type)}: ${resourceName}`,
|
|
188
177
|
id: resource.id,
|
|
@@ -207,7 +196,7 @@ module.exports = (RED) => {
|
|
|
207
196
|
id: resource.id,
|
|
208
197
|
});
|
|
209
198
|
}
|
|
210
|
-
if (_rtype === "motion") {
|
|
199
|
+
if (_rtype === "motion" || _rtype === "camera_motion") {
|
|
211
200
|
const linkedDevName = node.hueAllResources.find((dev) => dev.type === "device" && dev.services.find((serv) => serv.rid === resource.id)).metadata.name || "";
|
|
212
201
|
retArray.push({
|
|
213
202
|
name: `${capStr(_rtype)}: ${linkedDevName}`,
|
|
@@ -260,23 +249,17 @@ module.exports = (RED) => {
|
|
|
260
249
|
};
|
|
261
250
|
|
|
262
251
|
// Query HUE Bridge and get the updated color.
|
|
263
|
-
node.getColorFromHueLight = (_lightId) =>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
} catch (error) {
|
|
275
|
-
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`KNXUltimateHue: hueEngine: getColorFromHueLight: error ${error.message}`);
|
|
276
|
-
reject(error.message);
|
|
277
|
-
}
|
|
278
|
-
})();
|
|
279
|
-
});
|
|
252
|
+
node.getColorFromHueLight = (_lightId) => {
|
|
253
|
+
try {
|
|
254
|
+
// await node.loadResourcesFromHUEBridge();
|
|
255
|
+
const oLight = node.hueAllResources.filter((a) => a.id === _lightId)[0];
|
|
256
|
+
const ret = hueColorConverter.ColorConverter.xyBriToRgb(oLight.color.xy.x, oLight.color.xy.y, oLight.dimming.brightness);
|
|
257
|
+
return JSON.stringify(ret);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`KNXUltimateHue: hueEngine: getColorFromHueLight: error ${error.message}`);
|
|
260
|
+
return {};
|
|
261
|
+
}
|
|
262
|
+
};
|
|
280
263
|
|
|
281
264
|
node.addClient = (_Node) => {
|
|
282
265
|
// Check if node already exists
|
|
@@ -288,6 +271,12 @@ module.exports = (RED) => {
|
|
|
288
271
|
text: "Hue initialized.",
|
|
289
272
|
});
|
|
290
273
|
node.nodeClients.push(_Node);
|
|
274
|
+
// Update the node hue device, as soon as a node register itself to hue-config nodeClients
|
|
275
|
+
if (node.hueAllResources !== null) { // At first start, due to the async method for retrieving hueAllResources, hueAllResources is still null. The first start is handled in node.hueManager.on("connected")
|
|
276
|
+
const oHUEDevice = node.hueAllResources.filter((a) => a.id === _Node.hueDevice)[0];
|
|
277
|
+
_Node.currentHUEDevice = oHUEDevice;
|
|
278
|
+
if (oHUEDevice !== undefined) _Node.handleSendHUE(oHUEDevice);
|
|
279
|
+
}
|
|
291
280
|
}
|
|
292
281
|
};
|
|
293
282
|
|
|
@@ -295,7 +284,9 @@ module.exports = (RED) => {
|
|
|
295
284
|
// Remove the client node from the clients array
|
|
296
285
|
try {
|
|
297
286
|
node.nodeClients = node.nodeClients.filter((x) => x.id !== _Node.id);
|
|
298
|
-
} catch (error) {
|
|
287
|
+
} catch (error) {
|
|
288
|
+
/* empty */
|
|
289
|
+
}
|
|
299
290
|
};
|
|
300
291
|
|
|
301
292
|
node.on("close", (done) => {
|
|
@@ -320,14 +311,12 @@ module.exports = (RED) => {
|
|
|
320
311
|
});
|
|
321
312
|
|
|
322
313
|
RED.httpAdmin.get("/knxUltimateGetHueColor", RED.auth.needsPermission("hue-config.read"), (req, res) => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
})();
|
|
314
|
+
try {
|
|
315
|
+
const rgbColor = node.getColorFromHueLight(req.query.id);
|
|
316
|
+
res.json(rgbColor);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
res.json("Select the device first!");
|
|
319
|
+
}
|
|
331
320
|
});
|
|
332
321
|
|
|
333
322
|
RED.httpAdmin.get("/KNXUltimateGetResourcesHUE", RED.auth.needsPermission("hue-config.read"), (req, res) => {
|
|
@@ -940,14 +940,16 @@ return msg;`,
|
|
|
940
940
|
}
|
|
941
941
|
// 12/11/2021 Starts the telegram out queue handler
|
|
942
942
|
if (node.timerSendTelegramFromQueue !== null) clearInterval(node.timerSendTelegramFromQueue);
|
|
943
|
-
node.timerSendTelegramFromQueue = setInterval(handleTelegramQueue, config.delaybetweentelegrams === undefined || Number(config.delaybetweentelegrams) < 20 ? 20 : Number(config.delaybetweentelegrams)
|
|
944
|
-
); // 02/01/2020 Start the timer that handles the queue of telegrams
|
|
943
|
+
node.timerSendTelegramFromQueue = setInterval(handleTelegramQueue, config.delaybetweentelegrams === undefined || Number(config.delaybetweentelegrams) < 20 ? 20 : Number(config.delaybetweentelegrams)); // 02/01/2020 Start the timer that handles the queue of telegrams
|
|
945
944
|
node.linkStatus = "connected";
|
|
946
945
|
|
|
947
946
|
// Start the timer to do initial read.
|
|
948
947
|
if (node.timerDoInitialRead !== null) clearTimeout(node.timerDoInitialRead);
|
|
949
|
-
node.timerDoInitialRead = setTimeout(
|
|
950
|
-
|
|
948
|
+
node.timerDoInitialRead = setTimeout(() => {
|
|
949
|
+
DoInitialReadFromKNXBusOrFile();
|
|
950
|
+
callConnectToHueBridgeOfAllHUEServers();
|
|
951
|
+
}, 6000); // 17/02/2020 Do initial read of all nodes requesting initial read
|
|
952
|
+
//node.timerCallConnectToHueBridgeOfAllHUEServers = setTimeout(callConnectToHueBridgeOfAllHUEServers, 6000); // connects all hue-config nodes to the HUE Bridge.
|
|
951
953
|
const t = setTimeout(() => {
|
|
952
954
|
// 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
|
|
953
955
|
node.setAllClientsStatus("Connected.", "green", "On duty.");
|
|
@@ -1,107 +1,108 @@
|
|
|
1
1
|
module.exports = function (RED) {
|
|
2
2
|
function knxUltimateHueBattery(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 = false
|
|
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
|
|
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 = false;
|
|
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
25
|
|
|
26
26
|
// Used to call the status update from the config node.
|
|
27
|
-
node.setNodeStatus = ({
|
|
27
|
+
node.setNodeStatus = ({
|
|
28
|
+
fill, shape, text, payload,
|
|
29
|
+
}) => {
|
|
28
30
|
|
|
29
|
-
}
|
|
31
|
+
};
|
|
30
32
|
// Used to call the status update from the HUE config node.
|
|
31
|
-
node.setNodeStatusHue = ({
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
node.setNodeStatusHue = ({
|
|
34
|
+
fill, shape, text, payload,
|
|
35
|
+
}) => {
|
|
36
|
+
if (payload === undefined) return;
|
|
37
|
+
const dDate = new Date();
|
|
38
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
|
|
39
|
+
node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
|
|
40
|
+
};
|
|
37
41
|
|
|
38
42
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
39
|
-
node.handleSend = msg => {
|
|
40
|
-
}
|
|
43
|
+
node.handleSend = (msg) => {
|
|
44
|
+
};
|
|
41
45
|
|
|
42
|
-
node.handleSendHUE = _event => {
|
|
46
|
+
node.handleSendHUE = (_event) => {
|
|
43
47
|
try {
|
|
44
48
|
if (_event.id === config.hueDevice) {
|
|
45
|
-
const knxMsgPayload = {}
|
|
46
|
-
knxMsgPayload.topic = config.GAbatterysensor
|
|
47
|
-
knxMsgPayload.dpt = config.dptbatterysensor
|
|
49
|
+
const knxMsgPayload = {};
|
|
50
|
+
knxMsgPayload.topic = config.GAbatterysensor;
|
|
51
|
+
knxMsgPayload.dpt = config.dptbatterysensor;
|
|
48
52
|
|
|
49
53
|
if (_event.hasOwnProperty('power_state') && _event.power_state.hasOwnProperty('battery_level')) {
|
|
50
|
-
knxMsgPayload.payload = _event.power_state.battery_level
|
|
54
|
+
knxMsgPayload.payload = _event.power_state.battery_level;
|
|
51
55
|
// Send to KNX bus
|
|
52
|
-
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined)
|
|
53
|
-
|
|
56
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
|
|
57
|
+
node.server.writeQueueAdd({
|
|
58
|
+
grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
// Setup the output msg
|
|
55
|
-
knxMsgPayload.name = node.name
|
|
56
|
-
knxMsgPayload.event = 'power_state'
|
|
63
|
+
knxMsgPayload.name = node.name;
|
|
64
|
+
knxMsgPayload.event = 'power_state';
|
|
57
65
|
|
|
58
66
|
// Send payload
|
|
59
|
-
knxMsgPayload.rawEvent = _event
|
|
60
|
-
node.send(knxMsgPayload)
|
|
61
|
-
node.setNodeStatusHue({
|
|
67
|
+
knxMsgPayload.rawEvent = _event;
|
|
68
|
+
node.send(knxMsgPayload);
|
|
69
|
+
node.setNodeStatusHue({
|
|
70
|
+
fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload,
|
|
71
|
+
});
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
74
|
} catch (error) {
|
|
65
|
-
node.status({ fill: 'red', shape: 'dot', text:
|
|
75
|
+
node.status({ fill: 'red', shape: 'dot', text: `HUE->KNX error ${error.message} (${new Date().getDate()}, ${new Date().toLocaleTimeString()})` });
|
|
66
76
|
}
|
|
67
|
-
}
|
|
77
|
+
};
|
|
68
78
|
|
|
69
79
|
// On each deploy, unsubscribe+resubscribe
|
|
70
80
|
if (node.server) {
|
|
71
|
-
node.server.removeClient(node)
|
|
72
|
-
node.server.addClient(node)
|
|
81
|
+
node.server.removeClient(node);
|
|
82
|
+
node.server.addClient(node);
|
|
73
83
|
}
|
|
74
84
|
if (node.serverHue) {
|
|
75
|
-
node.serverHue.removeClient(node)
|
|
85
|
+
node.serverHue.removeClient(node);
|
|
76
86
|
// I must get the object, to store read the battery status
|
|
77
87
|
// I queue the state request, by passing the callback to call whenever the HUE bridge send me the light status async
|
|
78
88
|
if (node.serverHue !== null && node.serverHue.hueManager !== null) {
|
|
79
|
-
(
|
|
80
|
-
try {
|
|
81
|
-
node.serverHue.addClient(node)
|
|
82
|
-
await node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, null, 'getBattery', (jLight) => {
|
|
83
|
-
node.handleSendHUE(jLight)
|
|
84
|
-
})
|
|
85
|
-
} catch (err) {
|
|
86
|
-
RED.log.error('Errore knxUltimateHueBattery subscribe: ' + err.message)
|
|
87
|
-
}
|
|
88
|
-
})()
|
|
89
|
+
node.serverHue.addClient(node);
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
node.on('input',
|
|
93
|
+
node.on('input', (msg) => {
|
|
93
94
|
|
|
94
|
-
})
|
|
95
|
+
});
|
|
95
96
|
|
|
96
|
-
node.on('close',
|
|
97
|
+
node.on('close', (done) => {
|
|
97
98
|
if (node.server) {
|
|
98
|
-
node.server.removeClient(node)
|
|
99
|
+
node.server.removeClient(node);
|
|
99
100
|
}
|
|
100
101
|
if (node.serverHue) {
|
|
101
|
-
node.serverHue.removeClient(node)
|
|
102
|
+
node.serverHue.removeClient(node);
|
|
102
103
|
}
|
|
103
|
-
done()
|
|
104
|
-
})
|
|
104
|
+
done();
|
|
105
|
+
});
|
|
105
106
|
}
|
|
106
|
-
RED.nodes.registerType('knxUltimateHueBattery', knxUltimateHueBattery)
|
|
107
|
-
}
|
|
107
|
+
RED.nodes.registerType('knxUltimateHueBattery', knxUltimateHueBattery);
|
|
108
|
+
};
|