@bitpoolos/edge-bacnet 1.5.3 → 1.6.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 +155 -10
- package/bacnet_client.js +123 -107
- package/bacnet_gateway.html +22 -6
- package/bacnet_gateway.js +346 -250
- package/bacnet_inspector.html +43 -0
- package/bacnet_inspector.js +1420 -0
- package/bacnet_inspector_worker.js +535 -0
- package/bacnet_read.html +27 -27
- package/bacnet_read.js +0 -3
- package/common.js +201 -38
- package/examples/1-Discover-Read.json +170 -1
- package/examples/2-Discover-Write.json +164 -1
- package/examples/3-Discover-Read-Write.json +227 -1
- package/examples/4-Inspector.json +368 -0
- package/inspector.html +455 -0
- package/package.json +6 -2
- package/resources/Logo_Simplified_Positive.svg +32 -0
- package/resources/downloadAsHtml.js +656 -0
- package/resources/icons/device-id-change-icon.svg +4 -0
- package/resources/icons/device-id-conflict-icon.svg +4 -0
- package/resources/icons/favicon.ico +0 -0
- package/resources/icons/points-error-icon.svg +4 -0
- package/resources/icons/points-missing-icon.svg +4 -0
- package/resources/icons/points-ok-icon.svg +4 -0
- package/resources/icons/points-unmapped-icon.svg +5 -0
- package/resources/icons/points-warning-icon.svg +4 -0
- package/resources/inspector.css +25312 -0
- package/resources/inspectorStyle.css +254 -0
- package/resources/inspectorStyles.css +503 -0
- package/resources/primevue.min.js +1 -0
- package/resources/style.css +17 -1
- package/resources/vue3513.global.prod.js +9 -0
- package/ssrHtmlExporter.js +537 -0
- package/treeBuilder.js +3 -3
package/common.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
|
-
MIT License Copyright 2021,
|
|
2
|
+
MIT License Copyright 2021, 2025 - Bitpool Pty Ltd
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { createLogger, format, transports } = require("winston");
|
|
6
5
|
const { randomUUID } = require("crypto");
|
|
7
6
|
const os = require("os");
|
|
8
|
-
const { exec } = require("child_process");
|
|
9
7
|
const baEnum = require("./resources/node-bacstack-ts/dist/index.js").enum;
|
|
10
8
|
const fs = require("fs");
|
|
9
|
+
const fs2 = require("fs").promises;
|
|
11
10
|
|
|
12
11
|
class BacnetConfig {
|
|
13
12
|
constructor(
|
|
@@ -102,8 +101,6 @@ class BacnetClientConfig {
|
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
104
|
class ReadCommandConfig {
|
|
108
105
|
constructor(pointsToRead, objectProperties, decimalPrecision) {
|
|
109
106
|
this.pointsToRead = pointsToRead;
|
|
@@ -190,30 +187,12 @@ const roundDecimalPlaces = function (value, decimals) {
|
|
|
190
187
|
return value;
|
|
191
188
|
};
|
|
192
189
|
|
|
193
|
-
const doNodeRedRestart = function () {
|
|
194
|
-
return new Promise(function (resolve, reject) {
|
|
195
|
-
try {
|
|
196
|
-
exec("restart", (error, stdout, stderr) => {
|
|
197
|
-
if (error) {
|
|
198
|
-
console.log(`Node-Red restart error: ${error.message}`);
|
|
199
|
-
reject(error.message);
|
|
200
|
-
}
|
|
201
|
-
if (stderr) {
|
|
202
|
-
console.log(`Node-Red restart stderr: ${stderr}`);
|
|
203
|
-
reject(stderr);
|
|
204
|
-
}
|
|
205
|
-
resolve(stdout);
|
|
206
|
-
});
|
|
207
|
-
} catch (e) {
|
|
208
|
-
console.log(`Node-Red restart error: ${e}`);
|
|
209
|
-
reject(e);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
};
|
|
213
|
-
|
|
214
190
|
// STORE CONFIG FUNCTION ==========================================================
|
|
215
191
|
//
|
|
216
192
|
// ================================================================================
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
|
|
217
196
|
async function Store_Config(data) {
|
|
218
197
|
try {
|
|
219
198
|
await fs.writeFile("edge-bacnet-datastore.cfg", data, { encoding: "utf8", flag: "w" }, (err) => {
|
|
@@ -226,18 +205,185 @@ async function Store_Config(data) {
|
|
|
226
205
|
}
|
|
227
206
|
}
|
|
228
207
|
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
// refactor:
|
|
211
|
+
|
|
212
|
+
let storeQueue = [];
|
|
213
|
+
let isStoreProcessing = false;
|
|
214
|
+
|
|
215
|
+
async function queueConfigStore(data) {
|
|
216
|
+
storeQueue.push(data);
|
|
217
|
+
|
|
218
|
+
if (!isStoreProcessing) {
|
|
219
|
+
isStoreProcessing = true;
|
|
220
|
+
|
|
221
|
+
while (storeQueue.length > 0) {
|
|
222
|
+
const nextData = storeQueue.pop(); // Get most recent data
|
|
223
|
+
storeQueue.length = 0; // Clear any accumulated data
|
|
224
|
+
|
|
225
|
+
await Store_Config(nextData);
|
|
226
|
+
|
|
227
|
+
// Add small delay between attempts
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
isStoreProcessing = false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function Store_Config(data) {
|
|
236
|
+
const mainFile = "edge-bacnet-datastore.cfg";
|
|
237
|
+
const tempFile = "edge-bacnet-datastore.cfg.tmp";
|
|
238
|
+
const backupFile = "edge-bacnet-datastore.cfg.bak";
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
// First validate the JSON to ensure it's valid before writing
|
|
242
|
+
try {
|
|
243
|
+
JSON.parse(JSON.stringify(data));
|
|
244
|
+
} catch (jsonError) {
|
|
245
|
+
console.error("Invalid JSON data detected:", jsonError);
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Write to temporary file first
|
|
250
|
+
await fs2.writeFile(tempFile, JSON.stringify(data, null, 2), { encoding: "utf8" });
|
|
251
|
+
|
|
252
|
+
// Verify the temporary file is valid JSON
|
|
253
|
+
try {
|
|
254
|
+
const tempContent = await fs2.readFile(tempFile, "utf8");
|
|
255
|
+
JSON.parse(tempContent);
|
|
256
|
+
} catch (verifyError) {
|
|
257
|
+
console.error("Temporary file validation failed:", verifyError);
|
|
258
|
+
await fs2.unlink(tempFile).catch(() => {});
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Create backup of current file if it exists
|
|
263
|
+
try {
|
|
264
|
+
await fs2.access(mainFile);
|
|
265
|
+
await fs2.copyFile(mainFile, backupFile);
|
|
266
|
+
} catch (backupError) {
|
|
267
|
+
// If main file doesn't exist, no backup needed
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Atomic rename of temporary file to main file
|
|
271
|
+
await fs2.rename(tempFile, mainFile);
|
|
272
|
+
return true;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error("Store_Config error:", error);
|
|
275
|
+
|
|
276
|
+
// Cleanup temporary file if it exists
|
|
277
|
+
try {
|
|
278
|
+
await fs2.unlink(tempFile).catch(() => {});
|
|
279
|
+
} catch (cleanupError) {}
|
|
280
|
+
|
|
281
|
+
// If main file is corrupted and backup exists, restore from backup
|
|
282
|
+
try {
|
|
283
|
+
const backupExists = await fs2.access(backupFile).catch(() => false);
|
|
284
|
+
if (backupExists) {
|
|
285
|
+
await fs2.copyFile(backupFile, mainFile);
|
|
286
|
+
console.log("Restored from backup file");
|
|
287
|
+
}
|
|
288
|
+
} catch (restoreError) {
|
|
289
|
+
console.error("Failed to restore from backup:", restoreError);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
229
296
|
// READ CONFIG SYNC FUNCTION ======================================================
|
|
230
297
|
//
|
|
231
298
|
// ================================================================================
|
|
299
|
+
|
|
232
300
|
function Read_Config_Sync() {
|
|
233
|
-
|
|
301
|
+
const mainFile = "edge-bacnet-datastore.cfg";
|
|
302
|
+
const backupFile = "edge-bacnet-datastore.cfg.bak";
|
|
303
|
+
const defaultData = "{}";
|
|
304
|
+
|
|
234
305
|
try {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
306
|
+
// Try to read the main file
|
|
307
|
+
let data = fsSync.readFileSync(mainFile, { encoding: "utf8" });
|
|
308
|
+
|
|
309
|
+
// Validate JSON
|
|
310
|
+
try {
|
|
311
|
+
JSON.parse(data);
|
|
312
|
+
return data;
|
|
313
|
+
} catch (jsonError) {
|
|
314
|
+
console.error("Main file contains invalid JSON, attempting backup recovery");
|
|
315
|
+
|
|
316
|
+
// Try to read backup file
|
|
317
|
+
try {
|
|
318
|
+
const backupData = fsSync.readFileSync(backupFile, { encoding: "utf8" });
|
|
319
|
+
JSON.parse(backupData); // Validate backup JSON
|
|
320
|
+
|
|
321
|
+
// Restore from backup
|
|
322
|
+
fsSync.copyFileSync(backupFile, mainFile);
|
|
323
|
+
console.log("Successfully restored from backup file");
|
|
324
|
+
return backupData;
|
|
325
|
+
} catch (backupError) {
|
|
326
|
+
console.error("Backup recovery failed, creating new file");
|
|
327
|
+
fsSync.writeFileSync(mainFile, defaultData, { encoding: "utf8" });
|
|
328
|
+
return defaultData;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} catch (error) {
|
|
332
|
+
console.error("Error reading config:", error);
|
|
333
|
+
fsSync.writeFileSync(mainFile, defaultData, { encoding: "utf8" });
|
|
334
|
+
return defaultData;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// refactor:
|
|
339
|
+
|
|
340
|
+
async function Read_Config_Async() {
|
|
341
|
+
// todo rename function, not using sync
|
|
342
|
+
const mainFile = "edge-bacnet-datastore.cfg";
|
|
343
|
+
const backupFile = "edge-bacnet-datastore.cfg.bak";
|
|
344
|
+
const defaultData = "{}";
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
// Try to read the main file
|
|
348
|
+
const data = await fs2.readFile(mainFile, { encoding: "utf8" });
|
|
349
|
+
|
|
350
|
+
// Validate JSON
|
|
351
|
+
try {
|
|
352
|
+
JSON.parse(data);
|
|
353
|
+
|
|
354
|
+
return data;
|
|
355
|
+
} catch (jsonError) {
|
|
356
|
+
console.error("Main file contains invalid JSON, attempting backup recovery");
|
|
357
|
+
|
|
358
|
+
// Try to read backup file
|
|
359
|
+
try {
|
|
360
|
+
const backupData = await fs2.readFile(backupFile, { encoding: "utf8" });
|
|
361
|
+
JSON.parse(backupData); // Validate backup JSON
|
|
362
|
+
|
|
363
|
+
// Restore from backup
|
|
364
|
+
await fs.copyFile(backupFile, mainFile);
|
|
365
|
+
console.log("Successfully restored from backup file");
|
|
366
|
+
|
|
367
|
+
console.log("log2");
|
|
368
|
+
|
|
369
|
+
return backupData;
|
|
370
|
+
} catch (backupError) {
|
|
371
|
+
console.error("Backup recovery failed, creating new file");
|
|
372
|
+
await Store_Config(defaultData);
|
|
373
|
+
|
|
374
|
+
console.log("log3");
|
|
375
|
+
|
|
376
|
+
return defaultData;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.error("Error reading config:", error);
|
|
381
|
+
await Store_Config(defaultData);
|
|
382
|
+
|
|
383
|
+
console.log("log4");
|
|
384
|
+
|
|
385
|
+
return defaultData;
|
|
239
386
|
}
|
|
240
|
-
return data;
|
|
241
387
|
}
|
|
242
388
|
|
|
243
389
|
// STORE CONFIG FUNCTION - BACNET SERVER ==========================================
|
|
@@ -250,7 +396,7 @@ async function Store_Config_Server(data) {
|
|
|
250
396
|
//console.log("Store_Config_Server writeFile error: ", err);
|
|
251
397
|
}
|
|
252
398
|
});
|
|
253
|
-
} catch (err) {
|
|
399
|
+
} catch (err) {}
|
|
254
400
|
}
|
|
255
401
|
|
|
256
402
|
// READ CONFIG SYNC FUNCTION - BACNET SERVER ======================================
|
|
@@ -288,12 +434,12 @@ function decodeBitArray(size, bits) {
|
|
|
288
434
|
if (i == bits.length - 1) {
|
|
289
435
|
return array;
|
|
290
436
|
}
|
|
291
|
-
}
|
|
437
|
+
}
|
|
292
438
|
}
|
|
293
439
|
|
|
294
440
|
function getBacnetErrorString(classInt, codeInt) {
|
|
295
|
-
const classString = Object.keys(baEnum.ErrorClass).find(key => baEnum.ErrorClass[key] === classInt);
|
|
296
|
-
const codeString = Object.keys(baEnum.ErrorCode).find(key => baEnum.ErrorCode[key] === codeInt);
|
|
441
|
+
const classString = Object.keys(baEnum.ErrorClass).find((key) => baEnum.ErrorClass[key] === classInt);
|
|
442
|
+
const codeString = Object.keys(baEnum.ErrorCode).find((key) => baEnum.ErrorCode[key] === codeInt);
|
|
297
443
|
return `BacnetError - Class:${classString} - Code:${codeString}`;
|
|
298
444
|
}
|
|
299
445
|
|
|
@@ -309,7 +455,22 @@ function parseBacnetError(error) {
|
|
|
309
455
|
}
|
|
310
456
|
|
|
311
457
|
return err;
|
|
312
|
-
}
|
|
458
|
+
}
|
|
459
|
+
function debounce(func, wait) {
|
|
460
|
+
let timeout;
|
|
461
|
+
|
|
462
|
+
return function (...args) {
|
|
463
|
+
const context = this;
|
|
464
|
+
|
|
465
|
+
// Clear the previous timeout
|
|
466
|
+
clearTimeout(timeout);
|
|
467
|
+
|
|
468
|
+
// Set a new timeout
|
|
469
|
+
timeout = setTimeout(() => {
|
|
470
|
+
func.apply(context, args);
|
|
471
|
+
}, wait);
|
|
472
|
+
};
|
|
473
|
+
}
|
|
313
474
|
|
|
314
475
|
module.exports = {
|
|
315
476
|
BacnetConfig,
|
|
@@ -320,13 +481,15 @@ module.exports = {
|
|
|
320
481
|
generateId,
|
|
321
482
|
getIpAddress,
|
|
322
483
|
roundDecimalPlaces,
|
|
323
|
-
|
|
484
|
+
queueConfigStore,
|
|
324
485
|
Store_Config,
|
|
325
486
|
Read_Config_Sync,
|
|
487
|
+
Read_Config_Async,
|
|
326
488
|
Store_Config_Server,
|
|
327
489
|
Read_Config_Sync_Server,
|
|
328
490
|
isNumber,
|
|
329
491
|
decodeBitArray,
|
|
330
492
|
parseBacnetError,
|
|
331
493
|
getBacnetErrorString,
|
|
494
|
+
debounce,
|
|
332
495
|
};
|
|
@@ -1 +1,170 @@
|
|
|
1
|
-
[
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "ba92a36a18ffdfac",
|
|
4
|
+
"type": "Bacnet-Gateway",
|
|
5
|
+
"z": "f1fc21f44027188c",
|
|
6
|
+
"name": "",
|
|
7
|
+
"local_device_address": "",
|
|
8
|
+
"local_interface_name": "",
|
|
9
|
+
"apduTimeout": 6000,
|
|
10
|
+
"roundDecimal": 2,
|
|
11
|
+
"local_device_port": 47808,
|
|
12
|
+
"apduSize": "5",
|
|
13
|
+
"maxSegments": "0x50",
|
|
14
|
+
"retries": "5",
|
|
15
|
+
"broadCastAddr": "255.255.255.255",
|
|
16
|
+
"toLogIam": false,
|
|
17
|
+
"discover_polling_schedule": "900",
|
|
18
|
+
"discover_polling_schedule_value": "15",
|
|
19
|
+
"discover_polling_schedule_options": "Minutes",
|
|
20
|
+
"deviceId": 817001,
|
|
21
|
+
"logErrorToConsole": false,
|
|
22
|
+
"serverEnabled": true,
|
|
23
|
+
"device_read_schedule": "900",
|
|
24
|
+
"device_read_schedule_value": "15",
|
|
25
|
+
"device_read_schedule_options": "Minutes",
|
|
26
|
+
"deviceRangeRegisters": [
|
|
27
|
+
{
|
|
28
|
+
"enabled": true,
|
|
29
|
+
"start": "0",
|
|
30
|
+
"end": "4194303"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"portRangeRegisters": [
|
|
34
|
+
{
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"start": "47808",
|
|
37
|
+
"end": "47808"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"cacheFileEnabled": false,
|
|
41
|
+
"sanitise_device_schedule": "3600",
|
|
42
|
+
"sanitise_device_schedule_value": "1",
|
|
43
|
+
"sanitise_device_schedule_options": "Hours",
|
|
44
|
+
"x": 800,
|
|
45
|
+
"y": 460,
|
|
46
|
+
"wires": [
|
|
47
|
+
[
|
|
48
|
+
"0688901dadf6d984"
|
|
49
|
+
]
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "c404d53530d50ce9",
|
|
54
|
+
"type": "Bacnet-Discovery",
|
|
55
|
+
"z": "f1fc21f44027188c",
|
|
56
|
+
"name": "",
|
|
57
|
+
"events": true,
|
|
58
|
+
"json": true,
|
|
59
|
+
"mqtt": false,
|
|
60
|
+
"pointJson": false,
|
|
61
|
+
"hiddenDeployToggle": false,
|
|
62
|
+
"prevHiddenToggleState": false,
|
|
63
|
+
"roundDecimal": 2,
|
|
64
|
+
"pointsToRead": {},
|
|
65
|
+
"readDevices": [],
|
|
66
|
+
"object_property_simplePayload": false,
|
|
67
|
+
"object_property_simpleWithStatus": false,
|
|
68
|
+
"object_property_fullObject": true,
|
|
69
|
+
"useDeviceName": true,
|
|
70
|
+
"x": 630,
|
|
71
|
+
"y": 400,
|
|
72
|
+
"wires": [
|
|
73
|
+
[
|
|
74
|
+
"ba92a36a18ffdfac"
|
|
75
|
+
]
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "d89267e068e24882",
|
|
80
|
+
"type": "Bitpool-Inject",
|
|
81
|
+
"z": "f1fc21f44027188c",
|
|
82
|
+
"name": "Poll",
|
|
83
|
+
"props": [
|
|
84
|
+
{
|
|
85
|
+
"p": "payload"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"p": "topic",
|
|
89
|
+
"vt": "str"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"repeat": "",
|
|
93
|
+
"crontab": "",
|
|
94
|
+
"once": false,
|
|
95
|
+
"onceDelay": 0.1,
|
|
96
|
+
"topic": "",
|
|
97
|
+
"payload": "",
|
|
98
|
+
"payloadType": "date",
|
|
99
|
+
"doPoll": true,
|
|
100
|
+
"doDiscover": false,
|
|
101
|
+
"json": false,
|
|
102
|
+
"mqtt": false,
|
|
103
|
+
"pointJson": true,
|
|
104
|
+
"object_property_simplePayload": false,
|
|
105
|
+
"object_property_simpleWithStatus": false,
|
|
106
|
+
"object_property_fullObject": true,
|
|
107
|
+
"useDeviceName": true,
|
|
108
|
+
"x": 470,
|
|
109
|
+
"y": 400,
|
|
110
|
+
"wires": [
|
|
111
|
+
[
|
|
112
|
+
"c404d53530d50ce9"
|
|
113
|
+
]
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "5f5537b37018ec25",
|
|
118
|
+
"type": "Bitpool-Inject",
|
|
119
|
+
"z": "f1fc21f44027188c",
|
|
120
|
+
"name": "Discover",
|
|
121
|
+
"props": [
|
|
122
|
+
{
|
|
123
|
+
"p": "payload"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"p": "topic",
|
|
127
|
+
"vt": "str"
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"repeat": "",
|
|
131
|
+
"crontab": "",
|
|
132
|
+
"once": false,
|
|
133
|
+
"onceDelay": 0.1,
|
|
134
|
+
"topic": "",
|
|
135
|
+
"payload": "",
|
|
136
|
+
"payloadType": "date",
|
|
137
|
+
"doPoll": false,
|
|
138
|
+
"doDiscover": true,
|
|
139
|
+
"json": false,
|
|
140
|
+
"mqtt": false,
|
|
141
|
+
"pointJson": true,
|
|
142
|
+
"object_property_simplePayload": false,
|
|
143
|
+
"object_property_simpleWithStatus": false,
|
|
144
|
+
"object_property_fullObject": true,
|
|
145
|
+
"useDeviceName": true,
|
|
146
|
+
"x": 620,
|
|
147
|
+
"y": 460,
|
|
148
|
+
"wires": [
|
|
149
|
+
[
|
|
150
|
+
"ba92a36a18ffdfac"
|
|
151
|
+
]
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "0688901dadf6d984",
|
|
156
|
+
"type": "debug",
|
|
157
|
+
"z": "f1fc21f44027188c",
|
|
158
|
+
"name": "debug 1",
|
|
159
|
+
"active": true,
|
|
160
|
+
"tosidebar": true,
|
|
161
|
+
"console": false,
|
|
162
|
+
"tostatus": false,
|
|
163
|
+
"complete": "false",
|
|
164
|
+
"statusVal": "",
|
|
165
|
+
"statusType": "auto",
|
|
166
|
+
"x": 1000,
|
|
167
|
+
"y": 460,
|
|
168
|
+
"wires": []
|
|
169
|
+
}
|
|
170
|
+
]
|
|
@@ -1 +1,164 @@
|
|
|
1
|
-
[
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "25ee9078510fe398",
|
|
4
|
+
"type": "Bacnet-Gateway",
|
|
5
|
+
"z": "f1fc21f44027188c",
|
|
6
|
+
"name": "",
|
|
7
|
+
"local_device_address": "",
|
|
8
|
+
"local_interface_name": "",
|
|
9
|
+
"apduTimeout": 6000,
|
|
10
|
+
"roundDecimal": 2,
|
|
11
|
+
"local_device_port": 47808,
|
|
12
|
+
"apduSize": "5",
|
|
13
|
+
"maxSegments": "0x50",
|
|
14
|
+
"retries": "5",
|
|
15
|
+
"broadCastAddr": "255.255.255.255",
|
|
16
|
+
"toLogIam": false,
|
|
17
|
+
"discover_polling_schedule": "900",
|
|
18
|
+
"discover_polling_schedule_value": "15",
|
|
19
|
+
"discover_polling_schedule_options": "Minutes",
|
|
20
|
+
"deviceId": 817001,
|
|
21
|
+
"logErrorToConsole": false,
|
|
22
|
+
"serverEnabled": true,
|
|
23
|
+
"device_read_schedule": "900",
|
|
24
|
+
"device_read_schedule_value": "15",
|
|
25
|
+
"device_read_schedule_options": "Minutes",
|
|
26
|
+
"deviceRangeRegisters": [
|
|
27
|
+
{
|
|
28
|
+
"enabled": true,
|
|
29
|
+
"start": "0",
|
|
30
|
+
"end": "4194303"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"portRangeRegisters": [
|
|
34
|
+
{
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"start": "47808",
|
|
37
|
+
"end": "47808"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"cacheFileEnabled": true,
|
|
41
|
+
"sanitise_device_schedule": "3600",
|
|
42
|
+
"sanitise_device_schedule_value": "1",
|
|
43
|
+
"sanitise_device_schedule_options": "Hours",
|
|
44
|
+
"x": 840,
|
|
45
|
+
"y": 420,
|
|
46
|
+
"wires": [
|
|
47
|
+
[
|
|
48
|
+
"f41ef6737463370e"
|
|
49
|
+
]
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "0f90856ca1808ee7",
|
|
54
|
+
"type": "Bitpool-Inject",
|
|
55
|
+
"z": "f1fc21f44027188c",
|
|
56
|
+
"name": "Discover",
|
|
57
|
+
"props": [
|
|
58
|
+
{
|
|
59
|
+
"p": "payload"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"p": "topic",
|
|
63
|
+
"vt": "str"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"repeat": "",
|
|
67
|
+
"crontab": "",
|
|
68
|
+
"once": false,
|
|
69
|
+
"onceDelay": 0.1,
|
|
70
|
+
"topic": "",
|
|
71
|
+
"payload": "",
|
|
72
|
+
"payloadType": "date",
|
|
73
|
+
"doPoll": false,
|
|
74
|
+
"doDiscover": true,
|
|
75
|
+
"json": false,
|
|
76
|
+
"mqtt": false,
|
|
77
|
+
"pointJson": true,
|
|
78
|
+
"object_property_simplePayload": false,
|
|
79
|
+
"object_property_simpleWithStatus": false,
|
|
80
|
+
"object_property_fullObject": true,
|
|
81
|
+
"useDeviceName": true,
|
|
82
|
+
"x": 660,
|
|
83
|
+
"y": 420,
|
|
84
|
+
"wires": [
|
|
85
|
+
[
|
|
86
|
+
"25ee9078510fe398"
|
|
87
|
+
]
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "c7f1aa7764f29aa1",
|
|
92
|
+
"type": "Bacnet-Write",
|
|
93
|
+
"z": "f1fc21f44027188c",
|
|
94
|
+
"name": "",
|
|
95
|
+
"applicationTag": "4",
|
|
96
|
+
"priority": "16",
|
|
97
|
+
"pointsToWrite": [],
|
|
98
|
+
"writeDevices": [],
|
|
99
|
+
"hiddenDeployToggle": false,
|
|
100
|
+
"prevHiddenToggleState": false,
|
|
101
|
+
"x": 670,
|
|
102
|
+
"y": 500,
|
|
103
|
+
"wires": [
|
|
104
|
+
[
|
|
105
|
+
"25ee9078510fe398"
|
|
106
|
+
]
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "c97fbed9db70de7f",
|
|
111
|
+
"type": "Bitpool-Inject",
|
|
112
|
+
"z": "f1fc21f44027188c",
|
|
113
|
+
"name": "Poll",
|
|
114
|
+
"props": [
|
|
115
|
+
{
|
|
116
|
+
"p": "payload"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"p": "topic",
|
|
120
|
+
"vt": "str"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"repeat": "",
|
|
124
|
+
"crontab": "",
|
|
125
|
+
"once": false,
|
|
126
|
+
"onceDelay": 0.1,
|
|
127
|
+
"topic": "",
|
|
128
|
+
"payload": "",
|
|
129
|
+
"payloadType": "date",
|
|
130
|
+
"doPoll": true,
|
|
131
|
+
"doDiscover": false,
|
|
132
|
+
"json": false,
|
|
133
|
+
"mqtt": false,
|
|
134
|
+
"pointJson": true,
|
|
135
|
+
"object_property_simplePayload": false,
|
|
136
|
+
"object_property_simpleWithStatus": false,
|
|
137
|
+
"object_property_fullObject": true,
|
|
138
|
+
"useDeviceName": true,
|
|
139
|
+
"x": 490,
|
|
140
|
+
"y": 500,
|
|
141
|
+
"wires": [
|
|
142
|
+
[
|
|
143
|
+
"c7f1aa7764f29aa1"
|
|
144
|
+
]
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "f41ef6737463370e",
|
|
149
|
+
"type": "debug",
|
|
150
|
+
"z": "f1fc21f44027188c",
|
|
151
|
+
"name": "debug 1",
|
|
152
|
+
"active": true,
|
|
153
|
+
"tosidebar": true,
|
|
154
|
+
"console": false,
|
|
155
|
+
"tostatus": false,
|
|
156
|
+
"complete": "true",
|
|
157
|
+
"targetType": "full",
|
|
158
|
+
"statusVal": "",
|
|
159
|
+
"statusType": "auto",
|
|
160
|
+
"x": 1040,
|
|
161
|
+
"y": 420,
|
|
162
|
+
"wires": []
|
|
163
|
+
}
|
|
164
|
+
]
|