@bitpoolos/edge-bacnet 1.2.6 → 1.2.8
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 +1852 -1373
- package/bacnet_device.js +52 -0
- package/bacnet_gateway.html +38 -3
- package/bacnet_gateway.js +95 -37
- package/bacnet_read.html +53 -33
- package/bacnet_read.js +8 -2
- package/bacnet_write.html +733 -668
- package/bacnet_write.js +1 -1
- package/common.js +17 -7
- package/package.json +1 -1
- 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,10 @@
|
|
|
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},
|
|
118
|
+
sanitise_device_schedule: { value: "60" },
|
|
119
|
+
sanitise_device_schedule_value: { value: "1", required: true },
|
|
120
|
+
sanitise_device_schedule_options: { value: "Hours", required: true },
|
|
116
121
|
},
|
|
117
122
|
networkInterfaces: [],
|
|
118
123
|
inputs: 1,
|
|
@@ -453,6 +458,11 @@
|
|
|
453
458
|
document.getElementById("node-input-device_read_schedule_options").value
|
|
454
459
|
);
|
|
455
460
|
|
|
461
|
+
document.getElementById("node-input-sanitise_device_schedule").value = getTimePeriodInSeconds(
|
|
462
|
+
document.getElementById("node-input-sanitise_device_schedule_value").value,
|
|
463
|
+
document.getElementById("node-input-sanitise_device_schedule_options").value
|
|
464
|
+
);
|
|
465
|
+
|
|
456
466
|
node.deviceRangeRegisters = [];
|
|
457
467
|
let deviceRanges = $("#node-input-deviceIdRangeMatrix-container").editableList("items");
|
|
458
468
|
deviceRanges.each(function (i) {
|
|
@@ -634,7 +644,7 @@
|
|
|
634
644
|
<input type="text" id="node-input-apduTimeout" placeholder="10000" />
|
|
635
645
|
</div>
|
|
636
646
|
|
|
637
|
-
<div class="form-row">
|
|
647
|
+
<div class="form-row" style="display: none;">
|
|
638
648
|
<label for="node-input-apduSize"
|
|
639
649
|
><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduSize"></span>Max Apdu Size</label
|
|
640
650
|
>
|
|
@@ -648,7 +658,7 @@
|
|
|
648
658
|
</select>
|
|
649
659
|
</div>
|
|
650
660
|
|
|
651
|
-
<div class="form-row">
|
|
661
|
+
<div class="form-row" style="display: none;">
|
|
652
662
|
<label for="node-input-maxSegments"
|
|
653
663
|
><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.maxSegments"></span>Max Segments</label
|
|
654
664
|
>
|
|
@@ -734,6 +744,31 @@
|
|
|
734
744
|
</select>
|
|
735
745
|
</div>
|
|
736
746
|
|
|
747
|
+
<div class="form-row" style="align-items: center; display: flex;">
|
|
748
|
+
<label for="node-input-sanitise_device_schedule_value"
|
|
749
|
+
><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.sanitise_device_schedule"></span>Device Sanitisation
|
|
750
|
+
Frequency</label
|
|
751
|
+
>
|
|
752
|
+
<p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
|
|
753
|
+
<input type="text" id="node-input-sanitise_device_schedule" style="display: none;" />
|
|
754
|
+
<input
|
|
755
|
+
type="text"
|
|
756
|
+
id="node-input-sanitise_device_schedule_value"
|
|
757
|
+
placeholder="5"
|
|
758
|
+
style="width: 70px; margin-right: 5px;" />
|
|
759
|
+
<select name="timePeriod" id="node-input-sanitise_device_schedule_options" style="width: 120px; margin-right: 5px;">
|
|
760
|
+
<option value="Seconds">Seconds</option>
|
|
761
|
+
<option value="Minutes">Minutes</option>
|
|
762
|
+
<option value="Hours">Hours</option>
|
|
763
|
+
<option value="Days">Days</option>
|
|
764
|
+
</select>
|
|
765
|
+
</div>
|
|
766
|
+
|
|
767
|
+
<div class="form-row">
|
|
768
|
+
<label for="node-input-cacheFileEnabled"> Cache file enabled: </label>
|
|
769
|
+
<input type="checkbox" id="node-input-cacheFileEnabled" style="width: auto;" />
|
|
770
|
+
</div>
|
|
771
|
+
|
|
737
772
|
<div class="form-row">
|
|
738
773
|
<label for="node-input-toLog"> Log found device: </label>
|
|
739
774
|
<input type="checkbox" id="node-input-toLogIam" style="width: auto;" />
|
package/bacnet_gateway.js
CHANGED
|
@@ -34,6 +34,8 @@ 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;
|
|
38
|
+
this.sanitise_device_schedule = config.sanitise_device_schedule;
|
|
37
39
|
|
|
38
40
|
//client and config store
|
|
39
41
|
this.bacnetConfig = nodeContext.get("bacnetConfig");
|
|
@@ -60,7 +62,9 @@ module.exports = function (RED) {
|
|
|
60
62
|
node.manual_instance_range_start,
|
|
61
63
|
node.manual_instance_range_end,
|
|
62
64
|
node.device_read_schedule,
|
|
63
|
-
node.retries
|
|
65
|
+
node.retries,
|
|
66
|
+
node.cacheFileEnabled,
|
|
67
|
+
node.sanitise_device_schedule
|
|
64
68
|
);
|
|
65
69
|
|
|
66
70
|
nodeContext.set("bacnetConfig", node.bacnetConfig);
|
|
@@ -95,25 +99,25 @@ module.exports = function (RED) {
|
|
|
95
99
|
node.bacnetClient.removeAllListeners();
|
|
96
100
|
|
|
97
101
|
// Value response event handler for READ commands
|
|
98
|
-
node.bacnetClient.on("values", (values, outputType, objectPropertyType) => {
|
|
102
|
+
node.bacnetClient.on("values", (values, outputType, objectPropertyType, readNodeName) => {
|
|
99
103
|
if (typeof values !== "undefined" && Object.keys(values).length) {
|
|
100
104
|
if (outputType.json && !outputType.mqtt) {
|
|
101
105
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
102
|
-
sendSimpleJson(values);
|
|
103
|
-
sendJsonAsMqtt(values);
|
|
106
|
+
sendSimpleJson(values, readNodeName);
|
|
107
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
104
108
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
105
|
-
sendJsonAsMqtt(values);
|
|
109
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
106
110
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
107
|
-
sendSimpleJson(values);
|
|
111
|
+
sendSimpleJson(values, readNodeName);
|
|
108
112
|
}
|
|
109
113
|
} else if (!outputType.json && outputType.mqtt) {
|
|
110
114
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
111
|
-
sendAsMqtt(values);
|
|
112
|
-
sendSimpleMqtt(values);
|
|
115
|
+
sendAsMqtt(values, readNodeName);
|
|
116
|
+
sendSimpleMqtt(values, readNodeName);
|
|
113
117
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
114
|
-
sendAsMqtt(values);
|
|
118
|
+
sendAsMqtt(values, readNodeName);
|
|
115
119
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
116
|
-
sendSimpleMqtt(values);
|
|
120
|
+
sendSimpleMqtt(values, readNodeName);
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
}
|
|
@@ -156,14 +160,12 @@ module.exports = function (RED) {
|
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
if (msg.type == "Read") {
|
|
159
|
-
node.bacnetClient.doRead(msg.options, msg.outputType, msg.objectPropertyType, msg.
|
|
163
|
+
node.bacnetClient.doRead(msg.options, msg.outputType, msg.objectPropertyType, msg.readNodeName);
|
|
160
164
|
} else if (msg.type == "Write") {
|
|
161
|
-
node.bacnetClient.doWrite(msg.value, msg.options)
|
|
165
|
+
node.bacnetClient.doWrite(msg.value, msg.options);
|
|
162
166
|
} else if (msg.doDiscover == true) {
|
|
163
167
|
node.status({ fill: "blue", shape: "dot", text: "Sending global Who is" });
|
|
164
|
-
|
|
165
168
|
node.bacnetClient.globalWhoIs();
|
|
166
|
-
|
|
167
169
|
setTimeout(() => {
|
|
168
170
|
node.status({});
|
|
169
171
|
}, 2000);
|
|
@@ -177,6 +179,8 @@ module.exports = function (RED) {
|
|
|
177
179
|
.catch(function (error) {
|
|
178
180
|
logOut("Error updating priorityQueue: ", error);
|
|
179
181
|
});
|
|
182
|
+
} else if (msg.testFunc == true) {
|
|
183
|
+
node.bacnetClient.testFunction(msg.address, msg.type, msg.instance, msg.property);
|
|
180
184
|
}
|
|
181
185
|
});
|
|
182
186
|
|
|
@@ -310,24 +314,24 @@ module.exports = function (RED) {
|
|
|
310
314
|
|
|
311
315
|
function bindEventListeners() {
|
|
312
316
|
// Value response event handler for READ commands
|
|
313
|
-
node.bacnetClient.on("values", (device, values, outputType,
|
|
317
|
+
node.bacnetClient.on("values", (device, values, outputType, readNodeName, fullResult) => {
|
|
314
318
|
if (outputType.json && !outputType.mqtt) {
|
|
315
319
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
316
|
-
sendSimpleJson(values);
|
|
317
|
-
sendJsonAsMqtt(values);
|
|
320
|
+
sendSimpleJson(values, readNodeName);
|
|
321
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
318
322
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
319
|
-
sendJsonAsMqtt(values);
|
|
323
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
320
324
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
321
|
-
sendSimpleJson(values);
|
|
325
|
+
sendSimpleJson(values, readNodeName);
|
|
322
326
|
}
|
|
323
327
|
} else if (!outputType.json && outputType.mqtt) {
|
|
324
328
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
325
|
-
sendAsMqtt(values);
|
|
326
|
-
sendSimpleMqtt(values);
|
|
329
|
+
sendAsMqtt(values, readNodeName);
|
|
330
|
+
sendSimpleMqtt(values, readNodeName);
|
|
327
331
|
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
328
|
-
sendAsMqtt(values);
|
|
332
|
+
sendAsMqtt(values, readNodeName);
|
|
329
333
|
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
330
|
-
sendSimpleMqtt(values);
|
|
334
|
+
sendSimpleMqtt(values, readNodeName);
|
|
331
335
|
}
|
|
332
336
|
}
|
|
333
337
|
});
|
|
@@ -350,7 +354,7 @@ module.exports = function (RED) {
|
|
|
350
354
|
}
|
|
351
355
|
}
|
|
352
356
|
|
|
353
|
-
sendSimpleMqtt = function (values) {
|
|
357
|
+
sendSimpleMqtt = function (values, readNodeName) {
|
|
354
358
|
let devices = Object.keys(values);
|
|
355
359
|
devices.forEach(function (device) {
|
|
356
360
|
if (device !== "_msgid") {
|
|
@@ -368,9 +372,23 @@ module.exports = function (RED) {
|
|
|
368
372
|
node.nodeName !== "undefined" &&
|
|
369
373
|
typeof node.nodeName == "string"
|
|
370
374
|
) {
|
|
371
|
-
|
|
375
|
+
if(readNodeName !== ''&&
|
|
376
|
+
readNodeName !== null &&
|
|
377
|
+
readNodeName !== undefined
|
|
378
|
+
) {
|
|
379
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${point}`;
|
|
380
|
+
} else {
|
|
381
|
+
msg.topic = `${node.nodeName}/${device}/${point}`;
|
|
382
|
+
}
|
|
372
383
|
} else {
|
|
373
|
-
|
|
384
|
+
if(readNodeName !== ''&&
|
|
385
|
+
readNodeName !== null &&
|
|
386
|
+
readNodeName !== undefined
|
|
387
|
+
) {
|
|
388
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${point}`;
|
|
389
|
+
} else {
|
|
390
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}`;
|
|
391
|
+
}
|
|
374
392
|
}
|
|
375
393
|
msg.payload = points[point][prop];
|
|
376
394
|
node.send(msg);
|
|
@@ -383,7 +401,7 @@ module.exports = function (RED) {
|
|
|
383
401
|
};
|
|
384
402
|
|
|
385
403
|
// Breaks down response JSON object into mqtt topic / payload
|
|
386
|
-
sendAsMqtt = function (values) {
|
|
404
|
+
sendAsMqtt = function (values, readNodeName) {
|
|
387
405
|
let devices = Object.keys(values);
|
|
388
406
|
devices.forEach(function (device) {
|
|
389
407
|
if (device !== "_msgid") {
|
|
@@ -401,9 +419,23 @@ module.exports = function (RED) {
|
|
|
401
419
|
node.nodeName !== "undefined" &&
|
|
402
420
|
typeof node.nodeName == "string"
|
|
403
421
|
) {
|
|
404
|
-
|
|
422
|
+
if(readNodeName !== ''&&
|
|
423
|
+
readNodeName !== null &&
|
|
424
|
+
readNodeName !== undefined
|
|
425
|
+
) {
|
|
426
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${point}/${prop}`;
|
|
427
|
+
} else {
|
|
428
|
+
msg.topic = `${node.nodeName}/${device}/${point}/${prop}`;
|
|
429
|
+
}
|
|
405
430
|
} else {
|
|
406
|
-
|
|
431
|
+
if(readNodeName !== ''&&
|
|
432
|
+
readNodeName !== null &&
|
|
433
|
+
readNodeName !== undefined
|
|
434
|
+
) {
|
|
435
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${point}/${prop}`;
|
|
436
|
+
} else {
|
|
437
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}/${prop}`;
|
|
438
|
+
}
|
|
407
439
|
}
|
|
408
440
|
msg.payload = points[point][prop];
|
|
409
441
|
node.send(msg);
|
|
@@ -415,7 +447,7 @@ module.exports = function (RED) {
|
|
|
415
447
|
});
|
|
416
448
|
};
|
|
417
449
|
|
|
418
|
-
sendSimpleJson = function (values) {
|
|
450
|
+
sendSimpleJson = function (values, readNodeName) {
|
|
419
451
|
let devices = Object.keys(values);
|
|
420
452
|
devices.forEach(function (device) {
|
|
421
453
|
let msgg = {};
|
|
@@ -424,7 +456,6 @@ module.exports = function (RED) {
|
|
|
424
456
|
[device]: {},
|
|
425
457
|
};
|
|
426
458
|
let points = values[device];
|
|
427
|
-
|
|
428
459
|
for (var point in points) {
|
|
429
460
|
if (points[point]) {
|
|
430
461
|
let pointProps = Object.keys(points[point]);
|
|
@@ -444,9 +475,23 @@ module.exports = function (RED) {
|
|
|
444
475
|
node.nodeName !== "undefined" &&
|
|
445
476
|
typeof node.nodeName == "string"
|
|
446
477
|
) {
|
|
447
|
-
|
|
478
|
+
if(readNodeName !== ''&&
|
|
479
|
+
readNodeName !== null &&
|
|
480
|
+
readNodeName !== undefined
|
|
481
|
+
) {
|
|
482
|
+
msgg.topic = `${node.nodeName}/${readNodeName}/${device}`;
|
|
483
|
+
} else {
|
|
484
|
+
msgg.topic = `${node.nodeName}/${device}`;
|
|
485
|
+
}
|
|
448
486
|
} else {
|
|
449
|
-
|
|
487
|
+
if(readNodeName !== ''&&
|
|
488
|
+
readNodeName !== null &&
|
|
489
|
+
readNodeName !== undefined
|
|
490
|
+
) {
|
|
491
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}`;
|
|
492
|
+
} else {
|
|
493
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${device}`;
|
|
494
|
+
}
|
|
450
495
|
}
|
|
451
496
|
msgg.payload = value[device];
|
|
452
497
|
node.send(msgg);
|
|
@@ -454,13 +499,12 @@ module.exports = function (RED) {
|
|
|
454
499
|
});
|
|
455
500
|
};
|
|
456
501
|
|
|
457
|
-
sendJsonAsMqtt = function (values) {
|
|
502
|
+
sendJsonAsMqtt = function (values, readNodeName) {
|
|
458
503
|
if (typeof values == "object") {
|
|
459
504
|
let keys = Object.keys(values);
|
|
460
505
|
keys.forEach(function (key) {
|
|
461
506
|
let points = values[key];
|
|
462
507
|
let msgg = {};
|
|
463
|
-
|
|
464
508
|
if (
|
|
465
509
|
node.nodeName !== "gateway" &&
|
|
466
510
|
node.nodeName !== "" &&
|
|
@@ -468,9 +512,23 @@ module.exports = function (RED) {
|
|
|
468
512
|
node.nodeName !== "undefined" &&
|
|
469
513
|
typeof node.nodeName == "string"
|
|
470
514
|
) {
|
|
471
|
-
|
|
515
|
+
if(readNodeName !== ''&&
|
|
516
|
+
readNodeName !== null &&
|
|
517
|
+
readNodeName !== undefined
|
|
518
|
+
) {
|
|
519
|
+
msgg.topic = `${node.nodeName}/${readNodeName}/${key}`;
|
|
520
|
+
} else {
|
|
521
|
+
msgg.topic = `${node.nodeName}/${key}`;
|
|
522
|
+
}
|
|
472
523
|
} else {
|
|
473
|
-
|
|
524
|
+
if(readNodeName !== ''&&
|
|
525
|
+
readNodeName !== null &&
|
|
526
|
+
readNodeName !== undefined
|
|
527
|
+
) {
|
|
528
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${key}`;
|
|
529
|
+
} else {
|
|
530
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${key}`;
|
|
531
|
+
}
|
|
474
532
|
}
|
|
475
533
|
msgg.payload = points;
|
|
476
534
|
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
|
};
|