@bitpoolos/edge-bacnet 1.2.6 → 1.2.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/bacnet_client.js +404 -183
- package/bacnet_device.js +52 -0
- package/bacnet_gateway.html +10 -3
- package/bacnet_gateway.js +93 -37
- package/bacnet_read.html +53 -33
- package/bacnet_read.js +8 -2
- package/bacnet_write.html +105 -29
- package/bacnet_write.js +1 -1
- package/common.js +28 -12
- package/package.json +2 -2
- package/resources/icons/icon-read.svg +19 -0
- package/resources/icons/icon-write.svg +16 -0
- package/resources/node-bacstack-ts/dist/lib/client.js +3 -3
- package/resources/style.css +11 -0
package/bacnet_device.js
CHANGED
|
@@ -20,6 +20,18 @@ class BacnetDevice {
|
|
|
20
20
|
that.priorityQueue = config.priorityQueue;
|
|
21
21
|
that.lastPriorityQueueTS = config.lastPriorityQueueTS;
|
|
22
22
|
|
|
23
|
+
if(config.childDevices) {
|
|
24
|
+
that.childDevices = config.childDevices;
|
|
25
|
+
} else {
|
|
26
|
+
that.childDevices = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if(config.parentDeviceId) {
|
|
30
|
+
that.parentDeviceId = config.parentDeviceId;
|
|
31
|
+
} else {
|
|
32
|
+
that.parentDeviceId = null;
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
} else if(fromImport == false) {
|
|
24
36
|
if(config.net && config.adr) {
|
|
25
37
|
that.address = {address: config.address, net: config.net, adr: config.adr};
|
|
@@ -42,9 +54,49 @@ class BacnetDevice {
|
|
|
42
54
|
that.priorityQueueIsActive = false;
|
|
43
55
|
that.priorityQueue = [];
|
|
44
56
|
that.lastPriorityQueueTS = null;
|
|
57
|
+
that.childDevices = [];
|
|
58
|
+
that.parentDeviceId = null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setParentDeviceId(deviceId) {
|
|
63
|
+
this.parentDeviceId = deviceId;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getParentDeviceId() {
|
|
67
|
+
return this.parentDeviceId;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
hasChildDevices() {
|
|
71
|
+
if(this.childDevices.length > 0) {
|
|
72
|
+
return true;
|
|
73
|
+
} else if(this.childDevices.length == 0) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addChildDevice(deviceId) {
|
|
79
|
+
let foundIndex = this.childDevices.findIndex(ele => ele == deviceId);
|
|
80
|
+
|
|
81
|
+
if(foundIndex == -1) {
|
|
82
|
+
this.childDevices.push(deviceId);
|
|
83
|
+
} else {
|
|
84
|
+
this.childDevices[foundIndex] = deviceId
|
|
45
85
|
}
|
|
46
86
|
}
|
|
47
87
|
|
|
88
|
+
getChildDevice(deviceId) {
|
|
89
|
+
let foundIndex = this.childDevices.findIndex(ele => ele == deviceId);
|
|
90
|
+
|
|
91
|
+
if(foundIndex !== -1) return this.childDevices[foundIndex];
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getChildDevices() {
|
|
97
|
+
return this.childDevices;
|
|
98
|
+
}
|
|
99
|
+
|
|
48
100
|
setLastPriorityQueueTS() {
|
|
49
101
|
this.lastPriorityQueueTS = Date.now();
|
|
50
102
|
}
|
package/bacnet_gateway.html
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
MIT License Copyright 2021,
|
|
2
|
+
MIT License Copyright 2021, 2024 - Bitpool Pty Ltd
|
|
3
3
|
-->
|
|
4
4
|
<!-- PrimeVue -->
|
|
5
5
|
<link href="resources/@bitpoolos/edge-bacnet/primevue-saga-blue-theme.css" rel="stylesheet" />
|
|
6
6
|
<link href="resources/@bitpoolos/edge-bacnet/primevue.min.css" rel="stylesheet" />
|
|
7
7
|
<link href="resources/@bitpoolos/edge-bacnet/primeflex.min.css" rel="stylesheet" />
|
|
8
8
|
<link href="resources/@bitpoolos/edge-bacnet/primeicons.css" rel="stylesheet" />
|
|
9
|
+
<link href="resources/@bitpoolos/edge-bacnet/style.css" rel="stylesheet" />
|
|
9
10
|
|
|
10
11
|
<script>
|
|
11
12
|
//custom script loader to ensure dependencies load every time
|
|
@@ -113,6 +114,7 @@
|
|
|
113
114
|
device_read_schedule_value: { value: "1", required: true },
|
|
114
115
|
device_read_schedule_options: { value: "Minutes", required: true },
|
|
115
116
|
deviceRangeRegisters: { value: [] },
|
|
117
|
+
cacheFileEnabled: {value: false, required: true},
|
|
116
118
|
},
|
|
117
119
|
networkInterfaces: [],
|
|
118
120
|
inputs: 1,
|
|
@@ -634,7 +636,7 @@
|
|
|
634
636
|
<input type="text" id="node-input-apduTimeout" placeholder="10000" />
|
|
635
637
|
</div>
|
|
636
638
|
|
|
637
|
-
<div class="form-row">
|
|
639
|
+
<div class="form-row" style="display: none;">
|
|
638
640
|
<label for="node-input-apduSize"
|
|
639
641
|
><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduSize"></span>Max Apdu Size</label
|
|
640
642
|
>
|
|
@@ -648,7 +650,7 @@
|
|
|
648
650
|
</select>
|
|
649
651
|
</div>
|
|
650
652
|
|
|
651
|
-
<div class="form-row">
|
|
653
|
+
<div class="form-row" style="display: none;">
|
|
652
654
|
<label for="node-input-maxSegments"
|
|
653
655
|
><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.maxSegments"></span>Max Segments</label
|
|
654
656
|
>
|
|
@@ -734,6 +736,11 @@
|
|
|
734
736
|
</select>
|
|
735
737
|
</div>
|
|
736
738
|
|
|
739
|
+
<div class="form-row">
|
|
740
|
+
<label for="node-input-cacheFileEnabled"> Cache file enabled: </label>
|
|
741
|
+
<input type="checkbox" id="node-input-cacheFileEnabled" style="width: auto;" />
|
|
742
|
+
</div>
|
|
743
|
+
|
|
737
744
|
<div class="form-row">
|
|
738
745
|
<label for="node-input-toLog"> Log found device: </label>
|
|
739
746
|
<input type="checkbox" id="node-input-toLogIam" style="width: auto;" />
|
package/bacnet_gateway.js
CHANGED
|
@@ -34,6 +34,7 @@ module.exports = function (RED) {
|
|
|
34
34
|
this.retries = config.retries;
|
|
35
35
|
this.bacnetServer = nodeContext.get("bacnetServer") || null;
|
|
36
36
|
this.deviceRangeRegisters = config.deviceRangeRegisters;
|
|
37
|
+
this.cacheFileEnabled = config.cacheFileEnabled;
|
|
37
38
|
|
|
38
39
|
//client and config store
|
|
39
40
|
this.bacnetConfig = nodeContext.get("bacnetConfig");
|
|
@@ -60,7 +61,8 @@ module.exports = function (RED) {
|
|
|
60
61
|
node.manual_instance_range_start,
|
|
61
62
|
node.manual_instance_range_end,
|
|
62
63
|
node.device_read_schedule,
|
|
63
|
-
node.retries
|
|
64
|
+
node.retries,
|
|
65
|
+
node.cacheFileEnabled
|
|
64
66
|
);
|
|
65
67
|
|
|
66
68
|
nodeContext.set("bacnetConfig", node.bacnetConfig);
|
|
@@ -95,25 +97,25 @@ module.exports = function (RED) {
|
|
|
95
97
|
node.bacnetClient.removeAllListeners();
|
|
96
98
|
|
|
97
99
|
// Value response event handler for READ commands
|
|
98
|
-
node.bacnetClient.on("values", (values, outputType, objectPropertyType) => {
|
|
100
|
+
node.bacnetClient.on("values", (values, outputType, objectPropertyType, readNodeName) => {
|
|
99
101
|
if (typeof values !== "undefined" && Object.keys(values).length) {
|
|
100
102
|
if (outputType.json && !outputType.mqtt) {
|
|
101
103
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
102
|
-
sendSimpleJson(values);
|
|
103
|
-
sendJsonAsMqtt(values);
|
|
104
|
+
sendSimpleJson(values, readNodeName);
|
|
105
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
104
106
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
105
|
-
sendJsonAsMqtt(values);
|
|
107
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
106
108
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
107
|
-
sendSimpleJson(values);
|
|
109
|
+
sendSimpleJson(values, readNodeName);
|
|
108
110
|
}
|
|
109
111
|
} else if (!outputType.json && outputType.mqtt) {
|
|
110
112
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
111
|
-
sendAsMqtt(values);
|
|
112
|
-
sendSimpleMqtt(values);
|
|
113
|
+
sendAsMqtt(values, readNodeName);
|
|
114
|
+
sendSimpleMqtt(values, readNodeName);
|
|
113
115
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
114
|
-
sendAsMqtt(values);
|
|
116
|
+
sendAsMqtt(values, readNodeName);
|
|
115
117
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
116
|
-
sendSimpleMqtt(values);
|
|
118
|
+
sendSimpleMqtt(values, readNodeName);
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
}
|
|
@@ -156,14 +158,12 @@ module.exports = function (RED) {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
if (msg.type == "Read") {
|
|
159
|
-
node.bacnetClient.doRead(msg.options, msg.outputType, msg.objectPropertyType, msg.
|
|
161
|
+
node.bacnetClient.doRead(msg.options, msg.outputType, msg.objectPropertyType, msg.readNodeName);
|
|
160
162
|
} else if (msg.type == "Write") {
|
|
161
|
-
node.bacnetClient.doWrite(msg.value, msg.options)
|
|
163
|
+
node.bacnetClient.doWrite(msg.value, msg.options);
|
|
162
164
|
} else if (msg.doDiscover == true) {
|
|
163
165
|
node.status({ fill: "blue", shape: "dot", text: "Sending global Who is" });
|
|
164
|
-
|
|
165
166
|
node.bacnetClient.globalWhoIs();
|
|
166
|
-
|
|
167
167
|
setTimeout(() => {
|
|
168
168
|
node.status({});
|
|
169
169
|
}, 2000);
|
|
@@ -177,6 +177,8 @@ module.exports = function (RED) {
|
|
|
177
177
|
.catch(function (error) {
|
|
178
178
|
logOut("Error updating priorityQueue: ", error);
|
|
179
179
|
});
|
|
180
|
+
} else if (msg.testFunc == true) {
|
|
181
|
+
node.bacnetClient.testFunction();
|
|
180
182
|
}
|
|
181
183
|
});
|
|
182
184
|
|
|
@@ -310,24 +312,24 @@ module.exports = function (RED) {
|
|
|
310
312
|
|
|
311
313
|
function bindEventListeners() {
|
|
312
314
|
// Value response event handler for READ commands
|
|
313
|
-
node.bacnetClient.on("values", (device, values, outputType,
|
|
315
|
+
node.bacnetClient.on("values", (device, values, outputType, readNodeName, fullResult) => {
|
|
314
316
|
if (outputType.json && !outputType.mqtt) {
|
|
315
317
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
316
|
-
sendSimpleJson(values);
|
|
317
|
-
sendJsonAsMqtt(values);
|
|
318
|
+
sendSimpleJson(values, readNodeName);
|
|
319
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
318
320
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
319
|
-
sendJsonAsMqtt(values);
|
|
321
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
320
322
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
321
|
-
sendSimpleJson(values);
|
|
323
|
+
sendSimpleJson(values, readNodeName);
|
|
322
324
|
}
|
|
323
325
|
} else if (!outputType.json && outputType.mqtt) {
|
|
324
326
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
325
|
-
sendAsMqtt(values);
|
|
326
|
-
sendSimpleMqtt(values);
|
|
327
|
+
sendAsMqtt(values, readNodeName);
|
|
328
|
+
sendSimpleMqtt(values, readNodeName);
|
|
327
329
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
328
|
-
sendAsMqtt(values);
|
|
330
|
+
sendAsMqtt(values, readNodeName);
|
|
329
331
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
330
|
-
sendSimpleMqtt(values);
|
|
332
|
+
sendSimpleMqtt(values, readNodeName);
|
|
331
333
|
}
|
|
332
334
|
}
|
|
333
335
|
});
|
|
@@ -350,7 +352,7 @@ module.exports = function (RED) {
|
|
|
350
352
|
}
|
|
351
353
|
}
|
|
352
354
|
|
|
353
|
-
sendSimpleMqtt = function (values) {
|
|
355
|
+
sendSimpleMqtt = function (values, readNodeName) {
|
|
354
356
|
let devices = Object.keys(values);
|
|
355
357
|
devices.forEach(function (device) {
|
|
356
358
|
if (device !== "_msgid") {
|
|
@@ -368,9 +370,23 @@ module.exports = function (RED) {
|
|
|
368
370
|
node.nodeName !== "undefined" &&
|
|
369
371
|
typeof node.nodeName == "string"
|
|
370
372
|
) {
|
|
371
|
-
|
|
373
|
+
if(readNodeName !== ''&&
|
|
374
|
+
readNodeName !== null &&
|
|
375
|
+
readNodeName !== undefined
|
|
376
|
+
) {
|
|
377
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${point}`;
|
|
378
|
+
} else {
|
|
379
|
+
msg.topic = `${node.nodeName}/${device}/${point}`;
|
|
380
|
+
}
|
|
372
381
|
} else {
|
|
373
|
-
|
|
382
|
+
if(readNodeName !== ''&&
|
|
383
|
+
readNodeName !== null &&
|
|
384
|
+
readNodeName !== undefined
|
|
385
|
+
) {
|
|
386
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${point}`;
|
|
387
|
+
} else {
|
|
388
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}`;
|
|
389
|
+
}
|
|
374
390
|
}
|
|
375
391
|
msg.payload = points[point][prop];
|
|
376
392
|
node.send(msg);
|
|
@@ -383,7 +399,7 @@ module.exports = function (RED) {
|
|
|
383
399
|
};
|
|
384
400
|
|
|
385
401
|
// Breaks down response JSON object into mqtt topic / payload
|
|
386
|
-
sendAsMqtt = function (values) {
|
|
402
|
+
sendAsMqtt = function (values, readNodeName) {
|
|
387
403
|
let devices = Object.keys(values);
|
|
388
404
|
devices.forEach(function (device) {
|
|
389
405
|
if (device !== "_msgid") {
|
|
@@ -401,9 +417,23 @@ module.exports = function (RED) {
|
|
|
401
417
|
node.nodeName !== "undefined" &&
|
|
402
418
|
typeof node.nodeName == "string"
|
|
403
419
|
) {
|
|
404
|
-
|
|
420
|
+
if(readNodeName !== ''&&
|
|
421
|
+
readNodeName !== null &&
|
|
422
|
+
readNodeName !== undefined
|
|
423
|
+
) {
|
|
424
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${point}/${prop}`;
|
|
425
|
+
} else {
|
|
426
|
+
msg.topic = `${node.nodeName}/${device}/${point}/${prop}`;
|
|
427
|
+
}
|
|
405
428
|
} else {
|
|
406
|
-
|
|
429
|
+
if(readNodeName !== ''&&
|
|
430
|
+
readNodeName !== null &&
|
|
431
|
+
readNodeName !== undefined
|
|
432
|
+
) {
|
|
433
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${point}/${prop}`;
|
|
434
|
+
} else {
|
|
435
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}/${prop}`;
|
|
436
|
+
}
|
|
407
437
|
}
|
|
408
438
|
msg.payload = points[point][prop];
|
|
409
439
|
node.send(msg);
|
|
@@ -415,7 +445,7 @@ module.exports = function (RED) {
|
|
|
415
445
|
});
|
|
416
446
|
};
|
|
417
447
|
|
|
418
|
-
sendSimpleJson = function (values) {
|
|
448
|
+
sendSimpleJson = function (values, readNodeName) {
|
|
419
449
|
let devices = Object.keys(values);
|
|
420
450
|
devices.forEach(function (device) {
|
|
421
451
|
let msgg = {};
|
|
@@ -424,7 +454,6 @@ module.exports = function (RED) {
|
|
|
424
454
|
[device]: {},
|
|
425
455
|
};
|
|
426
456
|
let points = values[device];
|
|
427
|
-
|
|
428
457
|
for (var point in points) {
|
|
429
458
|
if (points[point]) {
|
|
430
459
|
let pointProps = Object.keys(points[point]);
|
|
@@ -444,9 +473,23 @@ module.exports = function (RED) {
|
|
|
444
473
|
node.nodeName !== "undefined" &&
|
|
445
474
|
typeof node.nodeName == "string"
|
|
446
475
|
) {
|
|
447
|
-
|
|
476
|
+
if(readNodeName !== ''&&
|
|
477
|
+
readNodeName !== null &&
|
|
478
|
+
readNodeName !== undefined
|
|
479
|
+
) {
|
|
480
|
+
msgg.topic = `${node.nodeName}/${readNodeName}/${device}`;
|
|
481
|
+
} else {
|
|
482
|
+
msgg.topic = `${node.nodeName}/${device}`;
|
|
483
|
+
}
|
|
448
484
|
} else {
|
|
449
|
-
|
|
485
|
+
if(readNodeName !== ''&&
|
|
486
|
+
readNodeName !== null &&
|
|
487
|
+
readNodeName !== undefined
|
|
488
|
+
) {
|
|
489
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}`;
|
|
490
|
+
} else {
|
|
491
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${device}`;
|
|
492
|
+
}
|
|
450
493
|
}
|
|
451
494
|
msgg.payload = value[device];
|
|
452
495
|
node.send(msgg);
|
|
@@ -454,13 +497,12 @@ module.exports = function (RED) {
|
|
|
454
497
|
});
|
|
455
498
|
};
|
|
456
499
|
|
|
457
|
-
sendJsonAsMqtt = function (values) {
|
|
500
|
+
sendJsonAsMqtt = function (values, readNodeName) {
|
|
458
501
|
if (typeof values == "object") {
|
|
459
502
|
let keys = Object.keys(values);
|
|
460
503
|
keys.forEach(function (key) {
|
|
461
504
|
let points = values[key];
|
|
462
505
|
let msgg = {};
|
|
463
|
-
|
|
464
506
|
if (
|
|
465
507
|
node.nodeName !== "gateway" &&
|
|
466
508
|
node.nodeName !== "" &&
|
|
@@ -468,9 +510,23 @@ module.exports = function (RED) {
|
|
|
468
510
|
node.nodeName !== "undefined" &&
|
|
469
511
|
typeof node.nodeName == "string"
|
|
470
512
|
) {
|
|
471
|
-
|
|
513
|
+
if(readNodeName !== ''&&
|
|
514
|
+
readNodeName !== null &&
|
|
515
|
+
readNodeName !== undefined
|
|
516
|
+
) {
|
|
517
|
+
msgg.topic = `${node.nodeName}/${readNodeName}/${key}`;
|
|
518
|
+
} else {
|
|
519
|
+
msgg.topic = `${node.nodeName}/${key}`;
|
|
520
|
+
}
|
|
472
521
|
} else {
|
|
473
|
-
|
|
522
|
+
if(readNodeName !== ''&&
|
|
523
|
+
readNodeName !== null &&
|
|
524
|
+
readNodeName !== undefined
|
|
525
|
+
) {
|
|
526
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${key}`;
|
|
527
|
+
} else {
|
|
528
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${key}`;
|
|
529
|
+
}
|
|
474
530
|
}
|
|
475
531
|
msgg.payload = points;
|
|
476
532
|
node.send(msgg);
|
package/bacnet_read.html
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
app.pollFrequency = parseInt(result.pollFrequency);
|
|
107
107
|
app.deviceCount = result.deviceList.length;
|
|
108
108
|
//progress bar percentage
|
|
109
|
-
let progressVal = parseInt((result.
|
|
109
|
+
let progressVal = parseInt((result.renderListCount / result.deviceList.length) * 100);
|
|
110
110
|
if(typeof progressVal == "number" && !isNaN(progressVal)) {
|
|
111
111
|
app.progressBarValue = progressVal;
|
|
112
112
|
} else {
|
|
@@ -241,11 +241,26 @@
|
|
|
241
241
|
//update UI
|
|
242
242
|
let parentDeviceName = slotProps.node.parentDevice;
|
|
243
243
|
let foundDeviceIndex = this.readDevices ? this.readDevices.findIndex(ele => ele.label == parentDeviceName) : -1;
|
|
244
|
-
let
|
|
244
|
+
let device = this.deviceList.find(ele => ele.deviceName == parentDeviceName);
|
|
245
|
+
let deviceAddress = app.getDeviceAddress(device.address);
|
|
246
|
+
let key = `${deviceAddress}-${device.deviceId}`;
|
|
247
|
+
let parentDevice = this.devices.find(ele => ele.ipAddr == deviceAddress);
|
|
248
|
+
let childDevice;
|
|
249
|
+
if(device.isMstp){
|
|
250
|
+
let foundChildIndex = parentDevice.children[1].children.findIndex(ele => ele.label == parentDeviceName);
|
|
251
|
+
if(foundChildIndex !== -1) {
|
|
252
|
+
childDevice = parentDevice.children[1].children[foundChildIndex];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
245
255
|
|
|
246
256
|
if (foundDeviceIndex == -1) {
|
|
247
257
|
//no read devices present, add new
|
|
248
|
-
let newReadParent
|
|
258
|
+
let newReadParent;
|
|
259
|
+
if(childDevice) {
|
|
260
|
+
newReadParent = {...childDevice};
|
|
261
|
+
} else{
|
|
262
|
+
newReadParent = {...parentDevice};
|
|
263
|
+
}
|
|
249
264
|
newReadParent.children = [];
|
|
250
265
|
newReadParent.children.push(slotProps.node);
|
|
251
266
|
|
|
@@ -260,22 +275,10 @@
|
|
|
260
275
|
}
|
|
261
276
|
|
|
262
277
|
//set show added to true
|
|
263
|
-
|
|
264
|
-
slot.showAdded = true;
|
|
265
|
-
|
|
278
|
+
slotProps.node.showAdded = true;
|
|
266
279
|
this.$forceUpdate();
|
|
267
280
|
|
|
268
281
|
//update node-red data structure
|
|
269
|
-
let device = this.deviceList.find(ele => {
|
|
270
|
-
if(ele.address.address) {
|
|
271
|
-
return ele.address.address == parentDevice.ipAddr && ele.deviceId == parentDevice.deviceId;
|
|
272
|
-
} else {
|
|
273
|
-
return ele.address == parentDevice.ipAddr && ele.deviceId == parentDevice.deviceId;
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
let deviceAddress = app.getDeviceAddress(device.address);
|
|
277
|
-
let key = `${deviceAddress}-${device.deviceId}`;
|
|
278
|
-
|
|
279
282
|
if (!this.pointsToRead[key]) {
|
|
280
283
|
this.pointsToRead[key] = {};
|
|
281
284
|
}
|
|
@@ -294,6 +297,9 @@
|
|
|
294
297
|
let parentDeviceName = slotProps.node.parentDevice;
|
|
295
298
|
let foundDeviceIndex = this.readDevices ? this.readDevices.findIndex(ele => ele.label == parentDeviceName) : -1;
|
|
296
299
|
let parentDevice = this.devices.find(ele => ele.label == parentDeviceName);
|
|
300
|
+
let device = this.deviceList.find(ele => ele.deviceName == parentDeviceName);
|
|
301
|
+
let deviceAddress = app.getDeviceAddress(device.address);
|
|
302
|
+
let key = `${deviceAddress}-${device.deviceId}`;
|
|
297
303
|
|
|
298
304
|
if (foundDeviceIndex !== -1) {
|
|
299
305
|
let foundIndex = this.readDevices[foundDeviceIndex].children.findIndex(ele => ele.key == slotProps.node.key && ele.pointName == slotProps.node.pointName);
|
|
@@ -304,21 +310,10 @@
|
|
|
304
310
|
}
|
|
305
311
|
|
|
306
312
|
//set show added to true
|
|
307
|
-
let slot = parentDevice.showAdded ? slotProps.node : parentDevice.children.find(ele => ele.pointName == slotProps.node.pointName);
|
|
308
|
-
slot.showAdded = false;
|
|
309
313
|
slotProps.node.showAdded = false;
|
|
310
314
|
this.$forceUpdate();
|
|
311
315
|
|
|
312
316
|
//update node-red data stucture
|
|
313
|
-
let device = this.deviceList.find(ele => {
|
|
314
|
-
if(ele.address.address) {
|
|
315
|
-
return ele.address.address == parentDevice.ipAddr && ele.deviceId == parentDevice.deviceId;
|
|
316
|
-
} else {
|
|
317
|
-
return ele.address == parentDevice.ipAddr && ele.deviceId == parentDevice.deviceId;
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
let deviceAddress = app.getDeviceAddress(device.address);
|
|
321
|
-
let key = `${deviceAddress}-${device.deviceId}`;
|
|
322
317
|
let point = this.pointList[key][slotProps.node.pointName];
|
|
323
318
|
if (this.pointsToRead[key][point.objectName]) delete this.pointsToRead[key][point.objectName];
|
|
324
319
|
//if last point is removed, deleted whole entry
|
|
@@ -508,9 +503,6 @@
|
|
|
508
503
|
.pointLabel {
|
|
509
504
|
font-weight: 400;
|
|
510
505
|
}
|
|
511
|
-
/* .p-treenode-children {
|
|
512
|
-
background-color: #f0f0f0;
|
|
513
|
-
} */
|
|
514
506
|
.deviceLabel {
|
|
515
507
|
font-weight: 100;
|
|
516
508
|
}
|
|
@@ -536,15 +528,17 @@
|
|
|
536
528
|
}
|
|
537
529
|
.p-treenode-children > li > .p-treenode-children > li {
|
|
538
530
|
font-size: 14px;
|
|
539
|
-
height:
|
|
531
|
+
/* height: 35px; */
|
|
540
532
|
color: #b5b5b5 !important;
|
|
541
533
|
}
|
|
542
534
|
.p-treenode-children > li > .p-treenode-children > .p-treenode-label {
|
|
543
535
|
color: #b5b5b5 !important;
|
|
544
536
|
}
|
|
537
|
+
/*
|
|
545
538
|
.p-treenode-children > li > .p-treenode-children > li:last-child {
|
|
546
|
-
padding-bottom: 30px;
|
|
539
|
+
padding-bottom: 30px;
|
|
547
540
|
}
|
|
541
|
+
*/
|
|
548
542
|
.p-tree-toggler:enabled:hover {
|
|
549
543
|
background: #d5d5d5 !important;
|
|
550
544
|
}
|
|
@@ -561,6 +555,7 @@
|
|
|
561
555
|
.statusOffline {
|
|
562
556
|
color: red;
|
|
563
557
|
}
|
|
558
|
+
|
|
564
559
|
.deviceLabel {
|
|
565
560
|
position: absolute;
|
|
566
561
|
}
|
|
@@ -669,6 +664,22 @@
|
|
|
669
664
|
padding-right: 20px;
|
|
670
665
|
}
|
|
671
666
|
|
|
667
|
+
.p-tree .p-treenode-children {
|
|
668
|
+
padding: 0 !important;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.p-tree-toggler .p-link {
|
|
672
|
+
width: 25px !important;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
/*
|
|
677
|
+
.p-treenode-content {
|
|
678
|
+
height: 15px;
|
|
679
|
+
}
|
|
680
|
+
*/
|
|
681
|
+
|
|
682
|
+
|
|
672
683
|
</style>
|
|
673
684
|
|
|
674
685
|
<div class="form-row">
|
|
@@ -711,7 +722,7 @@
|
|
|
711
722
|
|
|
712
723
|
|
|
713
724
|
<div id="deviceListApp">
|
|
714
|
-
<p-tree :value="devices" selectable="false" :filter="true" filterMode="lenient" filterPlaceholder="No results found." v-if="hasData()">
|
|
725
|
+
<p-tree :value="devices" selectable="false" :filter="true" filterMode="lenient" filterPlaceholder="No results found." v-if="hasData()">
|
|
715
726
|
<template #device="slotProps">
|
|
716
727
|
<div v-if="isDeviceActive(slotProps)" class="deviceLabelParent">
|
|
717
728
|
<b class="deviceLabel">{{slotProps.node.label}} <b class="statusOnline deviceStatus">Online</b></b>
|
|
@@ -736,6 +747,15 @@
|
|
|
736
747
|
</button>
|
|
737
748
|
</template>
|
|
738
749
|
|
|
750
|
+
<!-- <template #pointFolder="slotProps">
|
|
751
|
+
|
|
752
|
+
</template>
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
<template #deviceFolder="slotProps">
|
|
756
|
+
|
|
757
|
+
</template> -->
|
|
758
|
+
|
|
739
759
|
<template #point="slotProps" v-model:class="pointContent">
|
|
740
760
|
<b class="pointLabel">{{slotProps.node.label}}</b>
|
|
741
761
|
|
package/bacnet_read.js
CHANGED
|
@@ -19,6 +19,7 @@ module.exports = function (RED) {
|
|
|
19
19
|
this.pointsToRead = config.pointsToRead;
|
|
20
20
|
this.readDevices = config.readDevices;
|
|
21
21
|
this.id = config.id;
|
|
22
|
+
this.nodeName = config.name;
|
|
22
23
|
|
|
23
24
|
this.object_property_simplePayload = config.object_property_simplePayload;
|
|
24
25
|
this.object_property_fullObject = config.object_property_fullObject;
|
|
@@ -67,12 +68,13 @@ module.exports = function (RED) {
|
|
|
67
68
|
node.send(priorityDevicesMsg);
|
|
68
69
|
|
|
69
70
|
node.on('input', function(msg) {
|
|
71
|
+
node.status({ fill: "blue", shape: "dot", text: "Reading values" });
|
|
70
72
|
|
|
71
73
|
let readConfig = new ReadCommandConfig(node.pointsToRead, node.object_props, node.roundDecimal);
|
|
72
|
-
|
|
73
74
|
let output = {
|
|
74
75
|
type: "Read",
|
|
75
76
|
id: node.id,
|
|
77
|
+
readNodeName: node.nodeName,
|
|
76
78
|
options: readConfig,
|
|
77
79
|
objectPropertyType: {
|
|
78
80
|
simplePayload: node.object_property_simplePayload,
|
|
@@ -83,9 +85,13 @@ module.exports = function (RED) {
|
|
|
83
85
|
mqtt: node.mqtt
|
|
84
86
|
}
|
|
85
87
|
};
|
|
86
|
-
|
|
88
|
+
|
|
87
89
|
node.send(output);
|
|
88
90
|
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
node.status({});
|
|
93
|
+
}, 3000);
|
|
94
|
+
|
|
89
95
|
});
|
|
90
96
|
|
|
91
97
|
};
|