node-red-contrib-knx-ultimate 2.1.6 → 2.1.7
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 +4 -0
- package/nodes/knxUltimate-config.js +17 -31
- package/nodes/knxUltimate.js +20 -15
- package/nodes/knxUltimateAlerter.js +16 -11
- package/nodes/knxUltimateGlobalContext.js +10 -5
- package/nodes/knxUltimateLoadControl.js +1 -0
- package/nodes/knxUltimateLogger.js +11 -7
- package/nodes/knxUltimateSceneController.js +20 -16
- package/nodes/knxUltimateViewer.js +5 -1
- package/nodes/knxUltimateWatchDog.js +14 -10
- package/nodes/utils/hueUtils.js +8 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
<p>
|
|
10
|
+
<b>Version 2.1.7</b> - June 2023<br/>
|
|
11
|
+
- KNX nodes not correctly show status of JSON objects (like dimming, color, etc.).<br/>
|
|
12
|
+
</p>
|
|
9
13
|
<p>
|
|
10
14
|
<b>Version 2.1.6</b> - June 2023<br/>
|
|
11
15
|
- Several fixes for reading the correct GAMUT color.<br/>
|
|
@@ -101,7 +101,7 @@ return msg;`,
|
|
|
101
101
|
res.json(jRet)
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
function knxUltimateConfigNode
|
|
104
|
+
function knxUltimateConfigNode(config) {
|
|
105
105
|
RED.nodes.createNode(this, config)
|
|
106
106
|
const node = this
|
|
107
107
|
node.host = config.host
|
|
@@ -172,7 +172,7 @@ return msg;`,
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
node.setAllClientsStatus = (_status, _color, _text) => {
|
|
175
|
-
function nextStatus
|
|
175
|
+
function nextStatus(_oClient) {
|
|
176
176
|
let oClient = RED.nodes.getNode(_oClient.id)
|
|
177
177
|
oClient.setNodeStatus({ fill: _color, shape: 'dot', text: _status + ' ' + _text, payload: '', GA: oClient.topic, dpt: '', devicename: '' })
|
|
178
178
|
oClient = null
|
|
@@ -218,7 +218,7 @@ return msg;`,
|
|
|
218
218
|
// 04/04/2021 Supergiovane, creates the service paths where the persistent files are created.
|
|
219
219
|
// The values file is stored only upon disconnection/close
|
|
220
220
|
// ************************
|
|
221
|
-
function setupDirectory
|
|
221
|
+
function setupDirectory(_aPath) {
|
|
222
222
|
if (!fs.existsSync(_aPath)) {
|
|
223
223
|
// Create the path
|
|
224
224
|
try {
|
|
@@ -238,7 +238,7 @@ return msg;`,
|
|
|
238
238
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info('KNXUltimate-config: payload cache set to ' + path.join(node.userDir, 'knxpersistvalues'))
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
function saveExposedGAs
|
|
241
|
+
function saveExposedGAs() {
|
|
242
242
|
const sFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
|
|
243
243
|
try {
|
|
244
244
|
if (node.exposedGAs.length > 0) {
|
|
@@ -249,7 +249,7 @@ return msg;`,
|
|
|
249
249
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error('KNXUltimate-config: unable to write peristent values to the file ' + sFile + ' ' + err.message)
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
|
-
function loadExposedGAs
|
|
252
|
+
function loadExposedGAs() {
|
|
253
253
|
const sFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
|
|
254
254
|
try {
|
|
255
255
|
node.exposedGAs = JSON.parse(fs.readFileSync(sFile, 'utf8'))
|
|
@@ -274,7 +274,7 @@ return msg;`,
|
|
|
274
274
|
const appName = 'KNXUltimate'
|
|
275
275
|
const deviceName = 'Node-Red'
|
|
276
276
|
|
|
277
|
-
async function discoverBridge
|
|
277
|
+
async function discoverBridge() {
|
|
278
278
|
const discoveryResults = await discovery.nupnpSearch()
|
|
279
279
|
|
|
280
280
|
if (discoveryResults.length === 0) {
|
|
@@ -286,7 +286,7 @@ return msg;`,
|
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
async function discoverAndCreateUser
|
|
289
|
+
async function discoverAndCreateUser() {
|
|
290
290
|
const ipAddress = await discoverBridge()
|
|
291
291
|
|
|
292
292
|
// Create an unauthenticated instance of the Hue API so that we can create a new user
|
|
@@ -496,20 +496,6 @@ return msg;`,
|
|
|
496
496
|
})
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
-
// node.addClient = (_Node) => {
|
|
500
|
-
// // Check if node already exists
|
|
501
|
-
// if (node.nodeClients.filter(x => x.id === _Node.id).length === 0) {
|
|
502
|
-
// // Add _Node to the clients array
|
|
503
|
-
// if (node.autoReconnect) {
|
|
504
|
-
// _Node.setNodeStatus({ fill: "grey", shape: "ring", text: "Node initialized.", payload: "", GA: "", dpt: "", devicename: "" });
|
|
505
|
-
// } else {
|
|
506
|
-
// _Node.setNodeStatus({ fill: "red", shape: "ring", text: "Autoconnect disabled. Please manually connect.", payload: "", GA: "", dpt: "", devicename: "" });
|
|
507
|
-
// }
|
|
508
|
-
// node.nodeClients.push(_Node);
|
|
509
|
-
// }
|
|
510
|
-
|
|
511
|
-
// }
|
|
512
|
-
|
|
513
499
|
node.addClient = (_Node) => {
|
|
514
500
|
// Check if node already exists
|
|
515
501
|
if (node.nodeClients.filter(x => x.id === _Node.id).length === 0) {
|
|
@@ -549,7 +535,7 @@ return msg;`,
|
|
|
549
535
|
}
|
|
550
536
|
|
|
551
537
|
// 17/02/2020 Do initial read (called by node.timerDoInitialRead timer)
|
|
552
|
-
function DoInitialReadFromKNXBusOrFile
|
|
538
|
+
function DoInitialReadFromKNXBusOrFile() {
|
|
553
539
|
if (node.linkStatus !== 'connected') return // 29/08/2019 If not connected, exit
|
|
554
540
|
loadExposedGAs() // 04/04/2021 load the current values of GA payload
|
|
555
541
|
try {
|
|
@@ -909,7 +895,7 @@ return msg;`,
|
|
|
909
895
|
|
|
910
896
|
// Handle BUS events
|
|
911
897
|
// ---------------------------------------------------------------------------------------
|
|
912
|
-
function handleBusEvents
|
|
898
|
+
function handleBusEvents(_datagram, _echoed) {
|
|
913
899
|
// console.time('handleBusEvents');
|
|
914
900
|
|
|
915
901
|
let _rawValue = null
|
|
@@ -1177,7 +1163,7 @@ return msg;`,
|
|
|
1177
1163
|
node.telegramsQueue.unshift(_clonedMessage) // Add _clonedMessage as first in the queue pile
|
|
1178
1164
|
}
|
|
1179
1165
|
|
|
1180
|
-
function handleTelegramQueue
|
|
1166
|
+
function handleTelegramQueue() {
|
|
1181
1167
|
if (node.knxConnection !== null || node.host.toUpperCase() === 'EMULATE') {
|
|
1182
1168
|
if (node.lockHandleTelegramQueue === true) return // Exits if the funtion is busy
|
|
1183
1169
|
node.lockHandleTelegramQueue = true // Lock the function. It cannot be called again until finished.
|
|
@@ -1326,14 +1312,14 @@ return msg;`,
|
|
|
1326
1312
|
}
|
|
1327
1313
|
|
|
1328
1314
|
// 14/08/2019 If the node has payload same as the received telegram, return false
|
|
1329
|
-
function checkRBEInputFromKNXBusAllowSend
|
|
1315
|
+
function checkRBEInputFromKNXBusAllowSend(_node, _KNXTelegramPayload) {
|
|
1330
1316
|
if (_node.inputRBE !== true) return true
|
|
1331
1317
|
|
|
1332
1318
|
return !_.isEqual(_node.currentPayload, _KNXTelegramPayload)
|
|
1333
1319
|
}
|
|
1334
1320
|
|
|
1335
1321
|
// 26/10/2019 Try to figure out the datapoint type from raw value
|
|
1336
|
-
function tryToFigureOutDataPointFromRawValue
|
|
1322
|
+
function tryToFigureOutDataPointFromRawValue(_rawValue) {
|
|
1337
1323
|
// 25/10/2019 Try some Datapoints
|
|
1338
1324
|
if (_rawValue === null) return '1.001'
|
|
1339
1325
|
if (_rawValue.length === 1) {
|
|
@@ -1379,7 +1365,7 @@ return msg;`,
|
|
|
1379
1365
|
}
|
|
1380
1366
|
}
|
|
1381
1367
|
|
|
1382
|
-
function buildInputMessage
|
|
1368
|
+
function buildInputMessage({ _srcGA, _destGA, _event, _Rawvalue, _inputDpt, _devicename, _outputtopic, _oNode }) {
|
|
1383
1369
|
let sPayloadmeasureunit = 'unknown'
|
|
1384
1370
|
let sDptdesc = 'unknown'
|
|
1385
1371
|
let sPayloadsubtypevalue = 'unknown'
|
|
@@ -1486,7 +1472,7 @@ return msg;`,
|
|
|
1486
1472
|
}
|
|
1487
1473
|
};
|
|
1488
1474
|
|
|
1489
|
-
function readCSV
|
|
1475
|
+
function readCSV(_csvText) {
|
|
1490
1476
|
// 26/05/2023 check if the text is a file path
|
|
1491
1477
|
if (_csvText.toUpperCase().includes('.CSV') || _csvText.toUpperCase().includes('.ESF')) {
|
|
1492
1478
|
// I'ts a file. Read it now and pass to the _csvText
|
|
@@ -1580,7 +1566,7 @@ return msg;`,
|
|
|
1580
1566
|
}
|
|
1581
1567
|
}
|
|
1582
1568
|
|
|
1583
|
-
function readESF
|
|
1569
|
+
function readESF(_esfText) {
|
|
1584
1570
|
// 24/02/2020 must do an EIS to DPT conversion.
|
|
1585
1571
|
// https://www.loxone.com/dede/kb/eibknx-datentypen/
|
|
1586
1572
|
// Format: Attuatori luci.Luci primo piano.0/0/1 Luce camera da letto EIS 1 'Switching' (1 Bit) Low
|
|
@@ -1664,7 +1650,7 @@ return msg;`,
|
|
|
1664
1650
|
}
|
|
1665
1651
|
|
|
1666
1652
|
// 23/08/2019 Delete unwanted CRLF in the GA description
|
|
1667
|
-
function correctCRLFInCSV
|
|
1653
|
+
function correctCRLFInCSV(_csv) {
|
|
1668
1654
|
let sOut = '' // fixed output text to return
|
|
1669
1655
|
let sChar = ''
|
|
1670
1656
|
let bStart = false
|
|
@@ -1697,7 +1683,7 @@ return msg;`,
|
|
|
1697
1683
|
}
|
|
1698
1684
|
|
|
1699
1685
|
// 26/02/2021 Used to send the messages if the node gateway is in EMULATION mode
|
|
1700
|
-
function sendEmulatedTelegram
|
|
1686
|
+
function sendEmulatedTelegram(_msg) {
|
|
1701
1687
|
// INPUT IS
|
|
1702
1688
|
// _msg = {
|
|
1703
1689
|
// grpaddr: '5/0/1',
|
package/nodes/knxUltimate.js
CHANGED
|
@@ -40,21 +40,26 @@ module.exports = function (RED) {
|
|
|
40
40
|
|
|
41
41
|
// Used to call the status update from the config node.
|
|
42
42
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
node.server
|
|
56
|
-
|
|
57
|
-
|
|
43
|
+
try {
|
|
44
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
45
|
+
if (node.icountMessageInWindow == -999) return // Locked out, doesn't change status.
|
|
46
|
+
const dDate = new Date()
|
|
47
|
+
// 30/08/2019 Display only the things selected in the config
|
|
48
|
+
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
49
|
+
devicename = devicename || ''
|
|
50
|
+
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ' DPT' + dpt
|
|
51
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
52
|
+
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
53
|
+
// 16/02/2020 signal errors to the server
|
|
54
|
+
if (fill.toUpperCase() === 'RED') {
|
|
55
|
+
if (node.server) {
|
|
56
|
+
const oError = { nodeid: node.id, topic: node.outputtopic, devicename, GA, text }
|
|
57
|
+
node.server.reportToWatchdogCalledByKNXUltimateNode(oError)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
// Check if the node has a valid topic and dpt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
module.exports = function (RED) {
|
|
3
|
-
function knxUltimateAlerter
|
|
3
|
+
function knxUltimateAlerter(config) {
|
|
4
4
|
const fs = require('fs')
|
|
5
5
|
const path = require('path')
|
|
6
6
|
const mkdirp = require('mkdirp')
|
|
@@ -41,17 +41,22 @@ module.exports = function (RED) {
|
|
|
41
41
|
|
|
42
42
|
// Used to call the status update from the config node.
|
|
43
43
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
try {
|
|
45
|
+
if (node.server === null) return
|
|
46
|
+
// Log only service statuses, not the GA values
|
|
47
|
+
if (dpt !== undefined) return
|
|
48
|
+
if (dpt !== '') return
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
const dDate = new Date()
|
|
51
|
+
// 30/08/2019 Display only the things selected in the config
|
|
52
|
+
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
53
|
+
devicename = devicename || ''
|
|
54
|
+
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ' DPT' + dpt
|
|
55
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
56
|
+
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
57
|
+
} catch (error) {
|
|
58
|
+
|
|
59
|
+
}
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
// Used to call the status update from the config node.
|
|
@@ -57,11 +57,16 @@ module.exports = function (RED) {
|
|
|
57
57
|
|
|
58
58
|
// Used to call the status update from the config node.
|
|
59
59
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
try {
|
|
61
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
62
|
+
GA = GA === undefined ? '' : GA
|
|
63
|
+
payload = payload === undefined ? '' : payload
|
|
64
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
65
|
+
const dDate = new Date()
|
|
66
|
+
node.status({ fill, shape, text: GA + ' ' + payload + ' ' + text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
67
|
+
} catch (error) {
|
|
68
|
+
}
|
|
69
|
+
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
// 02/12/2022 Expose the complete ETS CSV as well
|
|
@@ -63,6 +63,7 @@ module.exports = function (RED) {
|
|
|
63
63
|
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
64
64
|
devicename = devicename || ''
|
|
65
65
|
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ' DPT' + dpt
|
|
66
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
66
67
|
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
67
68
|
} catch (error) {
|
|
68
69
|
|
|
@@ -28,13 +28,17 @@ module.exports = function (RED) {
|
|
|
28
28
|
|
|
29
29
|
// Used to call the status update from the config node.
|
|
30
30
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
try {
|
|
32
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
33
|
+
const dDate = new Date()
|
|
34
|
+
// 30/08/2019 Display only the things selected in the config
|
|
35
|
+
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
36
|
+
devicename = devicename || ''
|
|
37
|
+
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ' DPT' + dpt
|
|
38
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
39
|
+
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
40
|
+
} catch (error) {
|
|
41
|
+
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
if (!node.server) return
|
|
@@ -92,22 +92,26 @@ module.exports = function (RED) {
|
|
|
92
92
|
|
|
93
93
|
// Used to call the status update from the config node.
|
|
94
94
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
node.server
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
try {
|
|
96
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
97
|
+
if (node.icountMessageInWindow == -999) return // Locked out
|
|
98
|
+
if (node.disabled === true) fill = 'grey' // 21/09/2020 if disabled, color is grey
|
|
99
|
+
const dDate = new Date()
|
|
100
|
+
// 30/08/2019 Display only the things selected in the config
|
|
101
|
+
GA = (typeof GA === 'undefined' || GA === '') ? '' : '(' + GA + ') '
|
|
102
|
+
devicename = devicename || ''
|
|
103
|
+
dpt = (typeof dpt === 'undefined' || dpt === '') ? '' : ' DPT' + dpt
|
|
104
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
105
|
+
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
106
|
+
// 16/02/2020 signal errors to the server
|
|
107
|
+
if (fill.toUpperCase() === 'RED') {
|
|
108
|
+
if (node.server) {
|
|
109
|
+
const oError = { nodeid: node.id, topic: node.outputtopic, devicename, GA, text }
|
|
110
|
+
node.server.reportToWatchdogCalledByKNXUltimateNode(oError)
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
} catch (error) {
|
|
114
|
+
}
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
// 03/09/2021 Async function to allow await delay(x)
|
|
@@ -29,11 +29,15 @@ module.exports = function (RED) {
|
|
|
29
29
|
|
|
30
30
|
// Used to call the status update from the config node.
|
|
31
31
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
32
|
+
try {
|
|
32
33
|
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
33
34
|
GA = GA === undefined ? '' : GA
|
|
34
35
|
payload = payload === undefined ? '' : payload
|
|
36
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
35
37
|
const dDate = new Date()
|
|
36
|
-
|
|
38
|
+
node.status({ fill, shape, text: GA + ' ' + payload + ' ' + text + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
39
|
+
} catch (error) {
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const ping = require('ping')
|
|
2
2
|
|
|
3
3
|
module.exports = function (RED) {
|
|
4
|
-
function knxUltimateWatchDog
|
|
4
|
+
function knxUltimateWatchDog(config) {
|
|
5
5
|
RED.nodes.createNode(this, config)
|
|
6
6
|
const node = this
|
|
7
7
|
node.server = RED.nodes.getNode(config.server)
|
|
@@ -30,19 +30,23 @@ module.exports = function (RED) {
|
|
|
30
30
|
|
|
31
31
|
// Used to call the status update from the config node.
|
|
32
32
|
node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return }
|
|
35
|
+
if (node.icountMessageInWindow == -999) return // Locked out, doesn't change status.
|
|
36
|
+
const dDate = new Date()
|
|
37
|
+
// 30/08/2019 Display only the things selected in the config
|
|
38
|
+
GA = (typeof GA === 'undefined' || GA == '') ? '' : '(' + GA + ') '
|
|
39
|
+
devicename = devicename || ''
|
|
40
|
+
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ' DPT' + dpt
|
|
41
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload
|
|
42
|
+
node.status({ fill, shape, text: GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) === true ? ' ' + devicename : '') + (node.server.statusDisplayDataPoint === true ? dpt : '') + (node.server.statusDisplayLastUpdate === true ? ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' : '') + ' ' + text })
|
|
43
|
+
} catch (error) {
|
|
44
|
+
}
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
if (!node.server) return
|
|
44
48
|
|
|
45
|
-
function handleTheDog
|
|
49
|
+
function handleTheDog() {
|
|
46
50
|
node.beatNumber += 1
|
|
47
51
|
if (node.beatNumber > node.maxRetry) {
|
|
48
52
|
// Confirmed connection error
|
package/nodes/utils/hueUtils.js
CHANGED
|
@@ -27,6 +27,7 @@ class classHUE extends EventEmitter {
|
|
|
27
27
|
this.timerwriteQueueAdd = setTimeout(this.handleQueue, 3000) // First start
|
|
28
28
|
|
|
29
29
|
// start the SSE Stream Receiver
|
|
30
|
+
// #############################################
|
|
30
31
|
const options = {
|
|
31
32
|
host: _hueBridgeIP, // Indirizzo IP del tuo bridge Philips Hue
|
|
32
33
|
path: '/eventstream/clip/v2', // Il percorso dell'API per gli eventi
|
|
@@ -85,8 +86,11 @@ class classHUE extends EventEmitter {
|
|
|
85
86
|
// Starts the connection for the first time
|
|
86
87
|
req();
|
|
87
88
|
}
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
// #############################################
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
// Handle the send queue
|
|
93
|
+
// ######################################
|
|
90
94
|
handleQueue = async () => {
|
|
91
95
|
if (this.commandQueue.length > 0) {
|
|
92
96
|
const jRet = this.commandQueue.shift()
|
|
@@ -115,10 +119,10 @@ class classHUE extends EventEmitter {
|
|
|
115
119
|
// The Hue bridge allows about 10 telegram per second, so i need to make a queue manager
|
|
116
120
|
setTimeout(this.handleQueue, 100)
|
|
117
121
|
}
|
|
118
|
-
writeHueQueueAdd = async (_lightID, _state, _operation
|
|
122
|
+
writeHueQueueAdd = async (_lightID, _state, _operation, _callback) => {
|
|
119
123
|
this.commandQueue.push({ _lightID, _state, _operation, _callback })
|
|
120
124
|
}
|
|
121
|
-
|
|
125
|
+
// ######################################
|
|
122
126
|
|
|
123
127
|
// Get all devices and join it with relative rooms, by adding the room name to the device name
|
|
124
128
|
getResources = async (_rtype, _host, _username) => {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=14.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.1.
|
|
6
|
+
"version": "2.1.7",
|
|
7
7
|
"description": "Control your KNX intallation via Node-Red! Single Node KNX IN/OUT with optional ETS group address importer. Easy to use and highly configurable. With integrated Philips HUE devices handling.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"mkdirp": "1.0.4",
|