node-red-contrib-knx-ultimate 6.1.0 → 6.2.0
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 +16 -0
- package/examples/KNX AI - Conversational Control with Confirmation.json +374 -0
- package/examples/KNX AI - Telegrambot Direct Chat.json +221 -0
- package/examples/Matter Controller - Semantic Flow Input.json +248 -0
- package/nodes/commonFunctions.js +0 -174
- package/nodes/knxUltimateAI.html +254 -90
- package/nodes/knxUltimateAI.js +1286 -61
- package/nodes/knxUltimateMatterBridge.html +144 -11
- package/nodes/knxUltimateMatterControllerDevice.html +80 -55
- package/nodes/locales/de/knxUltimateAI.html +38 -2
- package/nodes/locales/de/knxUltimateAI.json +16 -3
- package/nodes/locales/de/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/de/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/de/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/de/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/en/knxUltimateAI.html +38 -2
- package/nodes/locales/en/knxUltimateAI.json +16 -3
- package/nodes/locales/en/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/en/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/en/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/en/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/es/knxUltimateAI.html +38 -2
- package/nodes/locales/es/knxUltimateAI.json +16 -3
- package/nodes/locales/es/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/es/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/es/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/es/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/fr/knxUltimateAI.html +38 -2
- package/nodes/locales/fr/knxUltimateAI.json +16 -3
- package/nodes/locales/fr/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/fr/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/it/knxUltimateAI.html +38 -2
- package/nodes/locales/it/knxUltimateAI.json +16 -3
- package/nodes/locales/it/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/it/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/it/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/it/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/zh-CN/knxUltimateAI.html +38 -2
- package/nodes/locales/zh-CN/knxUltimateAI.json +16 -3
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/utils/sysLogger.js +0 -109
- package/package.json +1 -2
- package/resources/KNXAIChatAdapterMappings.js +87 -0
- package/nodes/plugins/knxUltimateMonitor-sidebar-plugin.html +0 -922
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "matter_semantic_tab",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Matter Controller - Flow input",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "Example of the semantic msg.payload = { function, value } contract for Control Matter from KNX (BETA).\n\nAfter importing:\n1. Open the example Matter Controller node.\n2. Select your existing Matter Controller configuration and a commissioned non-light endpoint.\n3. Enable Node Input/Output PINs.\n4. In the Flow input section shown below the PIN selector, use only the Inject nodes matching functions advertised by the device.\n\nThis example creates no matter-config and sends no command automatically."
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "matter_semantic_instructions",
|
|
11
|
+
"type": "comment",
|
|
12
|
+
"z": "matter_semantic_tab",
|
|
13
|
+
"name": "1. Open the Controller, select matter-config + endpoint, then enable the flow PINs",
|
|
14
|
+
"info": "The Inject nodes are alternative examples: one endpoint normally does not support every function shown. Use only functions listed in the Controller node's Flow input section.",
|
|
15
|
+
"x": 520,
|
|
16
|
+
"y": 60,
|
|
17
|
+
"wires": []
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "matter_semantic_supported",
|
|
21
|
+
"type": "comment",
|
|
22
|
+
"z": "matter_semantic_tab",
|
|
23
|
+
"name": "2. Trigger only Inject nodes supported by the selected endpoint",
|
|
24
|
+
"info": "No Inject is configured to run automatically. Reads omit value; writes include value.",
|
|
25
|
+
"x": 340,
|
|
26
|
+
"y": 110,
|
|
27
|
+
"wires": []
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "matter_semantic_on",
|
|
31
|
+
"type": "inject",
|
|
32
|
+
"z": "matter_semantic_tab",
|
|
33
|
+
"name": "On: {onoff, true}",
|
|
34
|
+
"props": [
|
|
35
|
+
{
|
|
36
|
+
"p": "payload",
|
|
37
|
+
"v": "{\"function\":\"onoff\",\"value\":true}",
|
|
38
|
+
"vt": "json"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"repeat": "",
|
|
42
|
+
"crontab": "",
|
|
43
|
+
"once": false,
|
|
44
|
+
"onceDelay": 0.1,
|
|
45
|
+
"topic": "",
|
|
46
|
+
"x": 190,
|
|
47
|
+
"y": 180,
|
|
48
|
+
"wires": [
|
|
49
|
+
[
|
|
50
|
+
"matter_semantic_controller"
|
|
51
|
+
]
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "matter_semantic_off",
|
|
56
|
+
"type": "inject",
|
|
57
|
+
"z": "matter_semantic_tab",
|
|
58
|
+
"name": "Off: {onoff, false}",
|
|
59
|
+
"props": [
|
|
60
|
+
{
|
|
61
|
+
"p": "payload",
|
|
62
|
+
"v": "{\"function\":\"onoff\",\"value\":false}",
|
|
63
|
+
"vt": "json"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"repeat": "",
|
|
67
|
+
"crontab": "",
|
|
68
|
+
"once": false,
|
|
69
|
+
"onceDelay": 0.1,
|
|
70
|
+
"topic": "",
|
|
71
|
+
"x": 190,
|
|
72
|
+
"y": 230,
|
|
73
|
+
"wires": [
|
|
74
|
+
[
|
|
75
|
+
"matter_semantic_controller"
|
|
76
|
+
]
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "matter_semantic_level",
|
|
81
|
+
"type": "inject",
|
|
82
|
+
"z": "matter_semantic_tab",
|
|
83
|
+
"name": "Level 50%",
|
|
84
|
+
"props": [
|
|
85
|
+
{
|
|
86
|
+
"p": "payload",
|
|
87
|
+
"v": "{\"function\":\"level\",\"value\":50}",
|
|
88
|
+
"vt": "json"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"repeat": "",
|
|
92
|
+
"crontab": "",
|
|
93
|
+
"once": false,
|
|
94
|
+
"onceDelay": 0.1,
|
|
95
|
+
"topic": "",
|
|
96
|
+
"x": 180,
|
|
97
|
+
"y": 280,
|
|
98
|
+
"wires": [
|
|
99
|
+
[
|
|
100
|
+
"matter_semantic_controller"
|
|
101
|
+
]
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "matter_semantic_position",
|
|
106
|
+
"type": "inject",
|
|
107
|
+
"z": "matter_semantic_tab",
|
|
108
|
+
"name": "Cover position 35%",
|
|
109
|
+
"props": [
|
|
110
|
+
{
|
|
111
|
+
"p": "payload",
|
|
112
|
+
"v": "{\"function\":\"position\",\"value\":35}",
|
|
113
|
+
"vt": "json"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"repeat": "",
|
|
117
|
+
"crontab": "",
|
|
118
|
+
"once": false,
|
|
119
|
+
"onceDelay": 0.1,
|
|
120
|
+
"topic": "",
|
|
121
|
+
"x": 190,
|
|
122
|
+
"y": 330,
|
|
123
|
+
"wires": [
|
|
124
|
+
[
|
|
125
|
+
"matter_semantic_controller"
|
|
126
|
+
]
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"id": "matter_semantic_setpoint",
|
|
131
|
+
"type": "inject",
|
|
132
|
+
"z": "matter_semantic_tab",
|
|
133
|
+
"name": "Setpoint 21,5 °C",
|
|
134
|
+
"props": [
|
|
135
|
+
{
|
|
136
|
+
"p": "payload",
|
|
137
|
+
"v": "{\"function\":\"setpoint\",\"value\":21.5}",
|
|
138
|
+
"vt": "json"
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"repeat": "",
|
|
142
|
+
"crontab": "",
|
|
143
|
+
"once": false,
|
|
144
|
+
"onceDelay": 0.1,
|
|
145
|
+
"topic": "",
|
|
146
|
+
"x": 190,
|
|
147
|
+
"y": 380,
|
|
148
|
+
"wires": [
|
|
149
|
+
[
|
|
150
|
+
"matter_semantic_controller"
|
|
151
|
+
]
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "matter_semantic_temperature",
|
|
156
|
+
"type": "inject",
|
|
157
|
+
"z": "matter_semantic_tab",
|
|
158
|
+
"name": "Read temperature",
|
|
159
|
+
"props": [
|
|
160
|
+
{
|
|
161
|
+
"p": "payload",
|
|
162
|
+
"v": "{\"function\":\"temperature\"}",
|
|
163
|
+
"vt": "json"
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
"repeat": "",
|
|
167
|
+
"crontab": "",
|
|
168
|
+
"once": false,
|
|
169
|
+
"onceDelay": 0.1,
|
|
170
|
+
"topic": "",
|
|
171
|
+
"x": 190,
|
|
172
|
+
"y": 430,
|
|
173
|
+
"wires": [
|
|
174
|
+
[
|
|
175
|
+
"matter_semantic_controller"
|
|
176
|
+
]
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "matter_semantic_identify",
|
|
181
|
+
"type": "inject",
|
|
182
|
+
"z": "matter_semantic_tab",
|
|
183
|
+
"name": "Identify",
|
|
184
|
+
"props": [
|
|
185
|
+
{
|
|
186
|
+
"p": "payload",
|
|
187
|
+
"v": "{\"function\":\"identify\"}",
|
|
188
|
+
"vt": "json"
|
|
189
|
+
}
|
|
190
|
+
],
|
|
191
|
+
"repeat": "",
|
|
192
|
+
"crontab": "",
|
|
193
|
+
"once": false,
|
|
194
|
+
"onceDelay": 0.1,
|
|
195
|
+
"topic": "",
|
|
196
|
+
"x": 170,
|
|
197
|
+
"y": 480,
|
|
198
|
+
"wires": [
|
|
199
|
+
[
|
|
200
|
+
"matter_semantic_controller"
|
|
201
|
+
]
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "matter_semantic_controller",
|
|
206
|
+
"type": "knxUltimateMatterControllerDevice",
|
|
207
|
+
"z": "matter_semantic_tab",
|
|
208
|
+
"server": "",
|
|
209
|
+
"serverMatter": "",
|
|
210
|
+
"matterControllerMode": "single",
|
|
211
|
+
"universalService": "batteryMonitor",
|
|
212
|
+
"matterNodeId": "",
|
|
213
|
+
"matterEndpointId": 1,
|
|
214
|
+
"matterDeviceName": "",
|
|
215
|
+
"matterDeviceCapabilities": "",
|
|
216
|
+
"matterMappings": "[]",
|
|
217
|
+
"name": "SELECT A MATTER ENDPOINT",
|
|
218
|
+
"readStatusAtStartup": "no",
|
|
219
|
+
"enableNodePINS": "yes",
|
|
220
|
+
"updateLocalStateFromKNXWrite": true,
|
|
221
|
+
"inputs": 1,
|
|
222
|
+
"outputs": 1,
|
|
223
|
+
"x": 570,
|
|
224
|
+
"y": 330,
|
|
225
|
+
"wires": [
|
|
226
|
+
[
|
|
227
|
+
"matter_semantic_debug"
|
|
228
|
+
]
|
|
229
|
+
]
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "matter_semantic_debug",
|
|
233
|
+
"type": "debug",
|
|
234
|
+
"z": "matter_semantic_tab",
|
|
235
|
+
"name": "Complete Matter response",
|
|
236
|
+
"active": true,
|
|
237
|
+
"tosidebar": true,
|
|
238
|
+
"console": false,
|
|
239
|
+
"tostatus": true,
|
|
240
|
+
"complete": "true",
|
|
241
|
+
"targetType": "full",
|
|
242
|
+
"statusVal": "payload",
|
|
243
|
+
"statusType": "auto",
|
|
244
|
+
"x": 850,
|
|
245
|
+
"y": 330,
|
|
246
|
+
"wires": []
|
|
247
|
+
}
|
|
248
|
+
]
|
package/nodes/commonFunctions.js
CHANGED
|
@@ -7,7 +7,6 @@ const yaml = require('js-yaml')
|
|
|
7
7
|
const dptlib = require('knxultimate').dptlib
|
|
8
8
|
const customHTTP = require('./utils/http')
|
|
9
9
|
const KNXClient = require('knxultimate').KNXClient
|
|
10
|
-
const sysLogger = require('./utils/sysLogger')
|
|
11
10
|
const { normalizeAuthFromAccessTokenQuery } = require('./utils/httpAdminAccessToken')
|
|
12
11
|
|
|
13
12
|
// DATAPONT MANIPULATION HELPERS
|
|
@@ -62,52 +61,6 @@ module.exports = (RED) => {
|
|
|
62
61
|
function commonFunctions () {
|
|
63
62
|
const node = this
|
|
64
63
|
|
|
65
|
-
const ensureBuffer = (rawValue) => {
|
|
66
|
-
if (!rawValue) return null
|
|
67
|
-
if (Buffer.isBuffer(rawValue)) return rawValue
|
|
68
|
-
if (Array.isArray(rawValue)) return Buffer.from(rawValue)
|
|
69
|
-
if (typeof rawValue === 'object' && Array.isArray(rawValue.data)) return Buffer.from(rawValue.data)
|
|
70
|
-
if (rawValue.type === 'Buffer' && Array.isArray(rawValue.data)) return Buffer.from(rawValue.data)
|
|
71
|
-
return null
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const guessDptFromRawValue = (rawBuffer) => {
|
|
75
|
-
if (!rawBuffer || !rawBuffer.length) return null
|
|
76
|
-
if (rawBuffer.length === 1) {
|
|
77
|
-
if (rawBuffer[0] === 0 || rawBuffer[0] === 1) return '1.001'
|
|
78
|
-
return '5.001'
|
|
79
|
-
}
|
|
80
|
-
if (rawBuffer.length === 4) return '14.056'
|
|
81
|
-
if (rawBuffer.length === 2) return '9.001'
|
|
82
|
-
if (rawBuffer.length === 3) return '11.001'
|
|
83
|
-
if (rawBuffer.length === 14) return '16.001'
|
|
84
|
-
|
|
85
|
-
const dpts = Object.entries(dptlib).filter(onlyDptKeys).map(extractBaseNo).sort(sortBy('base')).reduce(toConcattedSubtypes, [])
|
|
86
|
-
for (let index = 0; index < dpts.length; index++) {
|
|
87
|
-
try {
|
|
88
|
-
const resolved = dptlib.resolve(dpts[index].value)
|
|
89
|
-
if (!resolved) continue
|
|
90
|
-
const jsValue = dptlib.fromBuffer(rawBuffer, resolved)
|
|
91
|
-
if (typeof jsValue !== 'undefined') return dpts[index].value
|
|
92
|
-
} catch (error) { /* empty */ }
|
|
93
|
-
}
|
|
94
|
-
return null
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const formatDisplayValue = (value) => {
|
|
98
|
-
if (value === null || value === undefined) return ''
|
|
99
|
-
if (value instanceof Date) return value.toISOString()
|
|
100
|
-
if (typeof value === 'object') {
|
|
101
|
-
try {
|
|
102
|
-
return JSON.stringify(value)
|
|
103
|
-
} catch (error) {
|
|
104
|
-
return String(value)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (typeof value === 'boolean') return value ? 'true' : 'false'
|
|
108
|
-
return String(value)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
64
|
// // Gather infos about all interfaces on the lan and provides a static variable utils.aDiscoveredknxGateways
|
|
112
65
|
// try {
|
|
113
66
|
// require('./utils/utils').DiscoverKNXGateways()
|
|
@@ -624,133 +577,6 @@ module.exports = (RED) => {
|
|
|
624
577
|
}
|
|
625
578
|
})
|
|
626
579
|
|
|
627
|
-
RED.httpAdmin.get('/knxUltimateMonitor', RED.auth.needsPermission('knxUltimate-config.read'), (req, res) => {
|
|
628
|
-
try {
|
|
629
|
-
const server = RED.nodes.getNode(req.query.serverId)
|
|
630
|
-
if (!server) {
|
|
631
|
-
res.json({ items: [], error: 'NO_SERVER' })
|
|
632
|
-
return
|
|
633
|
-
}
|
|
634
|
-
const items = Array.isArray(server.exposedGAs) ? server.exposedGAs.map((entry) => {
|
|
635
|
-
const rawBuffer = ensureBuffer(entry?.rawValue)
|
|
636
|
-
const rawHex = rawBuffer ? rawBuffer.toString('hex') : ''
|
|
637
|
-
let dpt = entry?.dpt
|
|
638
|
-
let guessed = false
|
|
639
|
-
if ((!dpt || dpt === '') && rawBuffer) {
|
|
640
|
-
const inferred = guessDptFromRawValue(rawBuffer)
|
|
641
|
-
if (inferred) {
|
|
642
|
-
dpt = inferred
|
|
643
|
-
guessed = true
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
let value = null
|
|
647
|
-
if (rawBuffer && dpt) {
|
|
648
|
-
try {
|
|
649
|
-
const resolved = dptlib.resolve(dpt)
|
|
650
|
-
if (resolved) value = dptlib.fromBuffer(rawBuffer, resolved)
|
|
651
|
-
} catch (error) { /* empty */ }
|
|
652
|
-
}
|
|
653
|
-
return {
|
|
654
|
-
ga: entry?.ga || '',
|
|
655
|
-
devicename: entry?.devicename || '',
|
|
656
|
-
dpt: dpt || '',
|
|
657
|
-
dptGuessed: guessed,
|
|
658
|
-
rawHex,
|
|
659
|
-
value,
|
|
660
|
-
valueText: formatDisplayValue(value),
|
|
661
|
-
updatedAt: entry?.updatedAt || null
|
|
662
|
-
}
|
|
663
|
-
}).sort((a, b) => a.ga.localeCompare(b.ga)) : []
|
|
664
|
-
res.json({ items })
|
|
665
|
-
} catch (error) {
|
|
666
|
-
try { RED.log.error(`KNXUltimate: knxUltimateMonitor error: ${error.message}`) } catch (e) { }
|
|
667
|
-
res.json({ items: [], error: error.message })
|
|
668
|
-
}
|
|
669
|
-
})
|
|
670
|
-
|
|
671
|
-
RED.httpAdmin.post('/knxUltimateMonitorToggle', RED.auth.needsPermission('knxUltimate-config.write'), (req, res) => {
|
|
672
|
-
try {
|
|
673
|
-
const serverId = req.body?.serverId
|
|
674
|
-
const ga = req.body?.ga
|
|
675
|
-
const server = serverId ? RED.nodes.getNode(serverId) : null
|
|
676
|
-
if (!server) {
|
|
677
|
-
res.json({ status: 'error', error: 'NO_SERVER' })
|
|
678
|
-
return
|
|
679
|
-
}
|
|
680
|
-
if (!ga) {
|
|
681
|
-
res.json({ status: 'error', error: 'NO_GA' })
|
|
682
|
-
return
|
|
683
|
-
}
|
|
684
|
-
const entry = Array.isArray(server.exposedGAs) ? server.exposedGAs.find((item) => item.ga === ga) : undefined
|
|
685
|
-
if (!entry) {
|
|
686
|
-
res.json({ status: 'error', error: 'GA_NOT_FOUND' })
|
|
687
|
-
return
|
|
688
|
-
}
|
|
689
|
-
const rawBuffer = ensureBuffer(entry.rawValue)
|
|
690
|
-
let dpt = entry.dpt
|
|
691
|
-
if (!rawBuffer) {
|
|
692
|
-
res.json({ status: 'error', error: 'NO_CURRENT_VALUE' })
|
|
693
|
-
return
|
|
694
|
-
}
|
|
695
|
-
if (!dpt) {
|
|
696
|
-
const inferred = guessDptFromRawValue(rawBuffer)
|
|
697
|
-
if (inferred) dpt = inferred
|
|
698
|
-
}
|
|
699
|
-
let currentValue = null
|
|
700
|
-
if (dpt) {
|
|
701
|
-
try {
|
|
702
|
-
const resolved = dptlib.resolve(dpt)
|
|
703
|
-
if (resolved) currentValue = dptlib.fromBuffer(rawBuffer, resolved)
|
|
704
|
-
} catch (error) { currentValue = null }
|
|
705
|
-
}
|
|
706
|
-
if (typeof currentValue !== 'boolean') {
|
|
707
|
-
res.json({ status: 'error', error: 'NOT_BOOLEAN' })
|
|
708
|
-
return
|
|
709
|
-
}
|
|
710
|
-
const nextValue = !currentValue
|
|
711
|
-
const sendDpt = dpt || '1.001'
|
|
712
|
-
try {
|
|
713
|
-
server.sendKNXTelegramToKNXEngine({
|
|
714
|
-
grpaddr: ga,
|
|
715
|
-
payload: nextValue,
|
|
716
|
-
dpt: sendDpt,
|
|
717
|
-
outputtype: 'write',
|
|
718
|
-
nodecallerid: 'knxUltimateMonitor'
|
|
719
|
-
})
|
|
720
|
-
} catch (error) {
|
|
721
|
-
res.json({ status: 'error', error: error.message })
|
|
722
|
-
return
|
|
723
|
-
}
|
|
724
|
-
res.json({ status: 'ok', value: nextValue })
|
|
725
|
-
} catch (error) {
|
|
726
|
-
try { RED.log.error(`KNXUltimate: knxUltimateMonitorToggle error: ${error.message}`) } catch (e) { }
|
|
727
|
-
res.json({ status: 'error', error: error.message })
|
|
728
|
-
}
|
|
729
|
-
})
|
|
730
|
-
|
|
731
|
-
RED.httpAdmin.get('/knxUltimateDebugLog', RED.auth.needsPermission('knxUltimate-config.read'), (req, res) => {
|
|
732
|
-
try {
|
|
733
|
-
const rawSince = req.query?.sinceSeq ?? req.query?.since ?? req.query?.after ?? null
|
|
734
|
-
let sinceSeq = null
|
|
735
|
-
if (rawSince !== null && rawSince !== undefined) {
|
|
736
|
-
const parsed = Number(rawSince)
|
|
737
|
-
if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {
|
|
738
|
-
sinceSeq = Math.floor(parsed)
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
const snapshot = sinceSeq === null ? sysLogger.getDebugSnapshot() : sysLogger.getDebugSnapshot({ sinceSeq })
|
|
742
|
-
res.json({
|
|
743
|
-
entries: snapshot.entries,
|
|
744
|
-
latestSeq: snapshot.latestSeq,
|
|
745
|
-
total: snapshot.total,
|
|
746
|
-
limit: snapshot.limit
|
|
747
|
-
})
|
|
748
|
-
} catch (error) {
|
|
749
|
-
try { RED.log.error(`KNXUltimate: knxUltimateDebugLog error: ${error.message}`) } catch (e) { }
|
|
750
|
-
res.json({ entries: [], error: error.message })
|
|
751
|
-
}
|
|
752
|
-
})
|
|
753
|
-
|
|
754
580
|
RED.httpAdmin.post('/KNXUltimateLocateHueDevice', async (req, res) => {
|
|
755
581
|
const respondError = (status, message) => {
|
|
756
582
|
res.status(status).json({ error: message })
|