@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_client.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
|
-
MIT License Copyright 2021,
|
|
2
|
+
MIT License Copyright 2021, 2024 - Bitpool Pty Ltd
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const bacnet = require('./resources/node-bacstack-ts/dist/index.js');
|
|
6
6
|
const baEnum = bacnet.enum;
|
|
7
7
|
const bacnetIdMax = baEnum.ASN1_MAX_PROPERTY_ID;
|
|
8
8
|
const { EventEmitter } = require('events');
|
|
9
|
-
const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync } = require('./common');
|
|
9
|
+
const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync, isNumber } = require('./common');
|
|
10
10
|
const { ToadScheduler, SimpleIntervalJob, Task } = require('toad-scheduler');
|
|
11
11
|
const { BacnetDevice } = require('./bacnet_device');
|
|
12
12
|
const {Mutex} = require("async-mutex");
|
|
@@ -28,22 +28,24 @@ class BacnetClient extends EventEmitter {
|
|
|
28
28
|
that.manualMutex = new Mutex();
|
|
29
29
|
that.pollInProgress = false;
|
|
30
30
|
that.scanMatrix = [];
|
|
31
|
+
that.renderListCount = 0;
|
|
31
32
|
|
|
32
33
|
try {
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if(cachedData
|
|
37
|
-
|
|
38
|
-
cachedData.deviceList
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
if(config.cacheFileEnabled) {
|
|
36
|
+
let cachedData = JSON.parse(Read_Config_Sync());
|
|
37
|
+
if(cachedData && typeof cachedData == "object") {
|
|
38
|
+
if(cachedData.renderList) that.renderList = cachedData.renderList;
|
|
39
|
+
if(cachedData.deviceList) {
|
|
40
|
+
cachedData.deviceList.forEach(function(device) {
|
|
41
|
+
let newBacnetDevice = new BacnetDevice(true, device);
|
|
42
|
+
that.deviceList.push(newBacnetDevice);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if(cachedData.pointList) that.networkTree = cachedData.pointList;
|
|
46
|
+
if(cachedData.renderListCount) that.renderListCount = cachedData.renderListCount;
|
|
42
47
|
}
|
|
43
|
-
if(cachedData.pointList) that.networkTree = cachedData.pointList;
|
|
44
48
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
49
|
|
|
48
50
|
that.config = config;
|
|
49
51
|
that.roundDecimal = config.roundDecimal;
|
|
@@ -59,12 +61,10 @@ class BacnetClient extends EventEmitter {
|
|
|
59
61
|
that.deviceRetryCount = parseInt(config.retries);
|
|
60
62
|
|
|
61
63
|
that.readPropertyMultipleOptions = {
|
|
62
|
-
maxSegments:
|
|
63
|
-
maxApdu:
|
|
64
|
+
maxSegments: 112,
|
|
65
|
+
maxApdu: 5
|
|
64
66
|
};
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
68
|
try {
|
|
69
69
|
|
|
70
70
|
that.client = new bacnet.Client({ apduTimeout: config.apduTimeout, interface: config.localIpAdrress, port: config.port, broadcastAddress: config.broadCastAddr});
|
|
@@ -90,7 +90,9 @@ class BacnetClient extends EventEmitter {
|
|
|
90
90
|
|
|
91
91
|
//buildNetworkTreeData task
|
|
92
92
|
const buildNetworkTree = new Task('simple task', () => {
|
|
93
|
-
that.buildNetworkTreeData()
|
|
93
|
+
that.buildNetworkTreeData().then(function() {
|
|
94
|
+
that.countDevices();
|
|
95
|
+
});
|
|
94
96
|
});
|
|
95
97
|
|
|
96
98
|
const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10, }, buildNetworkTree)
|
|
@@ -102,7 +104,9 @@ class BacnetClient extends EventEmitter {
|
|
|
102
104
|
setTimeout(() => {
|
|
103
105
|
that.queryDevices();
|
|
104
106
|
that.sanitizeDeviceList();
|
|
105
|
-
that.buildNetworkTreeData()
|
|
107
|
+
that.buildNetworkTreeData().then(function() {
|
|
108
|
+
that.countDevices();
|
|
109
|
+
});
|
|
106
110
|
}, "5000")
|
|
107
111
|
|
|
108
112
|
} catch(e) {
|
|
@@ -111,6 +115,7 @@ class BacnetClient extends EventEmitter {
|
|
|
111
115
|
|
|
112
116
|
//who is callback
|
|
113
117
|
that.client.on('iAm', (device) => {
|
|
118
|
+
//console.log("found iAm device: ", device);
|
|
114
119
|
if(device.address !== that.config.localIpAdrress) {
|
|
115
120
|
if(that.scanMatrix.length > 0) {
|
|
116
121
|
let matrixMap = that.scanMatrix.filter(ele => device.deviceId >= ele.start && device.deviceId <= ele.end);
|
|
@@ -121,12 +126,19 @@ class BacnetClient extends EventEmitter {
|
|
|
121
126
|
let newBacnetDevice = new BacnetDevice(false, device);
|
|
122
127
|
newBacnetDevice.setLastSeen(Date.now());
|
|
123
128
|
that.updateDeviceName(newBacnetDevice);
|
|
129
|
+
if(newBacnetDevice.getIsMstpDevice()) {
|
|
130
|
+
that.addToParentMstpNetwork(newBacnetDevice);
|
|
131
|
+
}
|
|
124
132
|
that.deviceList.push(newBacnetDevice);
|
|
125
133
|
|
|
126
134
|
} else if(foundIndex !== -1) {
|
|
127
135
|
that.deviceList[foundIndex].updateDeviceConfig(device);
|
|
128
136
|
that.deviceList[foundIndex].setLastSeen(Date.now());
|
|
129
137
|
that.updateDeviceName(that.deviceList[foundIndex]);
|
|
138
|
+
|
|
139
|
+
if(that.deviceList[foundIndex].getIsMstpDevice()) {
|
|
140
|
+
that.addToParentMstpNetwork(that.deviceList[foundIndex]);
|
|
141
|
+
}
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
//emit event for node-red to log
|
|
@@ -139,11 +151,19 @@ class BacnetClient extends EventEmitter {
|
|
|
139
151
|
let newBacnetDevice = new BacnetDevice(false, device);
|
|
140
152
|
newBacnetDevice.setLastSeen(Date.now());
|
|
141
153
|
that.updateDeviceName(newBacnetDevice);
|
|
154
|
+
if(newBacnetDevice.getIsMstpDevice()) {
|
|
155
|
+
that.addToParentMstpNetwork(newBacnetDevice);
|
|
156
|
+
}
|
|
142
157
|
that.deviceList.push(newBacnetDevice);
|
|
143
158
|
} else if(foundIndex !== -1) {
|
|
144
159
|
that.deviceList[foundIndex].updateDeviceConfig(device);
|
|
145
160
|
that.deviceList[foundIndex].setLastSeen(Date.now());
|
|
146
161
|
that.updateDeviceName(that.deviceList[foundIndex]);
|
|
162
|
+
|
|
163
|
+
if(that.deviceList[foundIndex].getIsMstpDevice()) {
|
|
164
|
+
that.addToParentMstpNetwork(that.deviceList[foundIndex]);
|
|
165
|
+
}
|
|
166
|
+
|
|
147
167
|
}
|
|
148
168
|
|
|
149
169
|
//emit event for node-red to log
|
|
@@ -167,7 +187,24 @@ class BacnetClient extends EventEmitter {
|
|
|
167
187
|
that.reinitializeClient(that.config);
|
|
168
188
|
}
|
|
169
189
|
});
|
|
170
|
-
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
testFunction() {
|
|
193
|
+
console.log("test function ");
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
addToParentMstpNetwork(device) {
|
|
200
|
+
let that = this;
|
|
201
|
+
let address = device.getAddress().address;
|
|
202
|
+
let deviceId = device.getDeviceId();
|
|
203
|
+
let foundParentIndex = that.deviceList.findIndex(ele => ele.getAddress() == address);
|
|
204
|
+
if(foundParentIndex !== -1) {
|
|
205
|
+
that.deviceList[foundParentIndex].addChildDevice(deviceId);
|
|
206
|
+
device.setParentDeviceId(that.deviceList[foundParentIndex].getDeviceId());
|
|
207
|
+
}
|
|
171
208
|
}
|
|
172
209
|
|
|
173
210
|
logOut(param1, param2) {
|
|
@@ -183,6 +220,7 @@ class BacnetClient extends EventEmitter {
|
|
|
183
220
|
that.renderList = [];
|
|
184
221
|
that.networkTree = {};
|
|
185
222
|
that.pollInProgress = false;
|
|
223
|
+
that.renderListCount = 0;
|
|
186
224
|
resolve(true);
|
|
187
225
|
} catch(e) {
|
|
188
226
|
that.logOut("Error clearing BACnet data model: ", e);
|
|
@@ -197,10 +235,11 @@ class BacnetClient extends EventEmitter {
|
|
|
197
235
|
that.pollInProgress = true;
|
|
198
236
|
|
|
199
237
|
let index = 0;
|
|
200
|
-
|
|
238
|
+
|
|
201
239
|
query(index);
|
|
202
240
|
|
|
203
241
|
function query(index) {
|
|
242
|
+
|
|
204
243
|
that.queryPriorityDevices().then(function() {
|
|
205
244
|
|
|
206
245
|
let device = that.deviceList[index];
|
|
@@ -221,8 +260,17 @@ class BacnetClient extends EventEmitter {
|
|
|
221
260
|
});
|
|
222
261
|
}).catch(function(e) {
|
|
223
262
|
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
224
|
-
|
|
225
|
-
|
|
263
|
+
device.setManualDiscoveryMode(true);
|
|
264
|
+
that.getDevicePointListWithoutObjectList(device).then(function() {
|
|
265
|
+
that.buildJsonObject(device, null).then(function() {
|
|
266
|
+
query(index);
|
|
267
|
+
}).catch(function(e) {
|
|
268
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
269
|
+
query(index);
|
|
270
|
+
});
|
|
271
|
+
}).catch(function(e){
|
|
272
|
+
query(index);
|
|
273
|
+
});
|
|
226
274
|
});
|
|
227
275
|
} catch(e) {
|
|
228
276
|
that.logOut("Error while querying devices: ", e);
|
|
@@ -242,10 +290,10 @@ class BacnetClient extends EventEmitter {
|
|
|
242
290
|
} else {
|
|
243
291
|
that.pollInProgress = false;
|
|
244
292
|
}
|
|
245
|
-
|
|
246
293
|
}
|
|
247
294
|
});
|
|
248
295
|
}
|
|
296
|
+
|
|
249
297
|
}
|
|
250
298
|
|
|
251
299
|
queryDevicesManually() {
|
|
@@ -444,6 +492,7 @@ class BacnetClient extends EventEmitter {
|
|
|
444
492
|
//buildNetworkTreeData task
|
|
445
493
|
const buildNetworkTree = new Task('simple task', () => {
|
|
446
494
|
that.buildNetworkTreeData();
|
|
495
|
+
that.countDevices();
|
|
447
496
|
});
|
|
448
497
|
|
|
449
498
|
const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10, }, buildNetworkTree)
|
|
@@ -474,11 +523,10 @@ class BacnetClient extends EventEmitter {
|
|
|
474
523
|
return newProps;
|
|
475
524
|
}
|
|
476
525
|
|
|
477
|
-
doRead(readConfig, outputType, objectPropertyType,
|
|
526
|
+
doRead(readConfig, outputType, objectPropertyType, readNodeName) {
|
|
478
527
|
let that = this;
|
|
479
528
|
that.roundDecimal = readConfig.precision;
|
|
480
529
|
let devicesToRead = Object.keys(readConfig.pointsToRead);
|
|
481
|
-
|
|
482
530
|
try {
|
|
483
531
|
let bacnetResults = {};
|
|
484
532
|
devicesToRead.forEach(function(key, index) {
|
|
@@ -493,18 +541,54 @@ class BacnetClient extends EventEmitter {
|
|
|
493
541
|
let bac_obj = that.getObjectType(readConfig.pointsToRead[key][pointName].meta.objectId.type);
|
|
494
542
|
let objectId = pointName + "_" + bac_obj + '_' + readConfig.pointsToRead[key][pointName].meta.objectId.instance;
|
|
495
543
|
let point = deviceObject[objectId];
|
|
496
|
-
|
|
544
|
+
|
|
545
|
+
that.updatePoint(device, point).then(function(result) {
|
|
546
|
+
if(isNumber(result.values[0].value)) {
|
|
547
|
+
point.presentValue = roundDecimalPlaces(result.values[0].value, that.roundDecimal);
|
|
548
|
+
} else {
|
|
549
|
+
point.presentValue = result.values[0].value;
|
|
550
|
+
}
|
|
551
|
+
bacnetResults[deviceName][pointName] = point;
|
|
552
|
+
}).catch(function(err) {
|
|
553
|
+
//do nothing for now
|
|
554
|
+
});
|
|
555
|
+
|
|
497
556
|
}
|
|
498
557
|
}
|
|
499
558
|
}
|
|
500
559
|
|
|
501
|
-
|
|
560
|
+
setTimeout(() => {
|
|
561
|
+
if(index == devicesToRead.length - 1 && Object.keys(readConfig.pointsToRead).length > 0) that.emit('values', bacnetResults, outputType, objectPropertyType, readNodeName);
|
|
562
|
+
}, 3000);
|
|
502
563
|
});
|
|
503
564
|
} catch(e) {
|
|
504
565
|
that.logOut("Issue doing read, see error: ", e);
|
|
505
566
|
}
|
|
506
567
|
}
|
|
507
568
|
|
|
569
|
+
updatePoint(device, point) {
|
|
570
|
+
let that = this;
|
|
571
|
+
return new Promise((resolve, reject) => {
|
|
572
|
+
|
|
573
|
+
that.client.readProperty(
|
|
574
|
+
device.getAddress(),
|
|
575
|
+
{type: point.objectID.type, instance: point.objectID.instance },
|
|
576
|
+
baEnum.PropertyIdentifier.PRESENT_VALUE,
|
|
577
|
+
{},
|
|
578
|
+
(err, value) => {
|
|
579
|
+
if(err) {
|
|
580
|
+
//console.log("err ", err);
|
|
581
|
+
reject(err);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if(value) {
|
|
585
|
+
resolve(value);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
);
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
508
592
|
getDeviceAddress(device) {
|
|
509
593
|
switch(typeof device.getAddress()) {
|
|
510
594
|
case "object":
|
|
@@ -615,91 +699,49 @@ class BacnetClient extends EventEmitter {
|
|
|
615
699
|
let that = this;
|
|
616
700
|
|
|
617
701
|
return new Promise(function(resolve, reject) {
|
|
618
|
-
|
|
619
|
-
let objectNameProperty = [{ id: baEnum.PropertyIdentifier.OBJECT_NAME }];
|
|
620
|
-
let address = device.getAddress();
|
|
621
|
-
let objectTypeList = [0, 1, 2, 3, 4, 5, 13, 14, 19];
|
|
622
|
-
//let objectTypeList = [0, 1, 2, 3, 4, 5, 6, 10, 13, 14, 15, 16, 17, ,19, 20, 56, 178];
|
|
623
|
-
//let instanceRange = {start: 0, end: 100};
|
|
624
|
-
let instanceRange = device.getmDiscoverInstanceRange();
|
|
625
|
-
let requestArray = [];
|
|
626
|
-
let maxRequestThreshold = 1000;
|
|
627
|
-
let requestRate = 20;
|
|
628
|
-
let requestBuffer = [];
|
|
629
|
-
let sendBuffer = [];
|
|
630
|
-
|
|
631
|
-
if(that.manual_instance_range_enabled == true) {
|
|
632
|
-
instanceRange.start = that.manual_instance_range_start;
|
|
633
|
-
maxRequestThreshold = that.manual_instance_range_end;
|
|
634
|
-
if(that.manual_instance_range_end < requestRate) {
|
|
635
|
-
requestRate = that.manual_instance_range_end;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
702
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
requestArray.push({
|
|
644
|
-
objectId: { type: objectType, instance: i },
|
|
645
|
-
properties: objectNameProperty
|
|
646
|
-
})
|
|
647
|
-
|
|
648
|
-
if(requestArray.length == requestRate ) {
|
|
649
|
-
requestBuffer.push(that._readObjectWithRequestArray(address, requestArray));
|
|
650
|
-
instanceRange.end += requestRate;
|
|
651
|
-
requestArray = [];
|
|
652
|
-
if(i >= maxRequestThreshold) {
|
|
653
|
-
if(typeListIndex == objectTypeList.length-1) {
|
|
654
|
-
device.setmDiscoverInstanceRange({start: instanceRange.end, end: instanceRange.end + 100})
|
|
655
|
-
send();
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
break;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
703
|
+
let address = device.getAddress();
|
|
704
|
+
let deviceId = device.getDeviceId();
|
|
705
|
+
let discoveredPointList = [];
|
|
662
706
|
|
|
663
|
-
|
|
707
|
+
let index = 1;
|
|
664
708
|
|
|
665
|
-
|
|
709
|
+
send(index);
|
|
710
|
+
|
|
666
711
|
|
|
667
|
-
|
|
668
|
-
let promise = requestBuffer[index];
|
|
669
|
-
try {
|
|
670
|
-
Promise.resolve(promise).then(function(result) {
|
|
671
|
-
for (const [key, value] of Object.entries(result)) {
|
|
672
|
-
if(key == "value" && typeof value == "object") {
|
|
673
|
-
for(let x = 0; x < value.values.length; x++) {
|
|
674
|
-
let ele = value.values[x];
|
|
675
|
-
let valueRoot = ele.values[0].value[0];
|
|
676
|
-
if(!valueRoot.value.errorClass && !valueRoot.value.errorCode) {
|
|
677
|
-
sendBuffer.push({"value": ele.objectId, "type": 12});
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
712
|
+
function send(index) {
|
|
682
713
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
714
|
+
let readOptions = {
|
|
715
|
+
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
716
|
+
maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
717
|
+
arrayIndex: index
|
|
718
|
+
}
|
|
686
719
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
720
|
+
that.client.readProperty(
|
|
721
|
+
address,
|
|
722
|
+
{type: baEnum.ObjectType.DEVICE, instance: deviceId },
|
|
723
|
+
baEnum.PropertyIdentifier.OBJECT_LIST,
|
|
724
|
+
readOptions,
|
|
725
|
+
(err, value) => {
|
|
726
|
+
if(err) {
|
|
727
|
+
resolve(discoveredPointList);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
if(value) {
|
|
731
|
+
discoveredPointList.push(value.values[0]);
|
|
732
|
+
index++;
|
|
733
|
+
send(index);
|
|
734
|
+
}
|
|
692
735
|
}
|
|
693
|
-
|
|
736
|
+
);
|
|
694
737
|
}
|
|
695
|
-
|
|
696
738
|
});
|
|
697
739
|
}
|
|
698
740
|
|
|
699
|
-
_readObjectWithRequestArray(deviceAddress, requestArray) {
|
|
741
|
+
_readObjectWithRequestArray(deviceAddress, requestArray, readOptions) {
|
|
700
742
|
let that = this;
|
|
701
743
|
return new Promise((resolve, reject) => {
|
|
702
|
-
this.client.readPropertyMultiple(deviceAddress, requestArray,
|
|
744
|
+
this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
|
|
703
745
|
resolve({
|
|
704
746
|
error: error,
|
|
705
747
|
value: value
|
|
@@ -708,7 +750,7 @@ class BacnetClient extends EventEmitter {
|
|
|
708
750
|
});
|
|
709
751
|
}
|
|
710
752
|
|
|
711
|
-
_readDeviceName(deviceAddress, deviceId, callback){
|
|
753
|
+
_readDeviceName(deviceAddress, deviceId, callback) {
|
|
712
754
|
let that = this;
|
|
713
755
|
that.client.readProperty(
|
|
714
756
|
deviceAddress,
|
|
@@ -719,7 +761,7 @@ class BacnetClient extends EventEmitter {
|
|
|
719
761
|
);
|
|
720
762
|
}
|
|
721
763
|
|
|
722
|
-
_readObjectList(deviceAddress, deviceId, callback) {
|
|
764
|
+
_readObjectList(deviceAddress, deviceId, readOptions, callback) {
|
|
723
765
|
let that = this;
|
|
724
766
|
|
|
725
767
|
try {
|
|
@@ -727,7 +769,7 @@ class BacnetClient extends EventEmitter {
|
|
|
727
769
|
deviceAddress,
|
|
728
770
|
{type: baEnum.ObjectType.DEVICE, instance: deviceId },
|
|
729
771
|
baEnum.PropertyIdentifier.OBJECT_LIST,
|
|
730
|
-
|
|
772
|
+
readOptions,
|
|
731
773
|
callback
|
|
732
774
|
);
|
|
733
775
|
|
|
@@ -736,14 +778,14 @@ class BacnetClient extends EventEmitter {
|
|
|
736
778
|
}
|
|
737
779
|
}
|
|
738
780
|
|
|
739
|
-
_readObject(deviceAddress, type, instance, properties) {
|
|
781
|
+
_readObject(deviceAddress, type, instance, properties, readOptions) {
|
|
740
782
|
let that = this;
|
|
741
783
|
return new Promise((resolve, reject) => {
|
|
742
784
|
const requestArray = [{
|
|
743
785
|
objectId: { type: type, instance: instance },
|
|
744
786
|
properties: properties
|
|
745
787
|
}];
|
|
746
|
-
this.client.readPropertyMultiple(deviceAddress, requestArray,
|
|
788
|
+
this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
|
|
747
789
|
resolve({
|
|
748
790
|
error: error,
|
|
749
791
|
value: value
|
|
@@ -752,8 +794,12 @@ class BacnetClient extends EventEmitter {
|
|
|
752
794
|
});
|
|
753
795
|
}
|
|
754
796
|
|
|
755
|
-
_readObjectFull(deviceAddress, type, instance) {
|
|
797
|
+
_readObjectFull(device, deviceAddress, type, instance) {
|
|
756
798
|
let that = this;
|
|
799
|
+
const readOptions = {
|
|
800
|
+
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
801
|
+
maxApdu: that.readPropertyMultipleOptions.maxApdu
|
|
802
|
+
};
|
|
757
803
|
|
|
758
804
|
const allProperties = [
|
|
759
805
|
{ id: baEnum.PropertyIdentifier.PRESENT_VALUE },
|
|
@@ -769,33 +815,71 @@ class BacnetClient extends EventEmitter {
|
|
|
769
815
|
];
|
|
770
816
|
|
|
771
817
|
return new Promise((resolve, reject) => {
|
|
772
|
-
that._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }]).then(function(result) {
|
|
818
|
+
that._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }], readOptions).then(function(result) {
|
|
773
819
|
|
|
774
820
|
if(result.value) {
|
|
775
821
|
resolve(result);
|
|
776
822
|
}
|
|
777
823
|
|
|
778
824
|
if(result.error) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
properties: allProperties
|
|
782
|
-
}];
|
|
783
|
-
|
|
784
|
-
that._readObjectWithRequestArray(deviceAddress, requestArray).then(function(manualRequest) {
|
|
785
|
-
if(manualRequest.value) {
|
|
786
|
-
resolve(manualRequest);
|
|
787
|
-
}
|
|
788
|
-
if(manualRequest.error) {
|
|
789
|
-
reject(manualRequest.error);
|
|
790
|
-
}
|
|
791
|
-
})
|
|
825
|
+
let i = 0;
|
|
826
|
+
readIndividualProperties(i);
|
|
792
827
|
}
|
|
793
828
|
|
|
794
829
|
}).catch(function(error) {
|
|
795
|
-
|
|
830
|
+
let i = 0;
|
|
831
|
+
readIndividualProperties(i);
|
|
796
832
|
});
|
|
797
|
-
});
|
|
798
833
|
|
|
834
|
+
let resultArray = [];
|
|
835
|
+
let errorArray = [];
|
|
836
|
+
|
|
837
|
+
function readIndividualProperties(index) {
|
|
838
|
+
|
|
839
|
+
const property = allProperties[index];
|
|
840
|
+
|
|
841
|
+
that.client.readProperty(
|
|
842
|
+
deviceAddress,
|
|
843
|
+
{type: type, instance: instance },
|
|
844
|
+
property.id,
|
|
845
|
+
readOptions,
|
|
846
|
+
(err, value) => {
|
|
847
|
+
if(err) {
|
|
848
|
+
errorArray.push(err);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if(value) {
|
|
852
|
+
let formattedResult = {
|
|
853
|
+
len: value.len,
|
|
854
|
+
objectId: value.objectId,
|
|
855
|
+
values: [
|
|
856
|
+
{
|
|
857
|
+
id: value.property.id,
|
|
858
|
+
index: value.property.index,
|
|
859
|
+
value: value.values
|
|
860
|
+
}
|
|
861
|
+
]
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
resultArray.push({error: null, value: formattedResult});
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if(index == allProperties.length - 1) {
|
|
868
|
+
resolve(resultArray);
|
|
869
|
+
|
|
870
|
+
// if(resultArray.length > 0) {
|
|
871
|
+
// resolve(resultArray);
|
|
872
|
+
// } else if(errorArray.length > 0){
|
|
873
|
+
// reject(errorArray);
|
|
874
|
+
// }
|
|
875
|
+
} else if( index < allProperties.length - 1) {
|
|
876
|
+
index++;
|
|
877
|
+
readIndividualProperties(index);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
);
|
|
881
|
+
};
|
|
882
|
+
});
|
|
799
883
|
};
|
|
800
884
|
|
|
801
885
|
_readObjectPropList(deviceAddress, type, instance) {
|
|
@@ -823,21 +907,15 @@ class BacnetClient extends EventEmitter {
|
|
|
823
907
|
doWrite(value, options){
|
|
824
908
|
let that = this;
|
|
825
909
|
let valuesArray = [];
|
|
826
|
-
|
|
827
910
|
options.pointsToWrite.forEach(function(point){
|
|
828
|
-
|
|
829
911
|
let deviceAddress = point.deviceAddress;
|
|
830
|
-
|
|
831
|
-
if(valuesArray[deviceAddress] == null || valuesArray[deviceAddress] == undefined){
|
|
832
|
-
valuesArray[deviceAddress] = [];
|
|
833
|
-
}
|
|
834
|
-
|
|
835
912
|
let writeObject = {
|
|
913
|
+
address: deviceAddress,
|
|
836
914
|
objectId: {
|
|
837
915
|
type: point.meta.objectId.type,
|
|
838
916
|
instance: point.meta.objectId.instance
|
|
839
917
|
},
|
|
840
|
-
values:
|
|
918
|
+
values: {
|
|
841
919
|
property: {
|
|
842
920
|
id: 85,
|
|
843
921
|
index: point.meta.arrayIndex
|
|
@@ -846,11 +924,17 @@ class BacnetClient extends EventEmitter {
|
|
|
846
924
|
type: options.appTag,
|
|
847
925
|
value: value
|
|
848
926
|
}],
|
|
927
|
+
|
|
928
|
+
},
|
|
929
|
+
options: {
|
|
930
|
+
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
931
|
+
maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
932
|
+
arrayIndex: point.meta.arrayIndex,
|
|
849
933
|
priority: options.priority
|
|
850
|
-
}
|
|
934
|
+
}
|
|
851
935
|
};
|
|
852
936
|
|
|
853
|
-
valuesArray
|
|
937
|
+
valuesArray.push(writeObject);
|
|
854
938
|
});
|
|
855
939
|
|
|
856
940
|
return that._writePropertyMultiple(valuesArray);
|
|
@@ -858,24 +942,23 @@ class BacnetClient extends EventEmitter {
|
|
|
858
942
|
|
|
859
943
|
_writePropertyMultiple(values) {
|
|
860
944
|
let that = this;
|
|
861
|
-
let writePromises = [];
|
|
862
945
|
try {
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
});
|
|
946
|
+
values.forEach(function(point) {
|
|
947
|
+
|
|
948
|
+
that.client.writeProperty(
|
|
949
|
+
point.address,
|
|
950
|
+
point.objectId,
|
|
951
|
+
baEnum.PropertyIdentifier.PRESENT_VALUE,
|
|
952
|
+
point.values.value,
|
|
953
|
+
point.options,
|
|
954
|
+
(err, value) => {
|
|
955
|
+
if(err) {
|
|
956
|
+
that.logOut(err);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
);
|
|
878
960
|
});
|
|
961
|
+
|
|
879
962
|
} catch (error) {
|
|
880
963
|
that.logOut(error);
|
|
881
964
|
}
|
|
@@ -895,7 +978,11 @@ class BacnetClient extends EventEmitter {
|
|
|
895
978
|
scanDevice(device) {
|
|
896
979
|
let that = this;
|
|
897
980
|
return new Promise((resolve, reject) => {
|
|
898
|
-
|
|
981
|
+
const readOptions = {
|
|
982
|
+
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
983
|
+
maxApdu: that.readPropertyMultipleOptions.maxApdu
|
|
984
|
+
};
|
|
985
|
+
this._readObjectList(device.getAddress(), device.getDeviceId(), readOptions, (err, result) => {
|
|
899
986
|
if (!err) {
|
|
900
987
|
try {
|
|
901
988
|
resolve(result.values);
|
|
@@ -937,7 +1024,7 @@ class BacnetClient extends EventEmitter {
|
|
|
937
1024
|
reducedDeviceList.forEach((device) => {
|
|
938
1025
|
delete device["pointsList"];
|
|
939
1026
|
});
|
|
940
|
-
resolve({renderList: that.renderList, deviceList: reducedDeviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule});
|
|
1027
|
+
resolve({renderList: that.renderList, deviceList: reducedDeviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule, renderListCount: that.renderListCount});
|
|
941
1028
|
} catch(e){
|
|
942
1029
|
reject(e);
|
|
943
1030
|
}
|
|
@@ -963,7 +1050,7 @@ class BacnetClient extends EventEmitter {
|
|
|
963
1050
|
deviceL.forEach(function(device) {
|
|
964
1051
|
let foundIndex = that.deviceList.findIndex(ele => ele.getDeviceId() == device.deviceId);
|
|
965
1052
|
if(foundIndex == -1) {
|
|
966
|
-
let newBacnetDevice = new BacnetDevice(
|
|
1053
|
+
let newBacnetDevice = new BacnetDevice(true, device);
|
|
967
1054
|
newBacnetDevice.setLastSeen(Date.now());
|
|
968
1055
|
that.deviceList.push(newBacnetDevice);
|
|
969
1056
|
|
|
@@ -1042,7 +1129,7 @@ class BacnetClient extends EventEmitter {
|
|
|
1042
1129
|
that.buildTreeMutex = new Mutex();
|
|
1043
1130
|
let displayNameCharThreshold = 40;
|
|
1044
1131
|
|
|
1045
|
-
Store_Config(JSON.stringify({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree}));
|
|
1132
|
+
Store_Config(JSON.stringify({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, renderListCount: that.renderListCount}));
|
|
1046
1133
|
|
|
1047
1134
|
return new Promise(async function(resolve, reject) {
|
|
1048
1135
|
if(!that.renderList) that.renderList = [];
|
|
@@ -1067,6 +1154,7 @@ class BacnetClient extends EventEmitter {
|
|
|
1067
1154
|
for(const pointName in deviceObject) {
|
|
1068
1155
|
let pointProperties = [];
|
|
1069
1156
|
let values = deviceObject[pointName];
|
|
1157
|
+
|
|
1070
1158
|
let displayName = pointName;
|
|
1071
1159
|
if(pointName.length > displayNameCharThreshold) {
|
|
1072
1160
|
displayName = "";
|
|
@@ -1080,45 +1168,150 @@ class BacnetClient extends EventEmitter {
|
|
|
1080
1168
|
}
|
|
1081
1169
|
|
|
1082
1170
|
if(values.objectName){
|
|
1083
|
-
pointProperties.push({"key": `${index}-${pointIndex}-0`, "label": `Name: ${values.objectName}`, "data": values.objectName, "icon": "pi pi-
|
|
1171
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-0`, "label": `Name: ${values.objectName}`, "data": values.objectName, "icon": "pi pi-cog", "children": null});
|
|
1084
1172
|
}
|
|
1085
|
-
if(values.objectType){
|
|
1086
|
-
pointProperties.push({"key": `${index}-${pointIndex}-1`, "label": `Object Type: ${values.objectType}`, "data": values.objectType, "icon": "pi pi-
|
|
1173
|
+
if(values.objectType && values.objectID.type !== 8){
|
|
1174
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-1`, "label": `Object Type: ${values.objectType}`, "data": values.objectType, "icon": "pi pi-cog", "children": null});
|
|
1087
1175
|
}
|
|
1088
1176
|
if(values.objectID && values.objectID.instance) {
|
|
1089
|
-
pointProperties.push({"key": `${index}-${pointIndex}-2`, "label": `Object Instance: ${values.objectID.instance}`, "data": values.objectID.instance, "icon": "pi pi-
|
|
1177
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-2`, "label": `Object Instance: ${values.objectID.instance}`, "data": values.objectID.instance, "icon": "pi pi-cog", "children": null});
|
|
1090
1178
|
}
|
|
1091
1179
|
if(values.description){
|
|
1092
|
-
pointProperties.push({"key": `${index}-${pointIndex}-3`, "label": `Description: ${values.description}`, "data": `${values.description}`, "icon": "pi pi-
|
|
1180
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-3`, "label": `Description: ${values.description}`, "data": `${values.description}`, "icon": "pi pi-cog", "children": null});
|
|
1093
1181
|
}
|
|
1094
1182
|
if(values.units){
|
|
1095
|
-
pointProperties.push({"key": `${index}-${pointIndex}-4`, "label": `Units: ${values.units}`, "data": `${values.units}`, "icon": "pi pi-
|
|
1183
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-4`, "label": `Units: ${values.units}`, "data": `${values.units}`, "icon": "pi pi-cog", "children": null});
|
|
1096
1184
|
}
|
|
1097
1185
|
if(values.presentValue !== "undefined" && values.presentValue !== null && typeof values.presentValue !== "undefined") {
|
|
1098
|
-
pointProperties.push({"key": `${index}-${pointIndex}-5`, "label": `Present Value: ${values.presentValue}`, "data": `${values.presentValue}`, "icon": "pi pi-
|
|
1186
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-5`, "label": `Present Value: ${values.presentValue}`, "data": `${values.presentValue}`, "icon": "pi pi-cog", "children": null});
|
|
1099
1187
|
}
|
|
1100
1188
|
if(values.systemStatus !== null && typeof values.systemStatus !== "undefined" && values.systemStatus !== ""){
|
|
1101
|
-
pointProperties.push({"key": `${index}-${pointIndex}-6`, "label": `System Status: ${values.systemStatus}`, "data": `${values.systemStatus}`, "icon": "pi pi-
|
|
1189
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-6`, "label": `System Status: ${values.systemStatus}`, "data": `${values.systemStatus}`, "icon": "pi pi-cog", "children": null});
|
|
1102
1190
|
}
|
|
1103
1191
|
if(values.modificationDate && !values.modificationDate.errorClass) {
|
|
1104
|
-
pointProperties.push({"key": `${index}-${pointIndex}-7`, "label": `Modification Date: ${values.modificationDate}`, "data": `${values.modificationDate}`, "icon": "pi pi-
|
|
1192
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-7`, "label": `Modification Date: ${values.modificationDate}`, "data": `${values.modificationDate}`, "icon": "pi pi-cog", "children": null});
|
|
1105
1193
|
}
|
|
1106
1194
|
if(values.programState){
|
|
1107
|
-
pointProperties.push({"key": `${index}-${pointIndex}-8`, "label": `Program State: ${values.programState}`, "data": `${values.programState}`, "icon": "pi pi-
|
|
1195
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-8`, "label": `Program State: ${values.programState}`, "data": `${values.programState}`, "icon": "pi pi-cog", "children": null});
|
|
1108
1196
|
}
|
|
1109
1197
|
if(values.recordCount && !values.recordCount.errorClass){
|
|
1110
|
-
pointProperties.push({"key": `${index}-${pointIndex}-9`, "label": `Record Count: ${values.recordCount}`, "data": `${values.recordCount}`, "icon": "pi pi-
|
|
1198
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-9`, "label": `Record Count: ${values.recordCount}`, "data": `${values.recordCount}`, "icon": "pi pi-cog", "children": null});
|
|
1199
|
+
}
|
|
1200
|
+
if(values.objectID && values.objectID.type == 8) {
|
|
1201
|
+
//device point, add segmentation supported, and apdu size
|
|
1202
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-10`, "label": `Segmentation Supported: ${deviceInfo.getSegmentation()}`, "data": `${deviceInfo.getSegmentation()}`, "icon": "pi pi-cog", "children": null});
|
|
1203
|
+
pointProperties.push({"key": `${index}-0-${pointIndex}-11`, "label": `APDU Size: ${deviceInfo.getMaxApdu()}`, "data": `${deviceInfo.getMaxApdu()}`, "icon": "pi pi-cog", "children": null});
|
|
1111
1204
|
}
|
|
1112
1205
|
|
|
1113
|
-
children.push({"key": `${index}-${pointIndex}`, "label": displayName, "data": displayName, "pointName": pointName, "icon": that.getPointIcon(values.meta.objectId.type), "children": pointProperties, "type": "point", "parentDevice": deviceName, "showAdded": false, "bacnetType": values.meta.objectId.type})
|
|
1206
|
+
children.push({"key": `${index}-0-${pointIndex}`, "label": displayName, "data": displayName, "pointName": pointName, "icon": that.getPointIcon(values.meta.objectId.type), "children": pointProperties, "type": "point", "parentDevice": deviceName, "showAdded": false, "bacnetType": values.meta.objectId.type})
|
|
1114
1207
|
pointIndex++;
|
|
1115
1208
|
}
|
|
1116
1209
|
let foundIndex = that.renderList.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
|
|
1117
1210
|
if(foundIndex !== -1) {
|
|
1118
|
-
|
|
1211
|
+
let folderJson = [];
|
|
1212
|
+
if(deviceInfo.hasChildDevices()) {
|
|
1213
|
+
folderJson = [
|
|
1214
|
+
{
|
|
1215
|
+
key: `${index}-0`,
|
|
1216
|
+
label: "Points",
|
|
1217
|
+
data: "Points Folder",
|
|
1218
|
+
icon: "pi pi-circle-fill",
|
|
1219
|
+
type: "pointFolder",
|
|
1220
|
+
children: children.sort(that.sortPoints)
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
key: `${index}-1`,
|
|
1224
|
+
label: "MSTP Network",
|
|
1225
|
+
data: "Devices Folder",
|
|
1226
|
+
icon: "pi pi-database",
|
|
1227
|
+
type: "deviceFolder",
|
|
1228
|
+
children: []
|
|
1229
|
+
}
|
|
1230
|
+
];
|
|
1231
|
+
} else {
|
|
1232
|
+
folderJson = [
|
|
1233
|
+
{
|
|
1234
|
+
key: `${index}-0`,
|
|
1235
|
+
label: "Points",
|
|
1236
|
+
data: "Points Folder",
|
|
1237
|
+
icon: "pi pi-circle-fill",
|
|
1238
|
+
type: "pointFolder",
|
|
1239
|
+
children: children.sort(that.sortPoints)
|
|
1240
|
+
}
|
|
1241
|
+
];
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
if(!isMstpDevice) {
|
|
1245
|
+
that.renderList[foundIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": that.renderList[foundIndex].children, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
|
|
1246
|
+
} else if(isMstpDevice) {
|
|
1247
|
+
let parentDeviceId = deviceInfo.getParentDeviceId();
|
|
1248
|
+
let parentDeviceIndex = that.renderList.findIndex(ele => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr);
|
|
1249
|
+
|
|
1250
|
+
if(parentDeviceIndex !== -1 && that.renderList[parentDeviceIndex].children[1].children) {
|
|
1251
|
+
let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
|
|
1252
|
+
if(mstpDeviceIndex == -1) {
|
|
1253
|
+
//that.renderListCount++;
|
|
1254
|
+
that.renderList[parentDeviceIndex].children[1].children.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
|
|
1255
|
+
} else {
|
|
1256
|
+
that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1119
1261
|
} else if(foundIndex == -1) {
|
|
1120
|
-
|
|
1262
|
+
let folderJson = [];
|
|
1263
|
+
if(deviceInfo.hasChildDevices()) {
|
|
1264
|
+
folderJson = [
|
|
1265
|
+
{
|
|
1266
|
+
key: `${index}-0`,
|
|
1267
|
+
label: "Points",
|
|
1268
|
+
data: "Points Folder",
|
|
1269
|
+
icon: "pi pi-circle-fill",
|
|
1270
|
+
type: "pointFolder",
|
|
1271
|
+
children: children.sort(that.sortPoints)
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
key: `${index}-1`,
|
|
1275
|
+
label: "MSTP Network",
|
|
1276
|
+
data: "Devices Folder",
|
|
1277
|
+
icon: "pi pi-database",
|
|
1278
|
+
type: "deviceFolder",
|
|
1279
|
+
children: []
|
|
1280
|
+
}
|
|
1281
|
+
];
|
|
1282
|
+
} else {
|
|
1283
|
+
folderJson = [
|
|
1284
|
+
{
|
|
1285
|
+
key: `${index}-0`,
|
|
1286
|
+
label: "Points",
|
|
1287
|
+
data: "Points Folder",
|
|
1288
|
+
icon: "pi pi-circle-fill",
|
|
1289
|
+
type: "pointFolder",
|
|
1290
|
+
children: children.sort(that.sortPoints)
|
|
1291
|
+
}
|
|
1292
|
+
];
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if(!isMstpDevice) {
|
|
1296
|
+
//that.renderListCount++;
|
|
1297
|
+
that.renderList.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
|
|
1298
|
+
} else if(isMstpDevice) {
|
|
1299
|
+
let parentDeviceId = deviceInfo.getParentDeviceId();
|
|
1300
|
+
let parentDeviceIndex = that.renderList.findIndex(ele => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr);
|
|
1301
|
+
|
|
1302
|
+
if(parentDeviceIndex !== -1 && that.renderList[parentDeviceIndex].children && that.renderList[parentDeviceIndex].children[1].children) {
|
|
1303
|
+
let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
|
|
1304
|
+
|
|
1305
|
+
if(mstpDeviceIndex == -1) {
|
|
1306
|
+
// that.renderListCount++;
|
|
1307
|
+
that.renderList[parentDeviceIndex].children[1].children.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
|
|
1308
|
+
} else {
|
|
1309
|
+
that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1121
1313
|
}
|
|
1314
|
+
|
|
1122
1315
|
if(index == that.deviceList.length - 1) {
|
|
1123
1316
|
that.renderList.sort(that.sortDevices);
|
|
1124
1317
|
resolve({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule});
|
|
@@ -1132,12 +1325,33 @@ class BacnetClient extends EventEmitter {
|
|
|
1132
1325
|
|
|
1133
1326
|
release();
|
|
1134
1327
|
});
|
|
1135
|
-
|
|
1136
1328
|
});
|
|
1137
1329
|
}
|
|
1138
1330
|
});
|
|
1139
1331
|
}
|
|
1140
1332
|
|
|
1333
|
+
countDevices() {
|
|
1334
|
+
let that = this;
|
|
1335
|
+
|
|
1336
|
+
let deviceCount = 0;
|
|
1337
|
+
|
|
1338
|
+
that.renderList.forEach(function(device, index) {
|
|
1339
|
+
if(device) {
|
|
1340
|
+
if(device.children[1] && device.children[1].label == 'MSTP Network' && device.children[1].children && device.children[1].children.length > 0) {
|
|
1341
|
+
//increment for parent device / mstp router
|
|
1342
|
+
deviceCount++;
|
|
1343
|
+
//increment for mstp device list
|
|
1344
|
+
deviceCount += device.children[1].children.length;
|
|
1345
|
+
} else {
|
|
1346
|
+
deviceCount++;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
if(index == that.renderList.length -1) {
|
|
1350
|
+
that.renderListCount = deviceCount;
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1141
1355
|
buildJsonObject(device, priorityQueue) {
|
|
1142
1356
|
let that = this;
|
|
1143
1357
|
let address = device.address;
|
|
@@ -1151,10 +1365,14 @@ class BacnetClient extends EventEmitter {
|
|
|
1151
1365
|
requestMutex
|
|
1152
1366
|
.acquire()
|
|
1153
1367
|
.then(function(release) {
|
|
1154
|
-
that._readObjectFull(address, point.value.type, point.value.instance).then(function(result) {
|
|
1368
|
+
that._readObjectFull(device, address, point.value.type, point.value.instance).then(function(result) {
|
|
1155
1369
|
|
|
1156
1370
|
if(!result.error) {
|
|
1157
|
-
|
|
1371
|
+
if(result.length > 0 && Array.isArray(result)) {
|
|
1372
|
+
promiseArray = result;
|
|
1373
|
+
} else {
|
|
1374
|
+
promiseArray.push(result);
|
|
1375
|
+
}
|
|
1158
1376
|
}
|
|
1159
1377
|
|
|
1160
1378
|
release();
|
|
@@ -1203,6 +1421,11 @@ class BacnetClient extends EventEmitter {
|
|
|
1203
1421
|
let successfulResult = !obj.error ? obj.value : null;
|
|
1204
1422
|
if(successfulResult) {
|
|
1205
1423
|
successfulResult.values.forEach(function(pointProperty, pointPropertyIndex) {
|
|
1424
|
+
|
|
1425
|
+
if(!pointProperty.objectId && successfulResult.objectId && !pointProperty.values && successfulResult.values) {
|
|
1426
|
+
pointProperty = successfulResult;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1206
1429
|
let currobjectId = pointProperty.objectId.type
|
|
1207
1430
|
let bac_obj = that.getObjectType(currobjectId);
|
|
1208
1431
|
let objectName = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_NAME);
|
|
@@ -1358,34 +1581,34 @@ class BacnetClient extends EventEmitter {
|
|
|
1358
1581
|
switch(objectId) {
|
|
1359
1582
|
case 0:
|
|
1360
1583
|
//AI
|
|
1361
|
-
return "pi pi-
|
|
1584
|
+
return "pi pi-circle";
|
|
1362
1585
|
case 1:
|
|
1363
1586
|
//AO
|
|
1364
|
-
return "pi pi-
|
|
1587
|
+
return "pi pi-circle";
|
|
1365
1588
|
case 2:
|
|
1366
1589
|
//AV
|
|
1367
|
-
return "pi pi-
|
|
1590
|
+
return "pi pi-circle";
|
|
1368
1591
|
case 3:
|
|
1369
1592
|
//BI
|
|
1370
|
-
return "pi pi-
|
|
1593
|
+
return "pi pi-circle";
|
|
1371
1594
|
case 4:
|
|
1372
1595
|
//BO
|
|
1373
|
-
return "pi pi-
|
|
1596
|
+
return "pi pi-circle";
|
|
1374
1597
|
case 5:
|
|
1375
1598
|
//BV
|
|
1376
|
-
return "pi pi-
|
|
1599
|
+
return "pi pi-circle";
|
|
1377
1600
|
case 8:
|
|
1378
1601
|
//Device
|
|
1379
1602
|
return "pi pi-box";
|
|
1380
1603
|
case 13:
|
|
1381
1604
|
//MI
|
|
1382
|
-
return "pi pi-
|
|
1605
|
+
return "pi pi-circle";
|
|
1383
1606
|
case 14:
|
|
1384
1607
|
//MO
|
|
1385
|
-
return "pi pi-
|
|
1608
|
+
return "pi pi-circle";
|
|
1386
1609
|
case 19:
|
|
1387
1610
|
//MV
|
|
1388
|
-
return "pi pi-
|
|
1611
|
+
return "pi pi-circle";
|
|
1389
1612
|
case 10:
|
|
1390
1613
|
//File
|
|
1391
1614
|
return "pi pi-file";
|
|
@@ -1408,7 +1631,7 @@ class BacnetClient extends EventEmitter {
|
|
|
1408
1631
|
return "pi pi-calendar";
|
|
1409
1632
|
default:
|
|
1410
1633
|
//Return circle for all other types
|
|
1411
|
-
return "pi pi-
|
|
1634
|
+
return "pi pi-circle";
|
|
1412
1635
|
}
|
|
1413
1636
|
}
|
|
1414
1637
|
|
|
@@ -1482,16 +1705,14 @@ class BacnetClient extends EventEmitter {
|
|
|
1482
1705
|
|
|
1483
1706
|
getDeviceIcon(isMstp, manualDiscoveryMode) {
|
|
1484
1707
|
if(manualDiscoveryMode == true) {
|
|
1485
|
-
|
|
1486
|
-
return "pi pi-exclamation-triangle"
|
|
1708
|
+
return "pi pi-question-circle"
|
|
1487
1709
|
} else if(manualDiscoveryMode == false) {
|
|
1488
1710
|
if(isMstp == true) {
|
|
1489
|
-
return "pi pi-
|
|
1711
|
+
return "pi pi-box"
|
|
1490
1712
|
} else if(isMstp == false) {
|
|
1491
1713
|
return "pi pi-server"
|
|
1492
1714
|
}
|
|
1493
1715
|
}
|
|
1494
|
-
|
|
1495
1716
|
return "pi pi-server";
|
|
1496
1717
|
};
|
|
1497
1718
|
}
|