@bitpoolos/edge-bacnet 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/bacnet_client.js +117 -39
- package/bacnet_device.js +3 -1
- package/bacnet_gateway.html +82 -0
- package/bacnet_gateway.js +36 -0
- package/bacnet_read.html +21 -24
- package/package.json +1 -1
- package/resources/node-bacstack-ts/dist/lib/client.js +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.3] - 23-01-2025
|
|
4
|
+
|
|
5
|
+
New feature:
|
|
6
|
+
- import / export buttons added to new tab in gateway node, used to manage the complete data model for backup or restore
|
|
7
|
+
- associated API end points for programatic backing up or restoring - /bitpool-bacnet-data/getDataModel; /bitpool-bacnet-data/updateDataModel;
|
|
8
|
+
|
|
9
|
+
Further async / await refactoring
|
|
10
|
+
|
|
11
|
+
Bug fixes:
|
|
12
|
+
- incorrect device name in read list export
|
|
13
|
+
- read command indexing unhandled scenario
|
|
14
|
+
- duplicating points in read list after pressing refresh tree button
|
|
15
|
+
- Multi State Values and other state text based points not being handled correctly in large volume scenarios
|
|
16
|
+
|
|
17
|
+
NOTE:
|
|
18
|
+
New importing and exporting feature handles a .json file instead of the .cfg file used in the back end. This is due to browsers flagging .cfg files as malicious. The contents of the file are unchanged.
|
|
19
|
+
|
|
3
20
|
## [1.5.2] - 10-01-2025
|
|
4
21
|
|
|
5
22
|
Mismatched network request hot fix
|
package/bacnet_client.js
CHANGED
|
@@ -534,7 +534,6 @@ class BacnetClient extends EventEmitter {
|
|
|
534
534
|
}
|
|
535
535
|
}
|
|
536
536
|
try {
|
|
537
|
-
|
|
538
537
|
await that.updateDeviceName(device);
|
|
539
538
|
|
|
540
539
|
if (device.getSegmentation() !== 3) {
|
|
@@ -579,23 +578,35 @@ class BacnetClient extends EventEmitter {
|
|
|
579
578
|
}
|
|
580
579
|
}
|
|
581
580
|
|
|
582
|
-
updateDeviceName(device) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
581
|
+
// updateDeviceName(device) {
|
|
582
|
+
// let that = this;
|
|
583
|
+
// return new Promise((resolve, reject) => {
|
|
584
|
+
// that
|
|
585
|
+
// ._getDeviceName(device)
|
|
586
|
+
// .then(function (deviceObject) {
|
|
587
|
+
// if (typeof deviceObject.name == "string") {
|
|
588
|
+
// device.setDeviceName(deviceObject.name + " " + device.getDeviceId());
|
|
589
|
+
// device.setPointsList(deviceObject.devicePointEntry);
|
|
590
|
+
// }
|
|
591
|
+
// resolve();
|
|
592
|
+
// })
|
|
593
|
+
// .catch(function (e) {
|
|
594
|
+
// that.logOut("updateDeviceName error: ", e);
|
|
595
|
+
// resolve();
|
|
596
|
+
// });
|
|
597
|
+
// });
|
|
598
|
+
// }
|
|
599
|
+
|
|
600
|
+
async updateDeviceName(device) {
|
|
601
|
+
try {
|
|
602
|
+
const deviceObject = await this._getDeviceName(device);
|
|
603
|
+
if (typeof deviceObject?.name === "string") {
|
|
604
|
+
device.setDeviceName(deviceObject.name + " " + device.getDeviceId());
|
|
605
|
+
device.setPointsList(deviceObject.devicePointEntry);
|
|
606
|
+
}
|
|
607
|
+
} catch (e) {
|
|
608
|
+
this.logOut("updateDeviceName error: ", e);
|
|
609
|
+
}
|
|
599
610
|
}
|
|
600
611
|
|
|
601
612
|
reinitializeClient(config) {
|
|
@@ -729,15 +740,15 @@ class BacnetClient extends EventEmitter {
|
|
|
729
740
|
// Process points for the current device
|
|
730
741
|
const pointsToRead = readConfig.pointsToRead[key];
|
|
731
742
|
const pointNames = Object.keys(pointsToRead);
|
|
732
|
-
let totalPoints = pointNames.length;
|
|
743
|
+
let totalPoints = pointNames.length - 1;
|
|
733
744
|
let requestArray = [];
|
|
734
745
|
let processedPoints = 0; // Counter for processed points
|
|
735
746
|
|
|
736
747
|
// Process each point for the device in batches
|
|
737
748
|
for (let i = 0; i < pointNames.length; i++) {
|
|
749
|
+
|
|
738
750
|
const pointName = pointNames[i];
|
|
739
751
|
if (pointName === "deviceName") {
|
|
740
|
-
totalPoints = totalPoints - 1;
|
|
741
752
|
continue;
|
|
742
753
|
}
|
|
743
754
|
|
|
@@ -758,8 +769,7 @@ class BacnetClient extends EventEmitter {
|
|
|
758
769
|
}
|
|
759
770
|
|
|
760
771
|
// Process the batch when the request array is full or the last point is reached
|
|
761
|
-
if (requestArray.length === maxObjectCount
|
|
762
|
-
|
|
772
|
+
if (requestArray.length === maxObjectCount) {
|
|
763
773
|
if (device.getProtocolServiceSupport("ReadPropertyMultiple") == true) {
|
|
764
774
|
await that.processBatch(device, requestArray, deviceName, bacnetResults, that, roundDecimal);
|
|
765
775
|
} else {
|
|
@@ -769,6 +779,16 @@ class BacnetClient extends EventEmitter {
|
|
|
769
779
|
requestArray = [];
|
|
770
780
|
// Increment the processed points counter
|
|
771
781
|
processedPoints += maxObjectCount;
|
|
782
|
+
} else if (i === pointNames.length - 1) {
|
|
783
|
+
if (device.getProtocolServiceSupport("ReadPropertyMultiple") == true) {
|
|
784
|
+
await that.processBatch(device, requestArray, deviceName, bacnetResults, that, roundDecimal);
|
|
785
|
+
} else {
|
|
786
|
+
await that.processIndividualPoints(device, requestArray, deviceName, bacnetResults, that, roundDecimal);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
requestArray = [];
|
|
790
|
+
// Increment the processed points counter
|
|
791
|
+
processedPoints += i;
|
|
772
792
|
}
|
|
773
793
|
|
|
774
794
|
// Check if all points for the device have been processed
|
|
@@ -870,17 +890,23 @@ class BacnetClient extends EventEmitter {
|
|
|
870
890
|
const { objectId, pointRef, pointName } = request;
|
|
871
891
|
try {
|
|
872
892
|
|
|
873
|
-
|
|
874
893
|
const result = await that.updatePoint(device, pointRef);
|
|
875
894
|
|
|
876
|
-
//const result = await that.updatePointWithRetry(device, pointRef, 1);
|
|
877
|
-
|
|
878
|
-
|
|
879
895
|
if (result.objectId.type == objectId.type && result.objectId.instance == objectId.instance) {
|
|
880
896
|
const val = result.values[0].value;
|
|
881
897
|
|
|
882
898
|
if (isNumber(val)) {
|
|
883
899
|
pointRef.presentValue = roundDecimalPlaces(val, roundDecimal);
|
|
900
|
+
|
|
901
|
+
if (pointRef.meta.objectId.type == 19 || pointRef.meta.objectId.type == 13 || pointRef.meta.objectId.type == 14) {
|
|
902
|
+
if (pointRef.stateTextArray && typeof pointRef.stateTextArray[0].value !== "object") {
|
|
903
|
+
if (val != 0) {
|
|
904
|
+
pointRef.presentValue = pointRef.stateTextArray[val - 1].value;
|
|
905
|
+
} else {
|
|
906
|
+
pointRef.presentValue = pointRef.stateTextArray[val].value;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
884
910
|
} else {
|
|
885
911
|
pointRef.presentValue = val;
|
|
886
912
|
}
|
|
@@ -905,24 +931,37 @@ class BacnetClient extends EventEmitter {
|
|
|
905
931
|
}
|
|
906
932
|
}
|
|
907
933
|
|
|
908
|
-
updateManyPoints(device, points) {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
934
|
+
// updateManyPoints(device, points) {
|
|
935
|
+
// let that = this;
|
|
936
|
+
// return new Promise((resolve, reject) => {
|
|
937
|
+
// // let readOptions = {
|
|
938
|
+
// // maxSegments: device.getMaxSe,
|
|
939
|
+
// // maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
940
|
+
// // };
|
|
941
|
+
|
|
942
|
+
// that
|
|
943
|
+
// ._readObjectWithRequestArray(device, points, that.readPropertyMultipleOptions)
|
|
944
|
+
// .then(function (results) {
|
|
945
|
+
// resolve(results);
|
|
946
|
+
// })
|
|
947
|
+
// .catch(function (err) {
|
|
948
|
+
// reject(err);
|
|
949
|
+
// });
|
|
950
|
+
// });
|
|
951
|
+
// }
|
|
952
|
+
|
|
953
|
+
async updateManyPoints(device, points) {
|
|
954
|
+
try {
|
|
912
955
|
// let readOptions = {
|
|
913
956
|
// maxSegments: device.getMaxSe,
|
|
914
957
|
// maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
915
958
|
// };
|
|
916
959
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
.catch(function (err) {
|
|
923
|
-
reject(err);
|
|
924
|
-
});
|
|
925
|
-
});
|
|
960
|
+
const results = await this._readObjectWithRequestArray(device, points, this.readPropertyMultipleOptions);
|
|
961
|
+
return results;
|
|
962
|
+
} catch (error) {
|
|
963
|
+
throw error;
|
|
964
|
+
}
|
|
926
965
|
}
|
|
927
966
|
|
|
928
967
|
updatePointWithRetry(device, point, retryCount = 1) {
|
|
@@ -1552,6 +1591,22 @@ class BacnetClient extends EventEmitter {
|
|
|
1552
1591
|
});
|
|
1553
1592
|
}
|
|
1554
1593
|
|
|
1594
|
+
getDataModel() {
|
|
1595
|
+
let that = this;
|
|
1596
|
+
return new Promise(async function (resolve, reject) {
|
|
1597
|
+
try {
|
|
1598
|
+
resolve({
|
|
1599
|
+
renderList: that.renderList,
|
|
1600
|
+
deviceList: that.deviceList,
|
|
1601
|
+
pointList: that.networkTree,
|
|
1602
|
+
renderListCount: that.renderListCount,
|
|
1603
|
+
});
|
|
1604
|
+
} catch (e) {
|
|
1605
|
+
reject(e);
|
|
1606
|
+
}
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1555
1610
|
updatePointsList(json) {
|
|
1556
1611
|
let that = this;
|
|
1557
1612
|
json.deviceList.forEach(function (updatedDevice) {
|
|
@@ -1587,6 +1642,29 @@ class BacnetClient extends EventEmitter {
|
|
|
1587
1642
|
});
|
|
1588
1643
|
}
|
|
1589
1644
|
|
|
1645
|
+
updateDataModel(json) {
|
|
1646
|
+
let that = this;
|
|
1647
|
+
return new Promise(async function (resolve, reject) {
|
|
1648
|
+
try {
|
|
1649
|
+
if (json.body.renderList) {
|
|
1650
|
+
that.renderList = json.body.renderList;
|
|
1651
|
+
}
|
|
1652
|
+
if (json.body.deviceList) {
|
|
1653
|
+
await that.updateDeviceList(json);
|
|
1654
|
+
}
|
|
1655
|
+
if (json.body.pointList) {
|
|
1656
|
+
that.networkTree = json.body.pointList;
|
|
1657
|
+
}
|
|
1658
|
+
if (json.body.renderListCount) {
|
|
1659
|
+
that.renderListCount = json.body.renderListCount;
|
|
1660
|
+
}
|
|
1661
|
+
resolve();
|
|
1662
|
+
} catch (e) {
|
|
1663
|
+
reject(e);
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1590
1668
|
sortDevices(a, b) {
|
|
1591
1669
|
if (a.deviceId < b.deviceId) {
|
|
1592
1670
|
return -1;
|
package/bacnet_device.js
CHANGED
package/bacnet_gateway.html
CHANGED
|
@@ -203,6 +203,11 @@
|
|
|
203
203
|
label: "Server",
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
+
tabs.addTab({
|
|
207
|
+
id: "read-backup-tab",
|
|
208
|
+
label: "Backup & Restore",
|
|
209
|
+
});
|
|
210
|
+
|
|
206
211
|
if (node.networkInterfaces && node.networkInterfaces.length > 0) {
|
|
207
212
|
let nicSelector = document.getElementById("node-input-local_device_address");
|
|
208
213
|
node.networkInterfaces.forEach(function (option) {
|
|
@@ -333,6 +338,8 @@
|
|
|
333
338
|
vueapp.use(primevue.confirmationservice);
|
|
334
339
|
node.vm1 = vueapp.mount("#serverParent");
|
|
335
340
|
|
|
341
|
+
|
|
342
|
+
// Import Device List
|
|
336
343
|
$("#file-upload").on("change", function (event) {
|
|
337
344
|
const input = event.target.files[0];
|
|
338
345
|
const reader = new FileReader();
|
|
@@ -356,6 +363,7 @@
|
|
|
356
363
|
reader.readAsText(input);
|
|
357
364
|
});
|
|
358
365
|
|
|
366
|
+
//Export Device List
|
|
359
367
|
$("#file-export").click(function (params) {
|
|
360
368
|
$.ajax({
|
|
361
369
|
url: RED.settings.httpNodeRoot + "bitpool-bacnet-data/getDeviceList",
|
|
@@ -370,6 +378,45 @@
|
|
|
370
378
|
});
|
|
371
379
|
});
|
|
372
380
|
|
|
381
|
+
//Import complete Data model
|
|
382
|
+
$("#file-upload-database").on("change", function (event) {
|
|
383
|
+
const input = event.target.files[0];
|
|
384
|
+
const reader = new FileReader();
|
|
385
|
+
|
|
386
|
+
reader.onload = function (e) {
|
|
387
|
+
const text = e.target.result;
|
|
388
|
+
|
|
389
|
+
let jsonPayload = JSON.parse(text);
|
|
390
|
+
|
|
391
|
+
$.ajax({
|
|
392
|
+
type: "POST",
|
|
393
|
+
url: RED.settings.httpNodeRoot + "bitpool-bacnet-data/updateDataModel",
|
|
394
|
+
dataType: "json",
|
|
395
|
+
contentType: "application/json",
|
|
396
|
+
data: JSON.stringify(jsonPayload),
|
|
397
|
+
success: function (result) { },
|
|
398
|
+
timeout: 15000,
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
reader.readAsText(input);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Export complete Data model
|
|
406
|
+
$("#file-export-database").click(function (params) {
|
|
407
|
+
$.ajax({
|
|
408
|
+
url: RED.settings.httpNodeRoot + "bitpool-bacnet-data/getDataModel",
|
|
409
|
+
success: function (deviceList) {
|
|
410
|
+
let data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(deviceList));
|
|
411
|
+
let aEle = document.getElementById("exportJSON");
|
|
412
|
+
aEle.setAttribute("href", "data:" + data);
|
|
413
|
+
aEle.setAttribute("download", "edge-bacnet-datastore.json");
|
|
414
|
+
aEle.click();
|
|
415
|
+
},
|
|
416
|
+
timeout: 10000,
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
373
420
|
//start device scan range matrix
|
|
374
421
|
|
|
375
422
|
$("#node-input-deviceIdRangeMatrix-container")
|
|
@@ -739,6 +786,21 @@
|
|
|
739
786
|
.point_name {
|
|
740
787
|
font-weight: bold;
|
|
741
788
|
}
|
|
789
|
+
.database-backup {
|
|
790
|
+
border-top: 1px solid grey;
|
|
791
|
+
padding-top: 25px;
|
|
792
|
+
margin-top: 5px !important;
|
|
793
|
+
}
|
|
794
|
+
.database-file-label {
|
|
795
|
+
color: black;
|
|
796
|
+
font-weight: bold;
|
|
797
|
+
font-size: 16px;
|
|
798
|
+
width: auto !important;
|
|
799
|
+
|
|
800
|
+
}
|
|
801
|
+
.database-file-label-div {
|
|
802
|
+
padding-top: 15px;
|
|
803
|
+
}
|
|
742
804
|
</style>
|
|
743
805
|
|
|
744
806
|
<div class="form-row node-input-read-tabs-row">
|
|
@@ -967,6 +1029,26 @@
|
|
|
967
1029
|
</div>
|
|
968
1030
|
</div>
|
|
969
1031
|
</div>
|
|
1032
|
+
<div id="read-backup-tab" style="display:none">
|
|
1033
|
+
<div class="database-file-label-div">
|
|
1034
|
+
<span class="database-file-label">Database File</span>
|
|
1035
|
+
</div>
|
|
1036
|
+
|
|
1037
|
+
<div class="form-row bp-import-buttons database-backup" id="importDeviceList">
|
|
1038
|
+
<!-- <label> Device List: </label> -->
|
|
1039
|
+
<label for="file-upload-database" class="custom-file-upload">
|
|
1040
|
+
<i class="fa fa-arrow-circle-up" id="fileLabel"></i>
|
|
1041
|
+
<a id="fileLabelText" style="padding-left: 10px;">Import database</a>
|
|
1042
|
+
</label>
|
|
1043
|
+
<input type="file" id="file-upload-database" accept="application/JSON" class="inputStyle" style="width: 258px;" />
|
|
1044
|
+
<label for="file-export-database" class="custom-file-upload" style="margin-left: 5px;">
|
|
1045
|
+
<i class="fa fa-arrow-circle-down" id="fileLabel"></i>
|
|
1046
|
+
<a id="fileLabelText" style="padding-left: 10px;">Export database</a>
|
|
1047
|
+
</label>
|
|
1048
|
+
<input id="file-export-database" class="inputStyle" style="width: 258px; display: none;" />
|
|
1049
|
+
<a id="exportJSON" style="display: none"></a>
|
|
1050
|
+
</div>
|
|
1051
|
+
</div>
|
|
970
1052
|
</div>
|
|
971
1053
|
</script>
|
|
972
1054
|
<script type="text/html" data-help-name="Bacnet-Gateway">
|
package/bacnet_gateway.js
CHANGED
|
@@ -371,6 +371,42 @@ module.exports = function (RED) {
|
|
|
371
371
|
}
|
|
372
372
|
});
|
|
373
373
|
|
|
374
|
+
//route handler for getting data model
|
|
375
|
+
RED.httpAdmin.get("/bitpool-bacnet-data/getDataModel", function (req, res) {
|
|
376
|
+
if (!node.bacnetClient) {
|
|
377
|
+
logOut("Issue with the bacnetClient while getting data model: ", node.bacnetClient);
|
|
378
|
+
res.send(false);
|
|
379
|
+
} else {
|
|
380
|
+
node.bacnetClient
|
|
381
|
+
.getDataModel()
|
|
382
|
+
.then(function (result) {
|
|
383
|
+
res.send(result);
|
|
384
|
+
})
|
|
385
|
+
.catch(function (error) {
|
|
386
|
+
res.send(error);
|
|
387
|
+
logOut("Error getting data model: ", error);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
//route handler for updating data model
|
|
393
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/updateDataModel", function (req, res) {
|
|
394
|
+
if (!node.bacnetClient) {
|
|
395
|
+
logOut("Issue with the bacnetClient while getting data model: ", node.bacnetClient);
|
|
396
|
+
res.send(false);
|
|
397
|
+
} else {
|
|
398
|
+
node.bacnetClient
|
|
399
|
+
.updateDataModel(req)
|
|
400
|
+
.then(function (result) {
|
|
401
|
+
res.send(result);
|
|
402
|
+
})
|
|
403
|
+
.catch(function (error) {
|
|
404
|
+
res.send(error);
|
|
405
|
+
logOut("Error getting data model: ", error);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
374
410
|
//route handler for purge device
|
|
375
411
|
RED.httpAdmin.post("/bitpool-bacnet-data/purgeDevice", function (req, res) {
|
|
376
412
|
if (!node.bacnetClient) {
|
package/bacnet_read.html
CHANGED
|
@@ -634,14 +634,7 @@
|
|
|
634
634
|
let app = this;
|
|
635
635
|
const slotProps = app.rightClickedDevice;
|
|
636
636
|
const displayName = app.deviceDisplayNameValue;
|
|
637
|
-
let device = app.
|
|
638
|
-
if (ele.address.address) {
|
|
639
|
-
return ele.address.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
|
|
640
|
-
} else {
|
|
641
|
-
return ele.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
|
|
642
|
-
}
|
|
643
|
-
});
|
|
644
|
-
|
|
637
|
+
let device = app.getDeviceFromDeviceList(slotProps.node.ipAddr, slotProps.node.deviceId);
|
|
645
638
|
if (device) {
|
|
646
639
|
app.nodeService.setDeviceDisplayName(device, displayName).then(function (result) {
|
|
647
640
|
if (result) {
|
|
@@ -660,7 +653,7 @@
|
|
|
660
653
|
const pointName = slotProps.node.pointName;
|
|
661
654
|
|
|
662
655
|
let device = app.deviceList.find((ele) => {
|
|
663
|
-
return ele.
|
|
656
|
+
return ele.displayName == slotProps.node.parentDevice;
|
|
664
657
|
});
|
|
665
658
|
|
|
666
659
|
if (device) {
|
|
@@ -676,6 +669,18 @@
|
|
|
676
669
|
|
|
677
670
|
app.showPointNameDialog = false;
|
|
678
671
|
},
|
|
672
|
+
getDeviceFromDeviceList(ip, id) {
|
|
673
|
+
let app = this;
|
|
674
|
+
let device = app.deviceList.find((ele) => {
|
|
675
|
+
if (ele.address.address) {
|
|
676
|
+
return ele.address.address == ip && ele.deviceId == id;
|
|
677
|
+
} else {
|
|
678
|
+
return ele.address == ip && ele.deviceId == id;
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
return device;
|
|
683
|
+
},
|
|
679
684
|
settingDeviceName(slotProps) {
|
|
680
685
|
let app = this;
|
|
681
686
|
if (slotProps.node.settingDisplayName) {
|
|
@@ -709,11 +714,9 @@
|
|
|
709
714
|
(ele) => ele.ipAddr == key.split("-")[0] && ele.deviceId == key.split("-")[1]
|
|
710
715
|
);
|
|
711
716
|
let deviceName;
|
|
712
|
-
|
|
713
717
|
if (readDevice) {
|
|
714
718
|
deviceName = readDevice.label;
|
|
715
719
|
}
|
|
716
|
-
|
|
717
720
|
exportJson[key] = {};
|
|
718
721
|
if (deviceName) {
|
|
719
722
|
exportJson[key]["deviceName"] = deviceName;
|
|
@@ -725,9 +728,8 @@
|
|
|
725
728
|
let pointName = devicePoints[pointIndex];
|
|
726
729
|
let pointObject = device[pointName];
|
|
727
730
|
|
|
728
|
-
//formatting json payload
|
|
729
|
-
|
|
730
|
-
if (pointObject) {
|
|
731
|
+
//formatting json payload
|
|
732
|
+
if (pointObject && pointName !== "deviceName") {
|
|
731
733
|
exportJson[key][pointName] = {
|
|
732
734
|
meta: pointObject.meta,
|
|
733
735
|
objectName: pointObject.objectName,
|
|
@@ -765,6 +767,7 @@
|
|
|
765
767
|
let ip = key.split("-")[0];
|
|
766
768
|
let id = key.split("-")[1];
|
|
767
769
|
const importedDevice = pointsToRead[key];
|
|
770
|
+
//match only by IP, to handle case of mstp device
|
|
768
771
|
let foundIndex = app.devices.findIndex((ele) => ele.ipAddr == ip);
|
|
769
772
|
|
|
770
773
|
if (foundIndex !== -1) {
|
|
@@ -772,17 +775,11 @@
|
|
|
772
775
|
if (app.devices[foundIndex].deviceId == id) {
|
|
773
776
|
//found device
|
|
774
777
|
let treeDevice = app.devices[foundIndex];
|
|
775
|
-
let device = app.
|
|
776
|
-
if (ele.address.address) {
|
|
777
|
-
return ele.address.address == ip && ele.deviceId == id;
|
|
778
|
-
} else {
|
|
779
|
-
return ele.address == ip && ele.deviceId == id;
|
|
780
|
-
}
|
|
781
|
-
});
|
|
778
|
+
let device = app.getDeviceFromDeviceList(ip, id);
|
|
782
779
|
|
|
783
780
|
for (let pointName in importedDevice) {
|
|
784
781
|
let point = importedDevice[pointName];
|
|
785
|
-
if (pointName == "deviceName") {
|
|
782
|
+
if (pointName == "deviceName" && typeof point == "string") {
|
|
786
783
|
app.nodeService.setDeviceDisplayName(device, point);
|
|
787
784
|
treeDevice.label = point;
|
|
788
785
|
} else {
|
|
@@ -849,7 +846,7 @@
|
|
|
849
846
|
|
|
850
847
|
for (let pointName in importedDevice) {
|
|
851
848
|
let point = importedDevice[pointName];
|
|
852
|
-
if (pointName == "deviceName") {
|
|
849
|
+
if (pointName == "deviceName" && typeof point == "string") {
|
|
853
850
|
app.nodeService.setDeviceDisplayName(device, point);
|
|
854
851
|
mstpDevice.label = point;
|
|
855
852
|
} else {
|
|
@@ -878,7 +875,7 @@
|
|
|
878
875
|
} else {
|
|
879
876
|
// read device found, add point to existing
|
|
880
877
|
let pointIndex = app.readDevices[isDeviceInReadList].children[0].children.findIndex(
|
|
881
|
-
(ele) => ele.
|
|
878
|
+
(ele) => parseInt(ele.bacnetInstance) == parseInt(point.meta.objectId.instance) && parseInt(ele.bacnetType) == parseInt(point.meta.objectId.type)
|
|
882
879
|
);
|
|
883
880
|
if (pointIndex == -1) {
|
|
884
881
|
app.readDevices[isDeviceInReadList].children[0].children.push(pointInTree);
|
package/package.json
CHANGED
|
@@ -237,9 +237,13 @@ class Client extends events_1.EventEmitter {
|
|
|
237
237
|
if (!result) return debug('Received invalid deleteObject message');
|
|
238
238
|
this.emit('deleteObject', { address: address, invokeId: invokeId, request: result, srcAddress: srcAddress });
|
|
239
239
|
} else if (service === baEnum.ConfirmedServiceChoice.ACKNOWLEDGE_ALARM) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
try {
|
|
241
|
+
result = baServices.alarmAcknowledge.decode(buffer, offset, length);
|
|
242
|
+
if (!result) return debug('Received invalid alarmAcknowledge message');
|
|
243
|
+
this.emit('alarmAcknowledge', { address: address, invokeId: invokeId, request: result, srcAddress: srcAddress });
|
|
244
|
+
} catch (e) {
|
|
245
|
+
//console.log("Error in alarmAcknowledge: ", e);
|
|
246
|
+
}
|
|
243
247
|
} else if (service === baEnum.ConfirmedServiceChoice.GET_ALARM_SUMMARY) {
|
|
244
248
|
this.emit('getAlarmSummary', { address: address, invokeId: invokeId });
|
|
245
249
|
} else if (service === baEnum.ConfirmedServiceChoice.GET_ENROLLMENT_SUMMARY) {
|