node-red-contrib-knx-ultimate 3.3.17 → 3.3.19
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 +8 -0
- package/nodes/commonFunctions.js +6 -3
- package/nodes/hue-config.js +14 -11
- package/nodes/knxUltimate-config.js +1 -1
- package/nodes/knxUltimateHueBattery.js +15 -8
- package/nodes/knxUltimateHueButton.js +15 -8
- package/nodes/knxUltimateHueContactSensor.js +19 -11
- package/nodes/knxUltimateHueLight.js +18 -5
- package/nodes/knxUltimateHueLightSensor.js +17 -6
- package/nodes/knxUltimateHueMotion.js +18 -5
- package/nodes/knxUltimateHueScene.js +17 -6
- package/nodes/knxUltimateHueTapDial.js +15 -7
- package/nodes/knxUltimateHueTemperatureSensor.js +15 -8
- package/nodes/knxUltimateHueZigbeeConnectivity.js +15 -8
- package/nodes/knxUltimateHuedevice_software_update.js +15 -8
- package/nodes/utils/hueEngine.js +28 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 3.3.19** - March 2025<br/>
|
|
10
|
+
- HUE light nodes now have the colored status icon that follows the light status on/off. Blue fill dot is ON, blue ring is OFF<br/>
|
|
11
|
+
|
|
12
|
+
**Version 3.3.18** - March 2025<br/>
|
|
13
|
+
- For all HUE nodes, added both the HUE and KNX status in the node's status text.<br/>
|
|
14
|
+
- HUE engine: fixed a reconnection issue occurring sometimes, in some circumstances.<br/>
|
|
15
|
+
- KNX engine: speed up the connection, from 30 to 10 seconds.<br/>
|
|
16
|
+
|
|
9
17
|
**Version 3.3.16** - February 2025<br/>
|
|
10
18
|
- HUE config node: moved the connect directive after events declarations.<br/>
|
|
11
19
|
- HUE engine: optimized the disconnection detection procedure.<br/>
|
package/nodes/commonFunctions.js
CHANGED
|
@@ -76,15 +76,18 @@ module.exports = (RED) => {
|
|
|
76
76
|
const serverId = RED.nodes.getNode(req.query.serverId); // Retrieve node.id of the config node.
|
|
77
77
|
if (serverId.hueAllResources === null || serverId.hueAllResources === undefined) {
|
|
78
78
|
(async function main() {
|
|
79
|
-
|
|
79
|
+
try {
|
|
80
|
+
await serverId.loadResourcesFromHUEBridge();
|
|
81
|
+
} catch (error) {
|
|
82
|
+
RED.log.error(`Errore RED.httpAdmin.get('/knxultimateCheckHueConnected' ${error.stack}`);
|
|
83
|
+
}
|
|
80
84
|
res.json({ ready: false });
|
|
81
85
|
}()).catch();
|
|
82
86
|
} else {
|
|
83
87
|
res.json({ ready: true });
|
|
84
88
|
}
|
|
85
89
|
} catch (error) {
|
|
86
|
-
RED.log.error(`Errore RED.httpAdmin.get('/knxultimateCheckHueConnected' ${error.
|
|
87
|
-
|
|
90
|
+
RED.log.error(`Errore RED.httpAdmin.get('/knxultimateCheckHueConnected' ${error.stack}`);
|
|
88
91
|
res.json({ ready: false });
|
|
89
92
|
}
|
|
90
93
|
});
|
package/nodes/hue-config.js
CHANGED
|
@@ -28,12 +28,19 @@ module.exports = (RED) => {
|
|
|
28
28
|
node.sysLogger = null;
|
|
29
29
|
node.hueAllResources = undefined;
|
|
30
30
|
node.timerHUEConfigCheckState = null; // Timer that check the connection to the hue bridge every xx seconds
|
|
31
|
-
node.linkStatus = "disconnected";
|
|
32
31
|
try {
|
|
33
32
|
node.sysLogger = loggerSetup({ loglevel: node.loglevel, setPrefix: "hue-config.js" });
|
|
34
33
|
} catch (error) { console.log(error.stack) }
|
|
35
34
|
node.name = config.name === undefined || config.name === "" ? node.host : config.name;
|
|
36
35
|
|
|
36
|
+
// Helper not to write everytime the "node.hueManager === null || node.hueManager === "undefined" || node.hueManager.HUEBridgeConnectionStatus === undefined"
|
|
37
|
+
Object.defineProperty(node, "linkStatus", {
|
|
38
|
+
get: function () {
|
|
39
|
+
return node.hueManager?.HUEBridgeConnectionStatus ?? "disconnected";
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
|
|
37
44
|
// Connect to Bridge and get the resources
|
|
38
45
|
node.initHUEConnection = async () => {
|
|
39
46
|
try {
|
|
@@ -44,13 +51,11 @@ module.exports = (RED) => {
|
|
|
44
51
|
} catch (error) { /* empty */ }
|
|
45
52
|
// Handle events
|
|
46
53
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
node.hueManager = new HueClass(node.host, node.credentials.username, node.credentials.clientkey, config.bridgeid, node.sysLogger);
|
|
50
|
-
} catch (error) { /* empty */ }
|
|
54
|
+
// Init HUE Utility
|
|
55
|
+
node.hueManager = new HueClass(node.host, node.credentials.username, node.credentials.clientkey, config.bridgeid, node.sysLogger);
|
|
51
56
|
} catch (error) {
|
|
52
57
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`Errore hue-config: node.initHUEConnection: ${error.message}`);
|
|
53
|
-
|
|
58
|
+
throw (error)
|
|
54
59
|
}
|
|
55
60
|
node.hueManager.on("event", (_event) => {
|
|
56
61
|
node.nodeClients.forEach((_oClient) => {
|
|
@@ -65,7 +70,6 @@ module.exports = (RED) => {
|
|
|
65
70
|
// Connected
|
|
66
71
|
node.hueManager.on("connected", () => {
|
|
67
72
|
if (node.linkStatus === "disconnected") {
|
|
68
|
-
node.linkStatus = "connected";
|
|
69
73
|
// Start the timer to do initial read.
|
|
70
74
|
if (node.timerDoInitialRead !== null) clearTimeout(node.timerDoInitialRead);
|
|
71
75
|
node.timerDoInitialRead = setTimeout(() => {
|
|
@@ -75,7 +79,6 @@ module.exports = (RED) => {
|
|
|
75
79
|
await node.loadResourcesFromHUEBridge();
|
|
76
80
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info(`Total HUE resources count : ${node.hueAllResources.length}`);
|
|
77
81
|
} catch (error) {
|
|
78
|
-
node.linkStatus = "disconnected";
|
|
79
82
|
node.nodeClients.forEach((_oClient) => {
|
|
80
83
|
setTimeout(() => {
|
|
81
84
|
_oClient.setNodeStatusHue({
|
|
@@ -93,7 +96,6 @@ module.exports = (RED) => {
|
|
|
93
96
|
});
|
|
94
97
|
|
|
95
98
|
node.hueManager.on("disconnected", () => {
|
|
96
|
-
node.linkStatus = "disconnected";
|
|
97
99
|
node.nodeClients.forEach((_oClient) => {
|
|
98
100
|
_oClient.setNodeStatusHue({
|
|
99
101
|
fill: "red",
|
|
@@ -114,10 +116,11 @@ module.exports = (RED) => {
|
|
|
114
116
|
node.timerHUEConfigCheckState = setTimeout(() => {
|
|
115
117
|
(async () => {
|
|
116
118
|
if (node.linkStatus === "disconnected") {
|
|
119
|
+
// The hueEngine is already connected to the HUE Bridge
|
|
117
120
|
try {
|
|
118
121
|
await node.initHUEConnection();
|
|
119
122
|
} catch (error) {
|
|
120
|
-
node.
|
|
123
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`Errore hue-config: node.startWatchdogTimer: ${error.message}`);
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
node.startWatchdogTimer();
|
|
@@ -126,6 +129,7 @@ module.exports = (RED) => {
|
|
|
126
129
|
};
|
|
127
130
|
node.startWatchdogTimer();
|
|
128
131
|
|
|
132
|
+
|
|
129
133
|
// Functions called from the nodes ----------------------------------------------------------------
|
|
130
134
|
// Query the HUE Bridge to return the resources
|
|
131
135
|
node.loadResourcesFromHUEBridge = async () => {
|
|
@@ -457,7 +461,6 @@ module.exports = (RED) => {
|
|
|
457
461
|
});
|
|
458
462
|
}
|
|
459
463
|
} else {
|
|
460
|
-
node.linkStatus = "disconnected";
|
|
461
464
|
// Add _Node to the clients array
|
|
462
465
|
_Node.setNodeStatusHue({
|
|
463
466
|
fill: "grey",
|
|
@@ -30,16 +30,23 @@ module.exports = function (RED) {
|
|
|
30
30
|
node.setNodeStatus = ({
|
|
31
31
|
fill, shape, text, payload,
|
|
32
32
|
}) => {
|
|
33
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (payload === undefined) payload = '';
|
|
35
|
+
const dDate = new Date();
|
|
36
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
37
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
38
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
39
|
+
} catch (error) { }
|
|
34
40
|
};
|
|
35
41
|
// Used to call the status update from the HUE config node.
|
|
36
|
-
node.setNodeStatusHue = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
43
|
+
try {
|
|
44
|
+
if (payload === undefined) payload = '';
|
|
45
|
+
const dDate = new Date();
|
|
46
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
47
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
48
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
49
|
+
} catch (error) { }
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -41,16 +41,23 @@ module.exports = function (RED) {
|
|
|
41
41
|
node.setNodeStatus = ({
|
|
42
42
|
fill, shape, text, payload,
|
|
43
43
|
}) => {
|
|
44
|
-
|
|
44
|
+
try {
|
|
45
|
+
if (payload === undefined) payload = '';
|
|
46
|
+
const dDate = new Date();
|
|
47
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
48
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
49
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
50
|
+
} catch (error) { }
|
|
45
51
|
};
|
|
46
52
|
// Used to call the status update from the HUE config node.
|
|
47
|
-
node.setNodeStatusHue = ({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
54
|
+
try {
|
|
55
|
+
if (payload === undefined) payload = '';
|
|
56
|
+
const dDate = new Date();
|
|
57
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
58
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
59
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
60
|
+
} catch (error) { }
|
|
54
61
|
};
|
|
55
62
|
|
|
56
63
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -26,19 +26,27 @@ module.exports = function (RED) {
|
|
|
26
26
|
node.initializingAtStart = false
|
|
27
27
|
|
|
28
28
|
// Used to call the status update from the config node.
|
|
29
|
-
node.setNodeStatus = ({
|
|
30
|
-
|
|
29
|
+
node.setNodeStatus = ({
|
|
30
|
+
fill, shape, text, payload,
|
|
31
|
+
}) => {
|
|
32
|
+
try {
|
|
33
|
+
if (payload === undefined) payload = '';
|
|
34
|
+
const dDate = new Date();
|
|
35
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
36
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
37
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
38
|
+
} catch (error) { }
|
|
39
|
+
};
|
|
31
40
|
// Used to call the status update from the HUE config node.
|
|
32
41
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
shape,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
+
try {
|
|
43
|
+
if (payload === undefined) payload = '';
|
|
44
|
+
const dDate = new Date();
|
|
45
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
46
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
47
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
48
|
+
} catch (error) { }
|
|
49
|
+
};
|
|
42
50
|
|
|
43
51
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
44
52
|
node.handleSend = (msg) => {
|
|
@@ -104,13 +104,26 @@ module.exports = function (RED) {
|
|
|
104
104
|
// Used to call the status update from the config node.
|
|
105
105
|
node.setNodeStatus = ({
|
|
106
106
|
fill, shape, text, payload,
|
|
107
|
-
}) => {
|
|
107
|
+
}) => {
|
|
108
|
+
try {
|
|
109
|
+
if (node.currentHUEDevice?.on?.on === true) { fill = "blue"; shape = "dot" } else { fill = "blue"; shape = "ring" };
|
|
110
|
+
if (payload === undefined) payload = '';
|
|
111
|
+
const dDate = new Date();
|
|
112
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
113
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
114
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
115
|
+
} catch (error) { }
|
|
116
|
+
};
|
|
108
117
|
// Used to call the status update from the HUE config node.
|
|
109
118
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
try {
|
|
120
|
+
if (node.currentHUEDevice?.on?.on === true) { fill = "blue"; shape = "dot" } else { fill = "blue"; shape = "ring" };
|
|
121
|
+
if (payload === undefined) payload = '';
|
|
122
|
+
const dDate = new Date();
|
|
123
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
124
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
125
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
126
|
+
} catch (error) { }
|
|
114
127
|
};
|
|
115
128
|
|
|
116
129
|
function getRandomIntInclusive(min, max) {
|
|
@@ -27,15 +27,26 @@ module.exports = function (RED) {
|
|
|
27
27
|
node.currentDeviceValue = 0;
|
|
28
28
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
30
|
-
node.setNodeStatus = ({
|
|
31
|
-
|
|
30
|
+
node.setNodeStatus = ({
|
|
31
|
+
fill, shape, text, payload,
|
|
32
|
+
}) => {
|
|
33
|
+
try {
|
|
34
|
+
if (payload === undefined) payload = '';
|
|
35
|
+
const dDate = new Date();
|
|
36
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
37
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
38
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
39
|
+
} catch (error) { }
|
|
32
40
|
};
|
|
33
41
|
// Used to call the status update from the HUE config node.
|
|
34
42
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
try {
|
|
44
|
+
if (payload === undefined) payload = '';
|
|
45
|
+
const dDate = new Date();
|
|
46
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
47
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
48
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
49
|
+
} catch (error) { }
|
|
39
50
|
};
|
|
40
51
|
|
|
41
52
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -26,13 +26,26 @@ module.exports = function (RED) {
|
|
|
26
26
|
node.initializingAtStart = false;
|
|
27
27
|
|
|
28
28
|
// Used to call the status update from the config node.
|
|
29
|
-
node.setNodeStatus = ({
|
|
29
|
+
node.setNodeStatus = ({
|
|
30
|
+
fill, shape, text, payload,
|
|
31
|
+
}) => {
|
|
32
|
+
try {
|
|
33
|
+
if (payload === undefined) payload = '';
|
|
34
|
+
const dDate = new Date();
|
|
35
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
36
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
37
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
38
|
+
} catch (error) { }
|
|
39
|
+
};
|
|
30
40
|
// Used to call the status update from the HUE config node.
|
|
31
41
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
try {
|
|
43
|
+
if (payload === undefined) payload = '';
|
|
44
|
+
const dDate = new Date();
|
|
45
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
46
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
47
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
48
|
+
} catch (error) { }
|
|
36
49
|
};
|
|
37
50
|
|
|
38
51
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -39,15 +39,26 @@ module.exports = function (RED) {
|
|
|
39
39
|
config.selectedModeTabNumber = config.selectedModeTabNumber === undefined ? 0 : Number(config.selectedModeTabNumber); // Transform as number
|
|
40
40
|
|
|
41
41
|
// Used to call the status update from the config node.
|
|
42
|
-
node.setNodeStatus = ({
|
|
43
|
-
|
|
42
|
+
node.setNodeStatus = ({
|
|
43
|
+
fill, shape, text, payload,
|
|
44
|
+
}) => {
|
|
45
|
+
try {
|
|
46
|
+
if (payload === undefined) payload = '';
|
|
47
|
+
const dDate = new Date();
|
|
48
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
49
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
50
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
51
|
+
} catch (error) { }
|
|
44
52
|
};
|
|
45
53
|
// Used to call the status update from the HUE config node.
|
|
46
54
|
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
try {
|
|
56
|
+
if (payload === undefined) payload = '';
|
|
57
|
+
const dDate = new Date();
|
|
58
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
59
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
60
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
61
|
+
} catch (error) { }
|
|
51
62
|
};
|
|
52
63
|
|
|
53
64
|
// This function is called by the knx-hue config node
|
|
@@ -32,15 +32,23 @@ module.exports = function (RED) {
|
|
|
32
32
|
node.setNodeStatus = ({
|
|
33
33
|
fill, shape, text, payload,
|
|
34
34
|
}) => {
|
|
35
|
+
try {
|
|
36
|
+
if (payload === undefined) payload = '';
|
|
37
|
+
const dDate = new Date();
|
|
38
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
39
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
40
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
41
|
+
} catch (error) { }
|
|
35
42
|
};
|
|
36
43
|
// Used to call the status update from the HUE config node.
|
|
37
|
-
node.setNodeStatusHue = ({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
45
|
+
try {
|
|
46
|
+
if (payload === undefined) payload = '';
|
|
47
|
+
const dDate = new Date();
|
|
48
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
49
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
50
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
51
|
+
} catch (error) { }
|
|
44
52
|
};
|
|
45
53
|
|
|
46
54
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -30,16 +30,23 @@ module.exports = function (RED) {
|
|
|
30
30
|
node.setNodeStatus = ({
|
|
31
31
|
fill, shape, text, payload,
|
|
32
32
|
}) => {
|
|
33
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (payload === undefined) payload = '';
|
|
35
|
+
const dDate = new Date();
|
|
36
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
37
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
38
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
39
|
+
} catch (error) { }
|
|
34
40
|
};
|
|
35
41
|
// Used to call the status update from the HUE config node.
|
|
36
|
-
node.setNodeStatusHue = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
43
|
+
try {
|
|
44
|
+
if (payload === undefined) payload = '';
|
|
45
|
+
const dDate = new Date();
|
|
46
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
47
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
48
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
49
|
+
} catch (error) { }
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -30,16 +30,23 @@ module.exports = function (RED) {
|
|
|
30
30
|
node.setNodeStatus = ({
|
|
31
31
|
fill, shape, text, payload,
|
|
32
32
|
}) => {
|
|
33
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (payload === undefined) payload = '';
|
|
35
|
+
const dDate = new Date();
|
|
36
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
37
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
38
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
39
|
+
} catch (error) { }
|
|
34
40
|
};
|
|
35
41
|
// Used to call the status update from the HUE config node.
|
|
36
|
-
node.setNodeStatusHue = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
43
|
+
try {
|
|
44
|
+
if (payload === undefined) payload = '';
|
|
45
|
+
const dDate = new Date();
|
|
46
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
47
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
48
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
49
|
+
} catch (error) { }
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -30,16 +30,23 @@ module.exports = function (RED) {
|
|
|
30
30
|
node.setNodeStatus = ({
|
|
31
31
|
fill, shape, text, payload,
|
|
32
32
|
}) => {
|
|
33
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (payload === undefined) payload = '';
|
|
35
|
+
const dDate = new Date();
|
|
36
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
37
|
+
node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
38
|
+
node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') });
|
|
39
|
+
} catch (error) { }
|
|
34
40
|
};
|
|
35
41
|
// Used to call the status update from the HUE config node.
|
|
36
|
-
node.setNodeStatusHue = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
|
|
43
|
+
try {
|
|
44
|
+
if (payload === undefined) payload = '';
|
|
45
|
+
const dDate = new Date();
|
|
46
|
+
payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString();
|
|
47
|
+
node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`;
|
|
48
|
+
node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') });
|
|
49
|
+
} catch (error) { }
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
package/nodes/utils/hueEngine.js
CHANGED
|
@@ -11,12 +11,13 @@ class classHUE extends EventEmitter {
|
|
|
11
11
|
|
|
12
12
|
constructor(_hueBridgeIP, _username, _clientkey, _bridgeid, _sysLogger) {
|
|
13
13
|
super();
|
|
14
|
+
this.HUEBridgeConnectionStatus = "disconnected";
|
|
15
|
+
this.exitAllQueues = false;
|
|
14
16
|
this.hueBridgeIP = _hueBridgeIP;
|
|
15
17
|
this.username = _username;
|
|
16
18
|
this.clientkey = _clientkey;
|
|
17
19
|
this.bridgeid = _bridgeid;
|
|
18
20
|
this.commandQueue = [];
|
|
19
|
-
this.closePushEventStream = false;
|
|
20
21
|
// eslint-disable-next-line max-len
|
|
21
22
|
setTimeout(this.handleQueue, 10000); // First start. Allow the KNX to connect
|
|
22
23
|
this.sysLogger = _sysLogger;
|
|
@@ -24,6 +25,9 @@ class classHUE extends EventEmitter {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
Connect = () => {
|
|
28
|
+
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
29
|
+
this.HUEBridgeConnectionStatus = "disconnected";
|
|
30
|
+
this.exitAllQueues = false;
|
|
27
31
|
|
|
28
32
|
const options = {
|
|
29
33
|
headers: {
|
|
@@ -80,12 +84,29 @@ class classHUE extends EventEmitter {
|
|
|
80
84
|
this.es.onopen = () => {
|
|
81
85
|
// if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: SSE-Connected')
|
|
82
86
|
this.emit("connected");
|
|
87
|
+
this.HUEBridgeConnectionStatus = "connected";
|
|
83
88
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info(`KNXUltimatehueEngine: classHUE: this.es.onopen: connected`);
|
|
84
89
|
// Check wether the hue bridge is connected or not
|
|
85
90
|
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
86
91
|
this.timerCheckConnected = setInterval(() => {
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
(async () => {
|
|
93
|
+
try {
|
|
94
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug(`KNXUltimatehueEngine: classHUE: processQueueItem: Pinging...`);
|
|
95
|
+
const jReturn = await this.hueApiV2.get('/resource/bridge');
|
|
96
|
+
if (!Array.isArray(jReturn) || jReturn.length < 1) throw new Error("jReturn: not an array or array empty")
|
|
97
|
+
this.HUEBridgeConnectionStatus = "connected";
|
|
98
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug(`KNXUltimatehueEngine: classHUE: processQueueItem: Ping OK`);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error(`KNXUltimatehueEngine: classHUE: processQueueItem: Ping ERROR: ${error.message}`);
|
|
101
|
+
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
102
|
+
this.commandQueue = [];
|
|
103
|
+
this.emit("disconnected");
|
|
104
|
+
try {
|
|
105
|
+
this.close();
|
|
106
|
+
} catch (error) { }
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
}, 20000);
|
|
89
110
|
};
|
|
90
111
|
|
|
91
112
|
this.es.onerror = (error) => {
|
|
@@ -149,20 +170,6 @@ class classHUE extends EventEmitter {
|
|
|
149
170
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error(`KNXUltimatehueEngine: classHUE: processQueueItem: stopScene: ${error.message}`);
|
|
150
171
|
}
|
|
151
172
|
break;
|
|
152
|
-
case "Ping":
|
|
153
|
-
try {
|
|
154
|
-
const jReturn = await this.hueApiV2.get('/resource/bridge');
|
|
155
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.debug(`KNXUltimatehueEngine: classHUE: processQueueItem: Ping OK: Bridge id:${jReturn[0].bridge_id}`);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error(`KNXUltimatehueEngine: classHUE: processQueueItem: Ping ERROR: ${error.message}`);
|
|
158
|
-
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
159
|
-
this.commandQueue = [];
|
|
160
|
-
try {
|
|
161
|
-
this.close();
|
|
162
|
-
} catch (error) { }
|
|
163
|
-
this.emit("disconnected");
|
|
164
|
-
}
|
|
165
|
-
break;
|
|
166
173
|
default:
|
|
167
174
|
break;
|
|
168
175
|
}
|
|
@@ -190,7 +197,7 @@ class classHUE extends EventEmitter {
|
|
|
190
197
|
//}
|
|
191
198
|
}
|
|
192
199
|
await pleaseWait(150);
|
|
193
|
-
} while (this.
|
|
200
|
+
} while (!this.exitAllQueues);
|
|
194
201
|
//console.log("\x1b[42m End processing commandQueue \x1b[0m " + new Date().toTimeString(), this.commandQueue.length);
|
|
195
202
|
};
|
|
196
203
|
|
|
@@ -212,8 +219,10 @@ class classHUE extends EventEmitter {
|
|
|
212
219
|
|
|
213
220
|
close = async () =>
|
|
214
221
|
new Promise((resolve, reject) => {
|
|
222
|
+
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
215
223
|
try {
|
|
216
|
-
this.
|
|
224
|
+
this.HUEBridgeConnectionStatus = "disconnected";
|
|
225
|
+
this.exitAllQueues = true;
|
|
217
226
|
setTimeout(() => {
|
|
218
227
|
try {
|
|
219
228
|
if (this.es !== null && this.es !== undefined) this.es.close();
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.3.
|
|
6
|
+
"version": "3.3.19",
|
|
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",
|