node-red-contrib-knx-ultimate 3.2.0 → 3.2.1
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 -1
- package/nodes/commonFunctions.js +0 -1
- package/nodes/hue-config.js +12 -6
- package/nodes/knxUltimate-config copy.html +456 -0
- package/nodes/knxUltimate-config copy.js +1939 -0
- package/nodes/knxUltimate-config.html +4 -9
- package/nodes/knxUltimate-config.js +128 -213
- package/nodes/knxUltimate.js +41 -32
- package/nodes/knxUltimateAlerter.js +11 -15
- package/nodes/knxUltimateAutoResponder.js +21 -13
- package/nodes/knxUltimateGarageDoorBarrierOpener.js +16 -8
- package/nodes/knxUltimateGlobalContext.js +10 -10
- package/nodes/knxUltimateHueBattery.js +8 -8
- package/nodes/knxUltimateHueButton.js +9 -9
- package/nodes/knxUltimateHueContactSensor.js +7 -7
- package/nodes/knxUltimateHueLight.js +26 -26
- package/nodes/knxUltimateHueLightSensor.js +8 -8
- package/nodes/knxUltimateHueMotion.js +7 -7
- package/nodes/knxUltimateHueScene.js +17 -9
- package/nodes/knxUltimateHueTapDial.js +13 -13
- package/nodes/knxUltimateHueTemperatureSensor.js +8 -8
- package/nodes/knxUltimateHueZigbeeConnectivity.js +8 -8
- package/nodes/knxUltimateHuedevice_software_update.js +8 -8
- package/nodes/knxUltimateLoadControl.js +24 -21
- package/nodes/knxUltimateLogger.js +8 -8
- package/nodes/knxUltimateSceneController.js +20 -13
- package/nodes/knxUltimateViewer.js +8 -8
- package/nodes/knxUltimateWatchDog.js +14 -14
- package/nodes/utils/http.js +0 -1
- package/nodes/utils/hueEngine.js +13 -6
- package/nodes/utils/payloadManipulation.js +2 -2
- package/nodes/utils/sysLogger.js +23 -60
- package/package.json +3 -3
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
|
|
2
|
+
// 10/09/2024 Setup the color logger
|
|
3
|
+
loggerSetup = (options) => {
|
|
4
|
+
let clog = require("node-color-log").createNamedLogger(options.setPrefix);
|
|
5
|
+
clog.setLevel(options.loglevel);
|
|
6
|
+
clog.setDate(() => (new Date()).toLocaleString());
|
|
7
|
+
return clog;
|
|
8
|
+
}
|
|
2
9
|
module.exports = function (RED) {
|
|
3
10
|
function knxUltimateLoadControl(config) {
|
|
4
11
|
// const Address = require('knxultimate')
|
|
5
12
|
|
|
6
13
|
RED.nodes.createNode(this, config)
|
|
7
14
|
const node = this
|
|
8
|
-
node.
|
|
15
|
+
node.serverKNX = RED.nodes.getNode(config.server)
|
|
9
16
|
node.name = config.name || 'KNX Load Control'
|
|
10
17
|
node.topic = config.topic
|
|
11
18
|
node.dpt = config.dpt
|
|
@@ -31,6 +38,8 @@ module.exports = function (RED) {
|
|
|
31
38
|
node.mainTimer = null
|
|
32
39
|
node.totalWatt = 0 // Current total watt consumption
|
|
33
40
|
node.wattLimit = config.wattLimit === undefined ? 3000 : Number(config.wattLimit)
|
|
41
|
+
node.sysLogger = loggerSetup({ loglevel: node.serverKNX.loglevel, setPrefix: "knxUltimateLoadControl.js" }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
|
|
42
|
+
|
|
34
43
|
node.deviceList = []
|
|
35
44
|
for (let index = 1; index < 6; index++) {
|
|
36
45
|
// Eval, the magic. Fill in the device list. DEFINITION DEVICELIST
|
|
@@ -46,15 +55,9 @@ module.exports = function (RED) {
|
|
|
46
55
|
})
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
try {
|
|
50
|
-
node.sysLogger = require('./utils/sysLogger.js').get({ loglevel: node.server.loglevel || 'error' }) // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
|
|
51
|
-
} catch (error) {
|
|
52
|
-
node.sysLogger = 'error'
|
|
53
|
-
}
|
|
54
|
-
|
|
55
58
|
// Used to call the status update from the config node.
|
|
56
59
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
57
|
-
if (node.
|
|
60
|
+
if (node.serverKNX === null) return
|
|
58
61
|
// Log only service statuses, not the GA values
|
|
59
62
|
try {
|
|
60
63
|
if (dpt !== '') return
|
|
@@ -117,9 +120,9 @@ module.exports = function (RED) {
|
|
|
117
120
|
|
|
118
121
|
// 03/02/2022 perform a read on all GA in the list
|
|
119
122
|
node.initialReadAllDevicesInRules = () => {
|
|
120
|
-
if (node.
|
|
123
|
+
if (node.serverKNX) {
|
|
121
124
|
// Read status of the Total Power GA
|
|
122
|
-
if (node.topic !== undefined && node.topic !== null && node.topic !== '') node.
|
|
125
|
+
if (node.topic !== undefined && node.topic !== null && node.topic !== '') node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: node.topic, payload: '', dpt: '', outputtype: 'read', nodecallerid: node.id })
|
|
123
126
|
|
|
124
127
|
for (let i = 0; i < node.deviceList.length; i++) {
|
|
125
128
|
const grpaddr = node.deviceList[i].monitorGA
|
|
@@ -128,7 +131,7 @@ module.exports = function (RED) {
|
|
|
128
131
|
// Check if it's a group address
|
|
129
132
|
// const ret = Address.KNXAddress.createFromString(grpaddr, Address.KNXAddress.TYPE_GROUP)
|
|
130
133
|
// node.setLocalStatus({ fill: "grey", shape: "dot", text: "Read Power from BUS" });
|
|
131
|
-
node.
|
|
134
|
+
node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr, payload: '', dpt: '', outputtype: 'read', nodecallerid: node.id })
|
|
132
135
|
} catch (error) {
|
|
133
136
|
node.setLocalStatus({ fill: 'grey', shape: 'dot', text: 'Not a KNX GA ' + error.message })
|
|
134
137
|
}
|
|
@@ -177,7 +180,7 @@ module.exports = function (RED) {
|
|
|
177
180
|
// Increase shedding timer (Switch off devices)
|
|
178
181
|
if (node.timerIncreaseShedding !== null) clearTimeout(node.timerIncreaseShedding)
|
|
179
182
|
node.timerIncreaseShedding = setTimeout(() => {
|
|
180
|
-
if (node.
|
|
183
|
+
if (node.serverKNX) {
|
|
181
184
|
// Check consumption
|
|
182
185
|
if (node.totalWatt > node.wattLimit) {
|
|
183
186
|
// Start increasing shedding!
|
|
@@ -195,7 +198,7 @@ module.exports = function (RED) {
|
|
|
195
198
|
// Decrease shedding timer (Switch devices on again)
|
|
196
199
|
if (node.timerDecreaseShedding !== null) clearTimeout(node.timerDecreaseShedding)
|
|
197
200
|
node.timerDecreaseShedding = setTimeout(() => {
|
|
198
|
-
if (node.
|
|
201
|
+
if (node.serverKNX) {
|
|
199
202
|
// Check consumption
|
|
200
203
|
if (node.totalWatt <= node.wattLimit) {
|
|
201
204
|
// Start decreasing shedding!
|
|
@@ -230,7 +233,7 @@ module.exports = function (RED) {
|
|
|
230
233
|
if (oRow.ga !== undefined && oRow.ga !== '' && oRow.ga !== null) {
|
|
231
234
|
// Check if the device is in use. If not, turn off the device and further increase the shedding stage to turn off the next one.
|
|
232
235
|
node.setLocalStatus({ fill: 'red', shape: 'dot', text: 'OFF ' + oRow.name })
|
|
233
|
-
node.
|
|
236
|
+
node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: oRow.ga, payload: false, dpt: oRow.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
234
237
|
} else {
|
|
235
238
|
node.setLocalStatus({ fill: 'grey', shape: 'dot', text: 'No GA defined' })
|
|
236
239
|
}
|
|
@@ -271,7 +274,7 @@ module.exports = function (RED) {
|
|
|
271
274
|
if (oRow.autoRestore === true) {
|
|
272
275
|
// Check if the device is in use. If not, turn off the device and further increase the shedding stage to turn off the next one.
|
|
273
276
|
node.setLocalStatus({ fill: 'green', shape: 'dot', text: 'ON ' + oRow.name })
|
|
274
|
-
node.
|
|
277
|
+
node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: oRow.ga, payload: true, dpt: oRow.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
275
278
|
} else {
|
|
276
279
|
// Cannot auto switch on the load.
|
|
277
280
|
node.setLocalStatus({ fill: 'yellow', shape: 'dot', text: 'Auto Restore disabled ' + oRow.name })
|
|
@@ -303,7 +306,7 @@ module.exports = function (RED) {
|
|
|
303
306
|
node.sheddingStage = 0
|
|
304
307
|
for (let index = 0; index < node.deviceList.length; index++) {
|
|
305
308
|
const oRow = node.deviceList[index]
|
|
306
|
-
if (oRow.autoRestore === true) node.
|
|
309
|
+
if (oRow.autoRestore === true) node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: oRow.ga, payload: true, dpt: oRow.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
307
310
|
}
|
|
308
311
|
const t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
|
|
309
312
|
node.setLocalStatus({ fill: 'green', shape: 'dot', text: 'All loads have been restored' })
|
|
@@ -363,17 +366,17 @@ module.exports = function (RED) {
|
|
|
363
366
|
if (node.mainTimer !== null) clearInterval(node.mainTimer)
|
|
364
367
|
if (node.timerDecreaseShedding !== null) clearTimeout(node.timerDecreaseShedding)
|
|
365
368
|
if (node.timerIncreaseShedding !== null) clearTimeout(node.timerIncreaseShedding)
|
|
366
|
-
if (node.
|
|
367
|
-
node.
|
|
369
|
+
if (node.serverKNX) {
|
|
370
|
+
node.serverKNX.removeClient(node)
|
|
368
371
|
}
|
|
369
372
|
done()
|
|
370
373
|
})
|
|
371
374
|
|
|
372
375
|
// On each deploy, unsubscribe+resubscribe
|
|
373
|
-
if (node.
|
|
374
|
-
node.
|
|
376
|
+
if (node.serverKNX) {
|
|
377
|
+
node.serverKNX.removeClient(node)
|
|
375
378
|
if (node.topic !== '') {
|
|
376
|
-
node.
|
|
379
|
+
node.serverKNX.addClient(node)
|
|
377
380
|
}
|
|
378
381
|
}
|
|
379
382
|
}
|
|
@@ -2,7 +2,7 @@ module.exports = function (RED) {
|
|
|
2
2
|
function knxUltimateLogger(config) {
|
|
3
3
|
RED.nodes.createNode(this, config)
|
|
4
4
|
const node = this
|
|
5
|
-
node.
|
|
5
|
+
node.serverKNX = RED.nodes.getNode(config.server)
|
|
6
6
|
node.notifyreadrequestalsorespondtobus = 'false'
|
|
7
7
|
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
|
|
8
8
|
node.notifyreadrequest = true
|
|
@@ -29,7 +29,7 @@ module.exports = function (RED) {
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
30
30
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
31
31
|
try {
|
|
32
|
-
if (node.
|
|
32
|
+
if (node.serverKNX === null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
33
33
|
const dDate = new Date()
|
|
34
34
|
// 30/08/2019 Display only the things selected in the config
|
|
35
35
|
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
@@ -41,7 +41,7 @@ module.exports = function (RED) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
if (!node.
|
|
44
|
+
if (!node.serverKNX) return
|
|
45
45
|
|
|
46
46
|
// 26/03/2020 Create and output the XML for ETS bus monitor
|
|
47
47
|
function createETSXML() {
|
|
@@ -133,19 +133,19 @@ module.exports = function (RED) {
|
|
|
133
133
|
node.on('close', function (done) {
|
|
134
134
|
if (node.timerCreateETSXML !== null) clearInterval(node.timerCreateETSXML)
|
|
135
135
|
if (node.timerTelegramCount !== null) clearInterval(node.timerTelegramCount)
|
|
136
|
-
if (node.
|
|
137
|
-
node.
|
|
136
|
+
if (node.serverKNX) {
|
|
137
|
+
node.serverKNX.removeClient(node)
|
|
138
138
|
};
|
|
139
139
|
done()
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
// On each deploy, unsubscribe+resubscribe
|
|
143
143
|
// Unsubscribe(Subscribe)
|
|
144
|
-
if (node.
|
|
144
|
+
if (node.serverKNX) {
|
|
145
145
|
if (node.timerCreateETSXML !== null) clearInterval(node.timerCreateETSXML)
|
|
146
146
|
if (node.timerTelegramCount !== null) clearInterval(node.timerTelegramCount)
|
|
147
|
-
node.
|
|
148
|
-
node.
|
|
147
|
+
node.serverKNX.removeClient(node)
|
|
148
|
+
node.serverKNX.addClient(node)
|
|
149
149
|
if (node.autoStartTimerCreateETSXML) node.StartETSXMLTimer() // autoStartTimerCreateETSXML ETS timer
|
|
150
150
|
if (node.autoStartTimerTelegramCounter) node.StartTelegramCounterTimer()
|
|
151
151
|
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
// 10/09/2024 Setup the color logger
|
|
2
|
+
loggerSetup = (options) => {
|
|
3
|
+
let clog = require("node-color-log").createNamedLogger(options.setPrefix);
|
|
4
|
+
clog.setLevel(options.loglevel);
|
|
5
|
+
clog.setDate(() => (new Date()).toLocaleString());
|
|
6
|
+
return clog;
|
|
7
|
+
}
|
|
1
8
|
module.exports = function (RED) {
|
|
2
9
|
function knxUltimateSceneController(config) {
|
|
3
10
|
const fs = require('fs')
|
|
@@ -6,7 +13,7 @@ module.exports = function (RED) {
|
|
|
6
13
|
|
|
7
14
|
RED.nodes.createNode(this, config)
|
|
8
15
|
const node = this
|
|
9
|
-
node.
|
|
16
|
+
node.serverKNX = RED.nodes.getNode(config.server)
|
|
10
17
|
node.name = config.name || 'KNX Scene Controller'
|
|
11
18
|
node.outputtopic = typeof config.outputtopic === 'undefined' ? '' : config.outputtopic
|
|
12
19
|
node.topic = config.topic || ''
|
|
@@ -26,7 +33,7 @@ module.exports = function (RED) {
|
|
|
26
33
|
node.rules = config.rules || [{}]
|
|
27
34
|
node.isSceneController = true // Signal to config node, that this is a node scene controller
|
|
28
35
|
node.userDir = path.join(RED.settings.userDir, 'knxultimatestorage') // 09/03/2020 Storage of ttsultimate (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files)
|
|
29
|
-
node.sysLogger =
|
|
36
|
+
node.sysLogger = loggerSetup({ loglevel: node.serverKNX.loglevel, setPrefix: "knxUltimateLoadControl.js" }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
|
|
30
37
|
node.timerWait = null
|
|
31
38
|
node.icountMessageInWindow = 0
|
|
32
39
|
node.disabled = false // 21/09/2020 you can now disable the scene controller
|
|
@@ -84,7 +91,7 @@ module.exports = function (RED) {
|
|
|
84
91
|
// Used to call the status update from the config node.
|
|
85
92
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
86
93
|
try {
|
|
87
|
-
if (node.
|
|
94
|
+
if (node.serverKNX === null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
88
95
|
if (node.icountMessageInWindow == -999) return // Locked out
|
|
89
96
|
if (node.disabled === true) fill = 'grey' // 21/09/2020 if disabled, color is grey
|
|
90
97
|
const dDate = new Date()
|
|
@@ -96,9 +103,9 @@ module.exports = function (RED) {
|
|
|
96
103
|
node.status({ fill, shape, text: GA + payload + (node.listenallga === true ? ' ' + devicename : '') + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ' ' + text })
|
|
97
104
|
// 16/02/2020 signal errors to the server
|
|
98
105
|
if (fill.toUpperCase() === 'RED') {
|
|
99
|
-
if (node.
|
|
106
|
+
if (node.serverKNX) {
|
|
100
107
|
const oError = { nodeid: node.id, topic: node.outputtopic, devicename, GA, text }
|
|
101
|
-
node.
|
|
108
|
+
node.serverKNX.reportToWatchdogCalledByKNXUltimateNode(oError)
|
|
102
109
|
};
|
|
103
110
|
};
|
|
104
111
|
} catch (error) {
|
|
@@ -234,7 +241,7 @@ module.exports = function (RED) {
|
|
|
234
241
|
}
|
|
235
242
|
} else {
|
|
236
243
|
// Topic is Group Address
|
|
237
|
-
node.
|
|
244
|
+
node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: rule.topic, payload: oPayload, dpt: rule.dpt, outputtype: 'write', nodecallerid: node.id })
|
|
238
245
|
}
|
|
239
246
|
}
|
|
240
247
|
const t = setTimeout(() => { // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
|
|
@@ -366,8 +373,8 @@ module.exports = function (RED) {
|
|
|
366
373
|
node.on('input', function (msg) {
|
|
367
374
|
if (typeof msg === 'undefined') return
|
|
368
375
|
|
|
369
|
-
if (!node.
|
|
370
|
-
if (node.
|
|
376
|
+
if (!node.serverKNX) return // 29/08/2019 Server not instantiate
|
|
377
|
+
if (node.serverKNX.linkStatus !== 'connected') {
|
|
371
378
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error('knxUltimateSceneController: Lost link due to a connection error')
|
|
372
379
|
return // 29/08/2019 If not connected, exit
|
|
373
380
|
}
|
|
@@ -401,16 +408,16 @@ module.exports = function (RED) {
|
|
|
401
408
|
})
|
|
402
409
|
|
|
403
410
|
node.on('close', function (done) {
|
|
404
|
-
if (node.
|
|
405
|
-
node.
|
|
411
|
+
if (node.serverKNX) {
|
|
412
|
+
node.serverKNX.removeClient(node)
|
|
406
413
|
}
|
|
407
414
|
done()
|
|
408
415
|
})
|
|
409
416
|
|
|
410
417
|
// On each deploy, unsubscribe+resubscribe
|
|
411
|
-
if (node.
|
|
412
|
-
node.
|
|
413
|
-
node.
|
|
418
|
+
if (node.serverKNX) {
|
|
419
|
+
node.serverKNX.removeClient(node)
|
|
420
|
+
node.serverKNX.addClient(node)
|
|
414
421
|
}
|
|
415
422
|
}
|
|
416
423
|
RED.nodes.registerType('knxUltimateSceneController', knxUltimateSceneController)
|
|
@@ -5,7 +5,7 @@ module.exports = function (RED) {
|
|
|
5
5
|
function knxUltimateViewer(config) {
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
const node = this;
|
|
8
|
-
node.
|
|
8
|
+
node.serverKNX = RED.nodes.getNode(config.server);
|
|
9
9
|
node.topic = node.name;
|
|
10
10
|
node.name = config.name === undefined ? 'KNXViewer' : config.name;
|
|
11
11
|
node.outputtopic = node.name;
|
|
@@ -31,7 +31,7 @@ module.exports = function (RED) {
|
|
|
31
31
|
// Used to call the status update from the config node.
|
|
32
32
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
33
33
|
try {
|
|
34
|
-
if (node.
|
|
34
|
+
if (node.serverKNX === null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return; }
|
|
35
35
|
GA = GA === undefined ? '' : GA;
|
|
36
36
|
payload = payload === undefined ? '' : payload;
|
|
37
37
|
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload;
|
|
@@ -140,7 +140,7 @@ module.exports = function (RED) {
|
|
|
140
140
|
// outputtype: "read",
|
|
141
141
|
// nodecallerid: _oClient.id,
|
|
142
142
|
// });
|
|
143
|
-
const aItems = _.clone(node.
|
|
143
|
+
const aItems = _.clone(node.serverKNX.telegramsQueue);
|
|
144
144
|
let sPayload = '';
|
|
145
145
|
|
|
146
146
|
const sHead = `<div class="main"><table><caption>Queue of outgoing telegrams to the KNX BUS. The more the count,</br>the more congested is the KNX BUS.</caption>
|
|
@@ -206,16 +206,16 @@ module.exports = function (RED) {
|
|
|
206
206
|
|
|
207
207
|
node.on('close', function (done) {
|
|
208
208
|
if (timerPIN3 !== null) clearInterval(timerPIN3);
|
|
209
|
-
if (node.
|
|
210
|
-
node.
|
|
209
|
+
if (node.serverKNX) {
|
|
210
|
+
node.serverKNX.removeClient(node);
|
|
211
211
|
}
|
|
212
212
|
done();
|
|
213
213
|
});
|
|
214
214
|
|
|
215
215
|
// On each deploy, unsubscribe+resubscribe
|
|
216
|
-
if (node.
|
|
217
|
-
node.
|
|
218
|
-
node.
|
|
216
|
+
if (node.serverKNX) {
|
|
217
|
+
node.serverKNX.removeClient(node);
|
|
218
|
+
node.serverKNX.addClient(node);
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
RED.nodes.registerType('knxUltimateViewer', knxUltimateViewer);
|
|
@@ -4,7 +4,7 @@ module.exports = function (RED) {
|
|
|
4
4
|
function knxUltimateWatchDog(config) {
|
|
5
5
|
RED.nodes.createNode(this, config)
|
|
6
6
|
const node = this
|
|
7
|
-
node.
|
|
7
|
+
node.serverKNX = RED.nodes.getNode(config.server)
|
|
8
8
|
node.dpt = '1.001'
|
|
9
9
|
node.notifyreadrequestalsorespondtobus = 'false'
|
|
10
10
|
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
|
|
@@ -31,7 +31,7 @@ module.exports = function (RED) {
|
|
|
31
31
|
// Used to call the status update from the config node.
|
|
32
32
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
33
33
|
try {
|
|
34
|
-
if (node.
|
|
34
|
+
if (node.serverKNX === null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
35
35
|
if (node.icountMessageInWindow == -999) return // Locked out, doesn't change status.
|
|
36
36
|
const dDate = new Date()
|
|
37
37
|
// 30/08/2019 Display only the things selected in the config
|
|
@@ -44,7 +44,7 @@ module.exports = function (RED) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
if (!node.
|
|
47
|
+
if (!node.serverKNX) return
|
|
48
48
|
|
|
49
49
|
function handleTheDog() {
|
|
50
50
|
node.beatNumber += 1
|
|
@@ -65,7 +65,7 @@ module.exports = function (RED) {
|
|
|
65
65
|
const cfg = {
|
|
66
66
|
timeout: 2
|
|
67
67
|
}
|
|
68
|
-
ping.sys.probe(node.
|
|
68
|
+
ping.sys.probe(node.serverKNX.host, function (isAlive) {
|
|
69
69
|
if (isAlive) {
|
|
70
70
|
node.watchDogTimerReset()
|
|
71
71
|
} else {
|
|
@@ -74,8 +74,8 @@ module.exports = function (RED) {
|
|
|
74
74
|
}, cfg)
|
|
75
75
|
} else {
|
|
76
76
|
// Issue a read request
|
|
77
|
-
if (node.
|
|
78
|
-
node.
|
|
77
|
+
if (node.serverKNX.knxConnection) {
|
|
78
|
+
node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: node.topic, payload: '', dpt: '', outputtype: 'read' })
|
|
79
79
|
node.setNodeStatus({ fill: 'grey', shape: 'dot', text: 'Checking level ' + node.checkLevel + ', with beat telegram ' + node.beatNumber + ' of ' + node.maxRetry, payload: '', GA: '', dpt: '', devicename: '' })
|
|
80
80
|
};
|
|
81
81
|
}
|
|
@@ -151,12 +151,12 @@ module.exports = function (RED) {
|
|
|
151
151
|
};
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
-
if (node.
|
|
154
|
+
if (node.serverKNX === undefined) return
|
|
155
155
|
|
|
156
156
|
// 01/02/2020 Dinamic change of the KNX Gateway IP, Port and Physical Address
|
|
157
157
|
// This new thing has been requested by proServ RealKNX staff.
|
|
158
158
|
if (msg.hasOwnProperty('setGatewayConfig')) {
|
|
159
|
-
node.
|
|
159
|
+
node.serverKNX.setGatewayConfig(msg.setGatewayConfig.IP, msg.setGatewayConfig.Port, msg.setGatewayConfig.PhysicalAddress, msg.setGatewayConfig.BindToEthernetInterface, msg.setGatewayConfig.Protocol, msg.setGatewayConfig.importCSV)
|
|
160
160
|
const ret = {
|
|
161
161
|
type: 'setGatewayConfig',
|
|
162
162
|
checkPerformed: 'The Watchdog node changed the gateway configuration.',
|
|
@@ -170,7 +170,7 @@ module.exports = function (RED) {
|
|
|
170
170
|
|
|
171
171
|
// 05/05/2021 force connection/disconnectio of the gateway
|
|
172
172
|
if (msg.hasOwnProperty('connectGateway')) {
|
|
173
|
-
node.
|
|
173
|
+
node.serverKNX.connectGateway(msg.connectGateway)
|
|
174
174
|
const ret = {
|
|
175
175
|
type: 'connectGateway',
|
|
176
176
|
checkPerformed: 'The Watchdog issued a connection/disconnection to the gateway.',
|
|
@@ -185,19 +185,19 @@ module.exports = function (RED) {
|
|
|
185
185
|
|
|
186
186
|
node.on('close', function (done) {
|
|
187
187
|
if (node.timerWatchDog !== null) clearInterval(node.timerWatchDog)
|
|
188
|
-
if (node.
|
|
189
|
-
node.
|
|
188
|
+
if (node.serverKNX) {
|
|
189
|
+
node.serverKNX.removeClient(node)
|
|
190
190
|
};
|
|
191
191
|
done()
|
|
192
192
|
})
|
|
193
193
|
|
|
194
194
|
// On each deploy, unsubscribe+resubscribe
|
|
195
195
|
// Unsubscribe(Subscribe)
|
|
196
|
-
if (node.
|
|
196
|
+
if (node.serverKNX) {
|
|
197
197
|
if (node.timerWatchDog !== null) clearInterval(node.timerWatchDog)
|
|
198
|
-
node.
|
|
198
|
+
node.serverKNX.removeClient(node)
|
|
199
199
|
if (node.topic || node.listenallga) {
|
|
200
|
-
node.
|
|
200
|
+
node.serverKNX.addClient(node)
|
|
201
201
|
if (node.autoStart) node.StartWatchDogTimer() // Autostart watchdog
|
|
202
202
|
}
|
|
203
203
|
}
|
package/nodes/utils/http.js
CHANGED
|
@@ -27,7 +27,6 @@ module.exports.use = (config) => {
|
|
|
27
27
|
simpleget.concat(opt, (err, res, data) => {
|
|
28
28
|
try {
|
|
29
29
|
if (err) {
|
|
30
|
-
RED.log.error(`utils.https: config.http.call: simpleget.concat ${err.message} : ${err.stack || ""} `);
|
|
31
30
|
reject(err);
|
|
32
31
|
} else {
|
|
33
32
|
// log.trace('http data ' + data);
|
package/nodes/utils/hueEngine.js
CHANGED
|
@@ -124,7 +124,7 @@ class classHUE extends EventEmitter {
|
|
|
124
124
|
const ok = await this.hueApiV2.put(`/resource/light/${jRet._lightID}`, jRet._state);
|
|
125
125
|
} catch (error) {
|
|
126
126
|
if (this.sysLogger !== undefined && this.sysLogger !== null) {
|
|
127
|
-
this.sysLogger.
|
|
127
|
+
this.sysLogger.error(`KNXUltimatehueEngine: classHUE: handleQueue: setLight light: ${error.message}. CHECK WETHER THE DEVICE IS POWERED ON`);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
break;
|
|
@@ -164,8 +164,9 @@ class classHUE extends EventEmitter {
|
|
|
164
164
|
} catch (error) {
|
|
165
165
|
if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error(`KNXUltimatehueEngine: classHUE: handleQueue: Ping: ${error.message}`);
|
|
166
166
|
if (this.timerCheckConnected !== null) clearInterval(this.timerCheckConnected);
|
|
167
|
-
this.commandQueue
|
|
167
|
+
this.commandQueue = [];
|
|
168
168
|
this.emit("disconnected");
|
|
169
|
+
this.close();
|
|
169
170
|
}
|
|
170
171
|
break;
|
|
171
172
|
default:
|
|
@@ -181,12 +182,18 @@ class classHUE extends EventEmitter {
|
|
|
181
182
|
handleQueue = async () => {
|
|
182
183
|
// Verifica se è possibile eseguire una nuova richiesta
|
|
183
184
|
do {
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
try {
|
|
186
|
+
const remainingRequests = await limiter.removeTokens(1);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
}
|
|
189
|
+
if (this.commandQueue !== undefined && this.commandQueue.length > 0) {
|
|
186
190
|
//if (remainingRequests >= 0) {
|
|
187
191
|
// OK, i can send
|
|
188
192
|
//console.log("\x1b[32m Messaggio. remainingRequests=" + remainingRequests + "\x1b[0m " + new Date().toTimeString(), this.commandQueue.length, "remainingRequests " + remainingRequests);
|
|
189
|
-
|
|
193
|
+
try {
|
|
194
|
+
await this.processQueueItem();
|
|
195
|
+
} catch (error) {
|
|
196
|
+
}
|
|
190
197
|
//} else {
|
|
191
198
|
// Limit reached, skip this round.
|
|
192
199
|
//console.log("\x1b[41m HO DETTO SPETA. remainingRequests=" + remainingRequests + "\x1b[0m " + new Date().toTimeString(), this.commandQueue.length, "remainingRequests " + remainingRequests);
|
|
@@ -198,7 +205,7 @@ class classHUE extends EventEmitter {
|
|
|
198
205
|
|
|
199
206
|
writeHueQueueAdd = async (_lightID, _state, _operation) => {
|
|
200
207
|
// Add the new item
|
|
201
|
-
this.commandQueue.
|
|
208
|
+
this.commandQueue.unshift({ _lightID, _state, _operation });
|
|
202
209
|
};
|
|
203
210
|
|
|
204
211
|
/**
|
|
@@ -60,9 +60,9 @@ module.exports.KNXULtimateChangeConfigByInputMSG = function KNXULtimateChangeCon
|
|
|
60
60
|
config.outputtopic = node.outputtopic;
|
|
61
61
|
|
|
62
62
|
// Read from the ETS file, the missing props
|
|
63
|
-
if (node.
|
|
63
|
+
if (node.serverKNX.csv !== undefined && node.serverKNX.csv !== null) {
|
|
64
64
|
// Read it from ETS File
|
|
65
|
-
const found = node.
|
|
65
|
+
const found = node.serverKNX.csv.find(item => item.ga === msg.setConfig.setGroupAddress);
|
|
66
66
|
if (found !== undefined) {
|
|
67
67
|
if (msg.setConfig.setDPT === 'auto') {
|
|
68
68
|
node.dpt = found.dpt; // SET THE DPT
|
package/nodes/utils/sysLogger.js
CHANGED
|
@@ -1,70 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* (C)
|
|
2
|
+
* (C) 2024 Supergiovane
|
|
3
3
|
*/
|
|
4
|
-
const util = require('util')
|
|
5
|
-
const possibleLEvels = ['silent', 'error', 'warn', 'info', 'debug', 'trace']
|
|
6
|
-
let logger = undefined;
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
5
|
+
class loggerEngine {
|
|
6
|
+
constructor() {
|
|
7
|
+
const possibleLEvels = ['success', 'error', 'warn', 'info', 'debug']
|
|
12
8
|
|
|
13
|
-
const determineLogLevel = options => {
|
|
14
|
-
let level
|
|
15
|
-
|
|
16
|
-
// 24/03/2021 Supergiovane fixed logLevel capitalization to lowercase
|
|
17
|
-
if (options) {
|
|
18
|
-
if (options.loglevel) {
|
|
19
|
-
level = options.loglevel
|
|
20
|
-
} else {
|
|
21
|
-
options.debug ? level = 'debug' : level = 'info'
|
|
22
|
-
}
|
|
23
|
-
} else {
|
|
24
|
-
level = 'info'
|
|
25
9
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (logger === undefined) {
|
|
33
|
-
// console.log('BANANA new logger, level',determineLogLevel(options),(options && options.debug && 'debug') ||
|
|
34
|
-
// (options && options.loglevel) ||
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
return (logger)
|
|
38
|
-
},
|
|
39
|
-
set: function (options) {
|
|
40
|
-
logger = require('log-driver')({
|
|
41
|
-
levels: ['silent', 'error', 'warn', 'info', 'debug', 'trace'],
|
|
42
|
-
level: determineLogLevel(options),
|
|
43
|
-
format: function () {
|
|
44
|
-
// arguments[0] is the log level ie 'debug'
|
|
45
|
-
const a = Array.from(arguments)
|
|
46
|
-
let ts
|
|
47
|
-
const dt = new Date()
|
|
48
|
-
try {
|
|
49
|
-
ts = dt.toLocaleString().replace(/T/, ' ').replace(/Z$/, '') + '.' + dt.getMilliseconds()
|
|
50
|
-
} catch (error) {
|
|
51
|
-
ts = dt.toISOString().replace(/T/, ' ').replace(/Z$/, '') + '.' + dt.getMilliseconds()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (a.length > 2) {
|
|
55
|
-
// if more than one item to log, assume a fmt string is given
|
|
56
|
-
const fmtargs = ['[%s] %s ' + a[1], a[0], ts].concat(a.slice(2))
|
|
57
|
-
return util.format.apply(util, fmtargs)
|
|
58
|
-
} else {
|
|
59
|
-
// arguments[1] is a plain string
|
|
60
|
-
return util.format('[%s] %s %s', a[0], ts, a[1])
|
|
61
|
-
}
|
|
10
|
+
get = (options) => {
|
|
11
|
+
let logger = require('node-color-log');
|
|
12
|
+
try {
|
|
13
|
+
//levels: ['silent', 'error', 'warn', 'info', 'debug', 'trace'],
|
|
14
|
+
if (options.setPrefix !== undefined) {
|
|
15
|
+
logger = logger.createNamedLogger(options.setPrefix);
|
|
62
16
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
17
|
+
if (options.loglevel === 'trace') options.loglevel = 'debug' // Backwart compatibility
|
|
18
|
+
if (options.loglevel === 'silent') options.loglevel = 'disable' // Backwart compatibility
|
|
19
|
+
logger.setLevel(options.loglevel);
|
|
20
|
+
logger.setDate(() => (new Date()).toLocaleString())
|
|
21
|
+
return logger
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return logger
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
destroy = () => {
|
|
67
27
|
// 16/08/2020 Supergiovane Destruction of the logger
|
|
68
28
|
logger = null
|
|
69
29
|
}
|
|
30
|
+
|
|
70
31
|
}
|
|
32
|
+
const colorlog = new loggerEngine();
|
|
33
|
+
module.exports = colorlog;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.2.
|
|
6
|
+
"version": "3.2.1",
|
|
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,10 +11,10 @@
|
|
|
11
11
|
"dns-sync": "0.2.1",
|
|
12
12
|
"eventsource": "2.0.2",
|
|
13
13
|
"js-yaml": "4.1.0",
|
|
14
|
-
"knxultimate": ">=
|
|
14
|
+
"knxultimate": ">=3.0.0",
|
|
15
15
|
"limiter": "^2.1.0",
|
|
16
16
|
"lodash": "4.17.21",
|
|
17
|
-
"log
|
|
17
|
+
"node-color-log": "12.0.1",
|
|
18
18
|
"mkdirp": "3.0.1",
|
|
19
19
|
"node-hue-api": "5.0.0-beta.16",
|
|
20
20
|
"path": "0.12.7",
|