node-red-contrib-knx-ultimate 3.3.2 → 3.3.4
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 +5 -0
- package/nodes/commonFunctions.js +9 -23
- package/nodes/knxUltimate-config.html +75 -25
- package/nodes/knxUltimate-config.js +6 -8
- package/nodes/utils/hueEngine.js +1 -1
- package/nodes/utils/utils.js +27 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 3.3.3** - November 2024<br/>
|
|
10
|
+
- KNX Config Node: Automatic KNX Gateway discover in the gateway node config window.<br/>
|
|
11
|
+
- KNX Engine: new: new telegram sequencer waiter, for more accurate timing in slow or sliggish computers.<br/>
|
|
12
|
+
- KNX Engine: bunp 4.0.0-beta.7 .<br/>
|
|
13
|
+
|
|
9
14
|
**Version 3.3.0** - November 2024<br/>
|
|
10
15
|
- KNX Engine: explicitly set the local port of the unicast socket on 3671 and the local IP of the multicast to 0.0.0.0.<br/>
|
|
11
16
|
- KNX Engine: many engine adaptation for the upcoming KNX-Secure implementation.<br/>
|
package/nodes/commonFunctions.js
CHANGED
|
@@ -61,6 +61,14 @@ module.exports = (RED) => {
|
|
|
61
61
|
function commonFunctions() {
|
|
62
62
|
var node = this;
|
|
63
63
|
|
|
64
|
+
// Gather infos about all interfaces on the lan and provides a static variable utils.aDiscoveredknxGateways
|
|
65
|
+
try {
|
|
66
|
+
require('./utils/utils').DiscoverKNXGateways()
|
|
67
|
+
} catch (error) {
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
64
72
|
|
|
65
73
|
// 11/03/2020 Delete scene saved file, from html
|
|
66
74
|
RED.httpAdmin.get('/knxultimateCheckHueConnected', (req, res) => {
|
|
@@ -310,29 +318,7 @@ module.exports = (RED) => {
|
|
|
310
318
|
|
|
311
319
|
// 14/08/2019 Endpoint for retrieving the ethernet interfaces
|
|
312
320
|
RED.httpAdmin.get("/knxUltimateDiscoverKNXGateways", RED.auth.needsPermission("knxUltimate-config.read"), async function (req, res) {
|
|
313
|
-
|
|
314
|
-
async function search() {
|
|
315
|
-
let jRet = [];
|
|
316
|
-
try {
|
|
317
|
-
const knxGateways = await KNXClient.discover();
|
|
318
|
-
// For each discovered gateway, get all possible device descriptions (usually only one)
|
|
319
|
-
// A description is a JSON object containing all details of the device and also what type of connection (Multicast, unicast, etc), it suppports
|
|
320
|
-
for (let index = 0; index < knxGateways.length; index++) {
|
|
321
|
-
const element = knxGateways[index];
|
|
322
|
-
const [ip, port] = element.split(':')
|
|
323
|
-
const descriptionsJSON = await KNXClient.getGatewayDescription(ip, port, 5000)
|
|
324
|
-
for (let index = 0; index < descriptionsJSON.length; index++) {
|
|
325
|
-
const element = descriptionsJSON[index];
|
|
326
|
-
jRet.push({ ip: ip, port: port, name: element.deviceInfo.name, physAddr: element.deviceInfo.formattedAddress });
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
res.json(jRet);
|
|
330
|
-
} catch (error) { }
|
|
331
|
-
}
|
|
332
|
-
search();
|
|
333
|
-
} catch (error) {
|
|
334
|
-
res.json({ error: error.stack });
|
|
335
|
-
}
|
|
321
|
+
res.json(require("./utils/utils").aDiscoveredknxGateways);
|
|
336
322
|
});
|
|
337
323
|
|
|
338
324
|
// 12/08/2021 Endpoint for deleting the GA persistent file for the current gateway
|
|
@@ -34,6 +34,32 @@
|
|
|
34
34
|
} catch (error) { }
|
|
35
35
|
|
|
36
36
|
var node = this;
|
|
37
|
+
// TIMER BLINK ####################################################
|
|
38
|
+
let blinkStatus = 2;
|
|
39
|
+
let timerBlinkBackground;
|
|
40
|
+
function blinkBackgroundArray(_arrayElementIDwithHashAtTheBeginning) {
|
|
41
|
+
if (timerBlinkBackground !== undefined) clearInterval(timerBlinkBackground);
|
|
42
|
+
timerBlinkBackground = setInterval(() => {
|
|
43
|
+
for (let index = 0; index < _arrayElementIDwithHashAtTheBeginning.length; index++) {
|
|
44
|
+
const _elementIDwithHashAtTheBeginning = _arrayElementIDwithHashAtTheBeginning[index];
|
|
45
|
+
if (isEven(blinkStatus)) $(_elementIDwithHashAtTheBeginning).css("background-color", "lightgreen");
|
|
46
|
+
if (!isEven(blinkStatus)) $(_elementIDwithHashAtTheBeginning).css("background-color", "");
|
|
47
|
+
}
|
|
48
|
+
blinkStatus += 1;
|
|
49
|
+
if (blinkStatus >= 14) {
|
|
50
|
+
clearInterval(timerBlinkBackground);
|
|
51
|
+
blinkStatus = 2;
|
|
52
|
+
for (let index = 0; index < _arrayElementIDwithHashAtTheBeginning.length; index++) {
|
|
53
|
+
const _elementIDwithHashAtTheBeginning = _arrayElementIDwithHashAtTheBeginning[index];
|
|
54
|
+
$(_elementIDwithHashAtTheBeginning).css("background-color", "");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}, 100);
|
|
58
|
+
}
|
|
59
|
+
function isEven(n) {
|
|
60
|
+
return (n % 2 == 0);
|
|
61
|
+
}
|
|
62
|
+
// ################################################################
|
|
37
63
|
|
|
38
64
|
// 22/07/2021 Main tab
|
|
39
65
|
$("#tabsMain").tabs({
|
|
@@ -44,28 +70,52 @@
|
|
|
44
70
|
});
|
|
45
71
|
|
|
46
72
|
// Autocomplete with KNX IP Interfaces
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
let aKNXInterfaces = [];
|
|
74
|
+
$.getJSON("knxUltimateDiscoverKNXGateways?" + { _: new Date().getTime() }, (data) => {
|
|
75
|
+
for (let index = 0; index < data.length; index++) {
|
|
76
|
+
const element = data[index];
|
|
77
|
+
const [ip, port, name, address] = element.split(':');
|
|
78
|
+
// Aggiungi l'elemento con descrizione e valore
|
|
79
|
+
aKNXInterfaces.push({
|
|
80
|
+
label: `${name} -> ${ip}:${port} phys addr:${address}`, // Testo visibile nella lista
|
|
81
|
+
value: element // Valore selezionato
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
$("#interfaces-count").text(`${aKNXInterfaces.length} interfaces found.`);
|
|
85
|
+
// Configura l'autocompletamento per il campo di input
|
|
86
|
+
$("#node-config-input-host").autocomplete({
|
|
87
|
+
minLength: 0, // Mostra suggerimenti subito
|
|
88
|
+
source: aKNXInterfaces, // Dati per il completamento
|
|
89
|
+
select: function (event, ui) {
|
|
90
|
+
// Quando l'utente seleziona un elemento, aggiorna il valore del campo
|
|
91
|
+
const [ip, port, name, address] = ui.item.value.split(':');
|
|
92
|
+
$("#node-config-input-host").val(ip);
|
|
93
|
+
$("#node-config-input-port").val(port);
|
|
94
|
+
$("#node-config-input-name").val(name);
|
|
95
|
+
$("#node-config-input-physAddr").val(address.split(".")[0] + '.' + address.split(".")[1] + '.' + Math.floor(Math.random() * 256));
|
|
96
|
+
blinkBackgroundArray(["#node-config-input-host", "#node-config-input-port", "#node-config-input-name", "#node-config-input-physAddr"]);
|
|
97
|
+
return false; // Evita il comportamento predefinito del browser
|
|
98
|
+
},
|
|
99
|
+
focus: function (event, ui) {
|
|
100
|
+
// Mantieni il valore corrente durante il focus, ma non cambiare il valore effettivo
|
|
101
|
+
$("#node-config-input-host").val(ui.item.value.split(":"[0]));
|
|
102
|
+
return false; // Evita di aggiornare il campo con il valore selezionato
|
|
103
|
+
}
|
|
104
|
+
}).on("focus", function () {
|
|
105
|
+
// Apri l'autocomplete quando il campo riceve il focus
|
|
106
|
+
$(this).autocomplete("search", "");
|
|
107
|
+
}).on("click", function () {
|
|
108
|
+
// Apri l'autocomplete quando il campo riceve il focus
|
|
109
|
+
$(this).autocomplete("search", "");
|
|
110
|
+
}).autocomplete("instance")._renderItem = function (ul, item) {
|
|
111
|
+
// Personalizza l'aspetto degli elementi della lista
|
|
112
|
+
const [ip, port, name, address] = item.value.split(':');
|
|
113
|
+
const color = (ip === "224.0.23.12") ? "gray" : "green"; // Condizione
|
|
114
|
+
return $("<li>")
|
|
115
|
+
.append(`<div style="color: ${color};"><b>${ip}:${port}</b> -> ${name} - Address:${address}</div>`) // Mostra la descrizione completa
|
|
116
|
+
.appendTo(ul);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
69
119
|
|
|
70
120
|
|
|
71
121
|
$("#node-config-input-KNXEthInterface").append($("<option></option>")
|
|
@@ -220,9 +270,9 @@
|
|
|
220
270
|
<input type="text" id="node-config-input-name" style="width: 200px">
|
|
221
271
|
</div>
|
|
222
272
|
<div class="form-row">
|
|
223
|
-
<label for="node-config-input-host" style="width: 200px">
|
|
224
|
-
<
|
|
225
|
-
|
|
273
|
+
<label for="node-config-input-host" style="width: 200px"><i class="fa fa-server"></i> IP/Hostname</label>
|
|
274
|
+
<input type="text" id="node-config-input-host" style="width: 200px"><br/>
|
|
275
|
+
<span id="interfaces-count" style="font-size: 12px; color:#377e00 ; margin-top: 2px;"></span>
|
|
226
276
|
</div>
|
|
227
277
|
|
|
228
278
|
<!-- KNX Secure / Unsecure tabbed selector-->
|
|
@@ -13,7 +13,7 @@ const dptlib = require('knxultimate').dptlib;
|
|
|
13
13
|
const loggerClass = require('./utils/sysLogger')
|
|
14
14
|
// const { Server } = require('http')
|
|
15
15
|
const payloadRounder = require("./utils/payloadManipulation");
|
|
16
|
-
|
|
16
|
+
const utils = require('./utils/utils');
|
|
17
17
|
|
|
18
18
|
// DATAPONT MANIPULATION HELPERS
|
|
19
19
|
// ####################
|
|
@@ -119,6 +119,7 @@ module.exports = (RED) => {
|
|
|
119
119
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("IP Protocol AUTO SET to " + node.hostProtocol + ", based on IP " + node.host);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
|
|
122
123
|
node.setAllClientsStatus = (_status, _color, _text) => {
|
|
123
124
|
node.nodeClients.forEach((oClient) => {
|
|
124
125
|
try {
|
|
@@ -525,7 +526,8 @@ module.exports = (RED) => {
|
|
|
525
526
|
isSecureKNXEnabled: node.knxSecureSelected,
|
|
526
527
|
jKNXSecureKeyring: node.jKNXSecureKeyring,
|
|
527
528
|
localIPAddress: "", // Riempito da KNXEngine
|
|
528
|
-
KNXQueueSendIntervalMilliseconds: Number(node.delaybetweentelegrams)
|
|
529
|
+
KNXQueueSendIntervalMilliseconds: Number(node.delaybetweentelegrams),
|
|
530
|
+
connectionKeepAliveTimeout: 30 // Every 30 seconds, send a connectionstatus_request
|
|
529
531
|
};
|
|
530
532
|
// 11/07/2022 Test if the IP is a valid one or is a DNS Name
|
|
531
533
|
switch (net.isIP(node.host)) {
|
|
@@ -647,11 +649,7 @@ module.exports = (RED) => {
|
|
|
647
649
|
node.Disconnect("Disconnected by error " + (err.message === undefined ? err : err.message), "red");
|
|
648
650
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error("Disconnected by: " + (err.message === undefined ? err : err.message));
|
|
649
651
|
});
|
|
650
|
-
|
|
651
|
-
// node.knxConnection.on(knx.KNXClientEvents.discover, info => {
|
|
652
|
-
// const [ip, port] = info.split(":");
|
|
653
|
-
// discoverCB(ip, port);
|
|
654
|
-
// });
|
|
652
|
+
|
|
655
653
|
node.knxConnection.on(knx.KNXClientEvents.disconnected, (info) => {
|
|
656
654
|
if (node.linkStatus !== "disconnected") {
|
|
657
655
|
node.linkStatus = "disconnected";
|
|
@@ -1838,7 +1836,7 @@ module.exports = (RED) => {
|
|
|
1838
1836
|
);
|
|
1839
1837
|
// node.initKNXConnection();
|
|
1840
1838
|
}
|
|
1841
|
-
},
|
|
1839
|
+
}, 30000);
|
|
1842
1840
|
|
|
1843
1841
|
node.Disconnect = async (_sNodeStatus = "", _sColor = "grey") => {
|
|
1844
1842
|
if (node.linkStatus === "disconnected") {
|
package/nodes/utils/hueEngine.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const { EventEmitter } = require("events");
|
|
3
3
|
const EventSource = require("eventsource");
|
|
4
4
|
const http = require("./http");
|
|
5
|
-
const
|
|
5
|
+
const { setTimeout: pleaseWait } = require('timers/promises');
|
|
6
6
|
//const { forEach } = require("lodash");
|
|
7
7
|
// Configura il rate limiter
|
|
8
8
|
//const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 150 }); // HUE telegram interval
|
package/nodes/utils/utils.js
CHANGED
|
@@ -58,4 +58,31 @@ module.exports.fetchFromObject = function fetchFromObject(
|
|
|
58
58
|
const DEFAULTTRANSLATIONINPUT =
|
|
59
59
|
"on:true\noff:false\nactive:true\ninactive:false\nopen:true\nclosed:false\nclose:false\n1:true\n0:false\ntrue:true\nfalse:false\nhome:true\nnot_home:false\nnormal:false\nviolated:true";
|
|
60
60
|
|
|
61
|
+
// 14/08/2019 Endpoint for retrieving the ethernet interfaces
|
|
61
62
|
|
|
63
|
+
module.exports.DiscoverKNXGateways = async function DiscoverKNXGateways() {
|
|
64
|
+
if (bDiscoverKNXGatewaysRunning) return;
|
|
65
|
+
bDiscoverKNXGatewaysRunning = true;
|
|
66
|
+
const KNXClient = require('knxultimate');
|
|
67
|
+
try {
|
|
68
|
+
if (this.aDiscoveredknxGateways === undefined) {
|
|
69
|
+
this.aDiscoveredknxGateways = await KNXClient.KNXClient.discover(2000);
|
|
70
|
+
this.aDiscoveredknxGateways.push('224.0.23.12:3671:Multicast Address:15.15.199')
|
|
71
|
+
bDiscoverKNXGatewaysRunning = false;
|
|
72
|
+
return this.aDiscoveredknxGateways;
|
|
73
|
+
} else {
|
|
74
|
+
bDiscoverKNXGatewaysRunning = false;
|
|
75
|
+
return this.aDiscoveredknxGateways;
|
|
76
|
+
}
|
|
77
|
+
} catch (error) { bDiscoverKNXGatewaysRunning = false; this.aDiscoveredknxGateways = []; return this.aDiscoveredknxGateways; }
|
|
78
|
+
}
|
|
79
|
+
let bDiscoverKNXGatewaysRunning = false;
|
|
80
|
+
module.exports.aDiscoveredknxGateways;
|
|
81
|
+
|
|
82
|
+
module.exports.getDiscoveredknxGateways = function () {
|
|
83
|
+
return module.exports.aDiscoveredknxGateways;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
module.exports.setDiscoveredknxGateways = function (value) {
|
|
87
|
+
module.exports.aDiscoveredknxGateways = value;
|
|
88
|
+
};
|
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.4",
|
|
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",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dns-sync": "0.2.1",
|
|
12
12
|
"eventsource": "2.0.2",
|
|
13
13
|
"js-yaml": "4.1.0",
|
|
14
|
-
"knxultimate": "4.
|
|
14
|
+
"knxultimate": "4.1.0-beta.1",
|
|
15
15
|
"lodash": "4.17.21",
|
|
16
16
|
"node-color-log": "12.0.1",
|
|
17
17
|
"mkdirp": "3.0.1",
|