@bitpoolos/edge-bacnet 1.4.1 → 1.4.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 +43 -0
- package/README.md +2 -0
- package/bacnet_gateway.js +222 -194
- package/bacnet_read.html +122 -63
- package/bacnet_read.js +49 -6
- package/bacnet_server.js +77 -106
- package/bitpool_inject.html +173 -1
- package/bitpool_inject.js +47 -24
- package/package.json +1 -1
- package/resources/style.css +12 -1
- package/treeBuilder.js +53 -1
package/bacnet_read.html
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
events: { value: true },
|
|
12
12
|
json: { value: true },
|
|
13
13
|
mqtt: { value: false },
|
|
14
|
+
pointJson: { value: false },
|
|
14
15
|
hiddenDeployToggle: { value: false },
|
|
15
16
|
prevHiddenToggleState: { value: false },
|
|
16
17
|
roundDecimal: { value: 2 },
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
object_property_simplePayload: { value: false },
|
|
22
23
|
object_property_simpleWithStatus: { value: false },
|
|
23
24
|
object_property_fullObject: { value: true },
|
|
25
|
+
useDeviceName: { value: true },
|
|
24
26
|
},
|
|
25
27
|
inputs: 1,
|
|
26
28
|
outputs: 1,
|
|
@@ -725,75 +727,21 @@
|
|
|
725
727
|
if (pointName == "deviceName") {
|
|
726
728
|
app.nodeService.setDeviceDisplayName(device, point);
|
|
727
729
|
treeDevice.label = point;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
);
|
|
732
|
-
|
|
733
|
-
if (pointInTree) {
|
|
734
|
-
pointInTree.label = point.displayName;
|
|
735
|
-
|
|
736
|
-
const isDeviceInReadList = app.readDevices
|
|
737
|
-
? app.readDevices.findIndex((ele) => ele.deviceId == treeDevice.deviceId)
|
|
738
|
-
: -1;
|
|
739
|
-
|
|
740
|
-
if (isDeviceInReadList == -1) {
|
|
741
|
-
//no read devices present, add new
|
|
742
|
-
let newReadParent = JSON.parse(JSON.stringify(treeDevice));
|
|
743
|
-
newReadParent.children[0].children = [];
|
|
744
|
-
newReadParent.children[0].children.push(pointInTree);
|
|
745
|
-
if (app.readDevices) {
|
|
746
|
-
app.readDevices.push(newReadParent);
|
|
747
|
-
} else {
|
|
748
|
-
app.readDevices = [newReadParent];
|
|
749
|
-
}
|
|
750
|
-
} else {
|
|
751
|
-
// read device found, add point to existing
|
|
752
|
-
let pointIndex = app.readDevices[isDeviceInReadList].children[0].children.findIndex(
|
|
753
|
-
(ele) => ele.data == point.objectName
|
|
754
|
-
);
|
|
755
|
-
if (pointIndex == -1) {
|
|
756
|
-
app.readDevices[isDeviceInReadList].children[0].children.push(pointInTree);
|
|
757
|
-
} else {
|
|
758
|
-
app.readDevices[isDeviceInReadList].children[0].children[pointIndex] = pointInTree;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
} else {
|
|
764
|
-
//search mstp devices
|
|
765
|
-
let mstpIndex = app.devices[foundIndex].children[1].children.findIndex((ele) => ele.deviceId == id);
|
|
766
|
-
|
|
767
|
-
if (mstpIndex !== -1) {
|
|
768
|
-
let mstpDevice = app.devices[foundIndex].children[1].children[mstpIndex];
|
|
769
|
-
let device = app.deviceList.find((ele) => {
|
|
770
|
-
if (ele.address.address) {
|
|
771
|
-
return ele.address.address == ip && ele.deviceId == id;
|
|
772
|
-
} else {
|
|
773
|
-
return ele.address == ip && ele.deviceId == id;
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
|
-
|
|
777
|
-
for (let pointName in importedDevice) {
|
|
778
|
-
let point = importedDevice[pointName];
|
|
779
|
-
if (pointName == "deviceName") {
|
|
780
|
-
app.nodeService.setDeviceDisplayName(device, point);
|
|
781
|
-
mstpDevice.label = point;
|
|
782
|
-
}
|
|
783
|
-
let pointInTree = mstpDevice.children[0].children.find(
|
|
784
|
-
(ele) => ele.data == pointName && ele.bacnetType == point.meta.objectId.type
|
|
730
|
+
} else {
|
|
731
|
+
let pointInTree = treeDevice.children[0].children.find(
|
|
732
|
+
(ele) => ele.bacnetInstance == point.meta.objectId.instance && ele.bacnetType == point.meta.objectId.type
|
|
785
733
|
);
|
|
786
734
|
|
|
787
735
|
if (pointInTree) {
|
|
788
736
|
pointInTree.label = point.displayName;
|
|
789
737
|
|
|
790
738
|
const isDeviceInReadList = app.readDevices
|
|
791
|
-
? app.readDevices.findIndex((ele) => ele.deviceId ==
|
|
739
|
+
? app.readDevices.findIndex((ele) => ele.deviceId == treeDevice.deviceId)
|
|
792
740
|
: -1;
|
|
793
741
|
|
|
794
742
|
if (isDeviceInReadList == -1) {
|
|
795
743
|
//no read devices present, add new
|
|
796
|
-
let newReadParent = JSON.parse(JSON.stringify(
|
|
744
|
+
let newReadParent = JSON.parse(JSON.stringify(treeDevice));
|
|
797
745
|
newReadParent.children[0].children = [];
|
|
798
746
|
newReadParent.children[0].children.push(pointInTree);
|
|
799
747
|
if (app.readDevices) {
|
|
@@ -814,6 +762,74 @@
|
|
|
814
762
|
}
|
|
815
763
|
}
|
|
816
764
|
}
|
|
765
|
+
}
|
|
766
|
+
} else {
|
|
767
|
+
//search mstp devices
|
|
768
|
+
let mstpIndex = -1;
|
|
769
|
+
let folderIndex = -1;
|
|
770
|
+
|
|
771
|
+
app.devices[foundIndex].children.forEach(function (child, index) {
|
|
772
|
+
let temporaryIndex = -1;
|
|
773
|
+
if (child.label.includes("MSTP")) {
|
|
774
|
+
temporaryIndex = child.children.findIndex((ele) => ele.deviceId == id);
|
|
775
|
+
}
|
|
776
|
+
if (temporaryIndex !== -1) {
|
|
777
|
+
mstpIndex = temporaryIndex;
|
|
778
|
+
folderIndex = index;
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
if (mstpIndex !== -1 && folderIndex !== -1) {
|
|
783
|
+
let mstpDevice = app.devices[foundIndex].children[folderIndex].children[mstpIndex];
|
|
784
|
+
let device = app.deviceList.find((ele) => {
|
|
785
|
+
if (ele.address.address) {
|
|
786
|
+
return ele.address.address == ip && ele.deviceId == id;
|
|
787
|
+
} else {
|
|
788
|
+
return ele.address == ip && ele.deviceId == id;
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
for (let pointName in importedDevice) {
|
|
793
|
+
let point = importedDevice[pointName];
|
|
794
|
+
if (pointName == "deviceName") {
|
|
795
|
+
app.nodeService.setDeviceDisplayName(device, point);
|
|
796
|
+
mstpDevice.label = point;
|
|
797
|
+
} else {
|
|
798
|
+
let pointInTree = mstpDevice.children[0].children.find(
|
|
799
|
+
(ele) => ele.bacnetInstance == point.meta.objectId.instance && ele.bacnetType == point.meta.objectId.type
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
if (pointInTree) {
|
|
803
|
+
pointInTree.label = point.displayName;
|
|
804
|
+
|
|
805
|
+
const isDeviceInReadList = app.readDevices
|
|
806
|
+
? app.readDevices.findIndex((ele) => ele.deviceId == mstpDevice.deviceId)
|
|
807
|
+
: -1;
|
|
808
|
+
|
|
809
|
+
if (isDeviceInReadList == -1) {
|
|
810
|
+
//no read devices present, add new
|
|
811
|
+
let newReadParent = JSON.parse(JSON.stringify(mstpDevice));
|
|
812
|
+
newReadParent.children[0].children = [];
|
|
813
|
+
newReadParent.children[0].children.push(pointInTree);
|
|
814
|
+
if (app.readDevices) {
|
|
815
|
+
app.readDevices.push(newReadParent);
|
|
816
|
+
} else {
|
|
817
|
+
app.readDevices = [newReadParent];
|
|
818
|
+
}
|
|
819
|
+
} else {
|
|
820
|
+
// read device found, add point to existing
|
|
821
|
+
let pointIndex = app.readDevices[isDeviceInReadList].children[0].children.findIndex(
|
|
822
|
+
(ele) => ele.data == point.objectName
|
|
823
|
+
);
|
|
824
|
+
if (pointIndex == -1) {
|
|
825
|
+
app.readDevices[isDeviceInReadList].children[0].children.push(pointInTree);
|
|
826
|
+
} else {
|
|
827
|
+
app.readDevices[isDeviceInReadList].children[0].children[pointIndex] = pointInTree;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
817
833
|
} else {
|
|
818
834
|
// not part of device list at all, notify user
|
|
819
835
|
}
|
|
@@ -823,6 +839,9 @@
|
|
|
823
839
|
|
|
824
840
|
app.$forceUpdate();
|
|
825
841
|
},
|
|
842
|
+
refreshReadListTree() {
|
|
843
|
+
this.addToReadDevices(this.pointsToRead);
|
|
844
|
+
},
|
|
826
845
|
calculateMstpCount(slotProps) {
|
|
827
846
|
let count = 0;
|
|
828
847
|
slotProps.node.children.forEach(function (child) {
|
|
@@ -876,6 +895,10 @@
|
|
|
876
895
|
document.getElementById("node-input-json").onclick = handleMsgTypeClick;
|
|
877
896
|
document.getElementById("node-input-mqtt").checked = node.mqtt;
|
|
878
897
|
document.getElementById("node-input-mqtt").onclick = handleMsgTypeClick;
|
|
898
|
+
document.getElementById("node-input-pointJson").checked = node.pointJson;
|
|
899
|
+
document.getElementById("node-input-pointJson").onclick = handleMsgTypeClick;
|
|
900
|
+
|
|
901
|
+
document.getElementById("node-input-useDeviceName").checked = node.useDeviceName;
|
|
879
902
|
|
|
880
903
|
var menu = document.querySelector(".context-menu");
|
|
881
904
|
window.addEventListener("click", (event) => {
|
|
@@ -904,10 +927,16 @@
|
|
|
904
927
|
|
|
905
928
|
function handleMsgTypeClick() {
|
|
906
929
|
if (this.id == "node-input-json") {
|
|
907
|
-
document.getElementById("node-input-mqtt").checked =
|
|
930
|
+
document.getElementById("node-input-mqtt").checked = false;
|
|
931
|
+
document.getElementById("node-input-pointJson").checked = false;
|
|
908
932
|
}
|
|
909
933
|
if (this.id == "node-input-mqtt") {
|
|
910
|
-
document.getElementById("node-input-json").checked =
|
|
934
|
+
document.getElementById("node-input-json").checked = false;
|
|
935
|
+
document.getElementById("node-input-pointJson").checked = false;
|
|
936
|
+
}
|
|
937
|
+
if (this.id == "node-input-pointJson") {
|
|
938
|
+
document.getElementById("node-input-json").checked = false;
|
|
939
|
+
document.getElementById("node-input-mqtt").checked = false;
|
|
911
940
|
}
|
|
912
941
|
}
|
|
913
942
|
|
|
@@ -1195,8 +1224,11 @@
|
|
|
1195
1224
|
<input type="file" id="readlist-file-upload" accept="application/JSON" class="inputStyle" style="display: none;" />
|
|
1196
1225
|
|
|
1197
1226
|
<button @click="removeAllDevices()" class="removeAllDevicesButton" title="Remove all devices">
|
|
1198
|
-
<
|
|
1199
|
-
|
|
1227
|
+
<a style="color: #ff0000;">Remove All Devices</a>
|
|
1228
|
+
</button>
|
|
1229
|
+
|
|
1230
|
+
<button @click="refreshReadListTree()" class="refreshReadListButton" title="Refresh tree">
|
|
1231
|
+
<i class="pi pi-refresh" style="color: #00AEEF;"> </i>
|
|
1200
1232
|
</button>
|
|
1201
1233
|
</div>
|
|
1202
1234
|
|
|
@@ -1312,9 +1344,36 @@
|
|
|
1312
1344
|
>Individual msgs</label
|
|
1313
1345
|
>
|
|
1314
1346
|
</div>
|
|
1347
|
+
<div style="display: flex; flex-direction: row; align-items: flex-start;">
|
|
1348
|
+
<input
|
|
1349
|
+
class="checkbox-round"
|
|
1350
|
+
type="checkbox"
|
|
1351
|
+
id="node-input-pointJson"
|
|
1352
|
+
style="width: 13px; margin-left: 5px;" /><label
|
|
1353
|
+
for="node-input-pointJson"
|
|
1354
|
+
style="padding-left: 20px; width: fit-content;"
|
|
1355
|
+
>Individual JSON</label
|
|
1356
|
+
>
|
|
1357
|
+
</div>
|
|
1315
1358
|
</div>
|
|
1316
1359
|
</div>
|
|
1317
1360
|
|
|
1361
|
+
<hr />
|
|
1362
|
+
|
|
1363
|
+
<div class="objectPropertiesLabel" style="margin-top: 20px; margin-bottom: 20px;">
|
|
1364
|
+
<label
|
|
1365
|
+
for="node-input-useDeviceName"
|
|
1366
|
+
style="width: auto; align-items: start;"
|
|
1367
|
+
class="objectPropertiesLabel">
|
|
1368
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.useDeviceName"></span>
|
|
1369
|
+
<input
|
|
1370
|
+
class=" objectProp"
|
|
1371
|
+
type="checkbox"
|
|
1372
|
+
id="node-input-useDeviceName" />
|
|
1373
|
+
<a style="white-space: nowrap; padding-left: 20px;">Use device name in topic</a>
|
|
1374
|
+
</label>
|
|
1375
|
+
</div>
|
|
1376
|
+
|
|
1318
1377
|
<div class="form-row">
|
|
1319
1378
|
<label for="node-input-roundDecimal"> Decimal place precision </label>
|
|
1320
1379
|
<input type="number" id="node-input-roundDecimal" placeholder="None" />
|
package/bacnet_read.js
CHANGED
|
@@ -15,6 +15,7 @@ module.exports = function (RED) {
|
|
|
15
15
|
|
|
16
16
|
this.json = config.json;
|
|
17
17
|
this.mqtt = config.mqtt;
|
|
18
|
+
this.pointJson = config.pointJson;
|
|
18
19
|
this.roundDecimal = config.roundDecimal;
|
|
19
20
|
this.pointsToRead = config.pointsToRead;
|
|
20
21
|
this.readDevices = config.readDevices;
|
|
@@ -25,7 +26,7 @@ module.exports = function (RED) {
|
|
|
25
26
|
this.object_property_simpleWithStatus = config.object_property_simpleWithStatus;
|
|
26
27
|
this.object_property_fullObject = config.object_property_fullObject;
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
this.useDeviceName = config.useDeviceName;
|
|
29
30
|
|
|
30
31
|
this.object_props = getObjectProps(this);
|
|
31
32
|
|
|
@@ -55,20 +56,62 @@ module.exports = function (RED) {
|
|
|
55
56
|
node.on('input', function (msg) {
|
|
56
57
|
node.status({ fill: "blue", shape: "dot", text: "Reading values" });
|
|
57
58
|
|
|
59
|
+
let object_property_simplePayload = false;
|
|
60
|
+
let object_property_simpleWithStatus = false;
|
|
61
|
+
let object_property_fullObject = false;
|
|
62
|
+
|
|
63
|
+
let jsonType = false;
|
|
64
|
+
let mqttType = false;
|
|
65
|
+
let pointJsonType = false;
|
|
66
|
+
let useDeviceName = false;
|
|
67
|
+
|
|
68
|
+
if (msg.simplePayload) {
|
|
69
|
+
object_property_simplePayload = msg.simplePayload;
|
|
70
|
+
} else if (msg.simpleWithStatus) {
|
|
71
|
+
object_property_simpleWithStatus = msg.simpleWithStatus;
|
|
72
|
+
} else if (msg.fullObject) {
|
|
73
|
+
object_property_fullObject = msg.fullObject;
|
|
74
|
+
} else {
|
|
75
|
+
object_property_simplePayload = node.object_property_simplePayload;
|
|
76
|
+
object_property_simpleWithStatus = node.object_property_simpleWithStatus;
|
|
77
|
+
object_property_fullObject = node.object_property_fullObject;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (msg.json) {
|
|
81
|
+
jsonType = msg.json;
|
|
82
|
+
} else if (msg.mqtt) {
|
|
83
|
+
mqttType = msg.mqtt;
|
|
84
|
+
} else if (msg.pointJson) {
|
|
85
|
+
pointJsonType = msg.pointJson;
|
|
86
|
+
} else {
|
|
87
|
+
jsonType = node.json;
|
|
88
|
+
mqttType = node.mqtt;
|
|
89
|
+
pointJsonType = node.pointJson
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (msg.useDeviceName) {
|
|
93
|
+
useDeviceName = msg.useDeviceName;
|
|
94
|
+
} else {
|
|
95
|
+
useDeviceName = node.useDeviceName;
|
|
96
|
+
}
|
|
97
|
+
|
|
58
98
|
let readConfig = new ReadCommandConfig(node.pointsToRead, node.object_props, node.roundDecimal);
|
|
99
|
+
|
|
59
100
|
let output = {
|
|
60
101
|
type: "Read",
|
|
61
102
|
id: node.id,
|
|
62
103
|
readNodeName: node.nodeName,
|
|
63
104
|
options: readConfig,
|
|
64
105
|
objectPropertyType: {
|
|
65
|
-
simplePayload:
|
|
66
|
-
simpleWithStatus:
|
|
67
|
-
fullObject:
|
|
106
|
+
simplePayload: object_property_simplePayload,
|
|
107
|
+
simpleWithStatus: object_property_simpleWithStatus,
|
|
108
|
+
fullObject: object_property_fullObject
|
|
68
109
|
},
|
|
69
110
|
outputType: {
|
|
70
|
-
json:
|
|
71
|
-
mqtt:
|
|
111
|
+
json: jsonType,
|
|
112
|
+
mqtt: mqttType,
|
|
113
|
+
pointJson: pointJsonType,
|
|
114
|
+
useDeviceName: useDeviceName
|
|
72
115
|
}
|
|
73
116
|
};
|
|
74
117
|
|
package/bacnet_server.js
CHANGED
|
@@ -6,12 +6,12 @@ const { EventEmitter } = require("events");
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Class representing a BACnet Server.
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* This class initializes a BACnet server with specified client, device ID, and Node-Red version.
|
|
11
11
|
* It provides methods to set device name, add objects, retrieve objects, clear server points, clear server point, and get server points.
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* Simulates a BACnet IP device on a regular IP network
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* @constructor
|
|
16
16
|
* @param {Object} client - The BACnet client object.
|
|
17
17
|
* @param {number} deviceId - The ID of the device.
|
|
@@ -248,7 +248,7 @@ class BacnetServer extends EventEmitter {
|
|
|
248
248
|
|
|
249
249
|
/**
|
|
250
250
|
* Set the name of the device.
|
|
251
|
-
*
|
|
251
|
+
*
|
|
252
252
|
* @param {string} nodeName - The new name for the device.
|
|
253
253
|
*/
|
|
254
254
|
setDeviceName(nodeName) {
|
|
@@ -259,116 +259,85 @@ class BacnetServer extends EventEmitter {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
/**
|
|
262
|
-
* Adds a new object to the BacnetServer's object store based on the provided name and
|
|
263
|
-
*
|
|
262
|
+
* Adds a new object to the BacnetServer's object store based on the provided name and payload.
|
|
263
|
+
*
|
|
264
264
|
* @param {string} name - The name of the object to be added.
|
|
265
|
-
* @param {number|boolean|string}
|
|
265
|
+
* @param {number|boolean|string|object} payload - The payload of the object to be added.
|
|
266
266
|
* @returns {void}
|
|
267
267
|
*/
|
|
268
|
-
addObject(name,
|
|
268
|
+
addObject(name, payload) {
|
|
269
269
|
let that = this;
|
|
270
|
-
let objectType = that.getBacnetObjectType(value);
|
|
270
|
+
let objectType = that.getBacnetObjectType(payload.value ?? payload);
|
|
271
271
|
if (name && objectType) {
|
|
272
272
|
let instanceNumber;
|
|
273
273
|
if (name.includes('|')) {
|
|
274
274
|
// split name, assign last part to instanceNumber and the rest to name
|
|
275
275
|
let nameParts = name.split('|');
|
|
276
|
-
instanceNumber = nameParts
|
|
277
|
-
nameParts.pop();
|
|
276
|
+
instanceNumber = nameParts.pop();
|
|
278
277
|
name = nameParts.join('|');
|
|
279
278
|
}
|
|
280
|
-
let formattedName = name.replaceAll('.', '_');
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
293
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
294
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
295
|
-
[baEnum.PropertyIdentifier.UNITS]: [{ value: 95, type: 9 }],
|
|
296
|
-
[baEnum.PropertyIdentifier.PRIORITY_ARRAY]: [{ value: 0, type: 9 }],
|
|
297
|
-
[baEnum.PropertyIdentifier.MAX_PRES_VALUE]: [{ value: value, type: 4 }],
|
|
298
|
-
[baEnum.PropertyIdentifier.MIN_PRES_VALUE]: [{ value: value, type: 4 }],
|
|
299
|
-
[baEnum.PropertyIdentifier.RESOLUTION]: [{ value: 0, type: 4 }],
|
|
300
|
-
[baEnum.PropertyIdentifier.PROPERTY_LIST]:
|
|
301
|
-
[
|
|
302
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
303
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
304
|
-
{ value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
305
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
306
|
-
{ value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 },
|
|
307
|
-
{ value: baEnum.PropertyIdentifier.STATUS_FLAGS, type: 9 },
|
|
308
|
-
{ value: baEnum.PropertyIdentifier.EVENT_STATE, type: 9 },
|
|
309
|
-
{ value: baEnum.PropertyIdentifier.OUT_OF_SERVICE, type: 9 },
|
|
310
|
-
{ value: baEnum.PropertyIdentifier.UNITS, type: 9 },
|
|
311
|
-
{ value: baEnum.PropertyIdentifier.PRIORITY_ARRAY, type: 9 },
|
|
312
|
-
{ value: baEnum.PropertyIdentifier.MAX_PRES_VALUE, type: 9 },
|
|
313
|
-
{ value: baEnum.PropertyIdentifier.MIN_PRES_VALUE, type: 9 },
|
|
314
|
-
{ value: baEnum.PropertyIdentifier.RESOLUTION, type: 9 },
|
|
315
|
-
],
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
that.objectList.push({ value: { type: baEnum.ObjectType.ANALOG_VALUE, instance: objectId }, type: 12 })
|
|
319
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
320
|
-
} else if (foundIndex !== -1) {
|
|
321
|
-
let foundObject = that.objectStore[baEnum.ObjectType.ANALOG_VALUE][foundIndex];
|
|
322
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
323
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
324
|
-
}
|
|
325
|
-
} else if (objectType == "boolean") {
|
|
326
|
-
let foundIndex = that.objectStore[baEnum.ObjectType.BINARY_VALUE].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
327
|
-
if (foundIndex == -1) {
|
|
328
|
-
let objectId = that.getObjectIdentifier(baEnum.ObjectType.BINARY_VALUE);
|
|
329
|
-
that.objectStore[baEnum.ObjectType.BINARY_VALUE].push({
|
|
330
|
-
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{ value: formattedName, type: 7 }],
|
|
331
|
-
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{ value: baEnum.ObjectType.BINARY_VALUE, type: 9 }],
|
|
332
|
-
[baEnum.PropertyIdentifier.DESCRIPTION]: [{ value: '', type: 7 }],
|
|
333
|
-
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{ value: { type: baEnum.ObjectType.BINARY_VALUE, instance: objectId }, type: 12 }],
|
|
334
|
-
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: value, type: 1 }],
|
|
335
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
336
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
337
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
338
|
-
[baEnum.PropertyIdentifier.ACTIVE_TEXT]: [{ value: 'ACTIVE', type: 7 }],
|
|
339
|
-
[baEnum.PropertyIdentifier.INACTIVE_TEXT]: [{ value: 'INACTIVE', type: 7 }],
|
|
340
|
-
});
|
|
279
|
+
let formattedName = name.replaceAll('.', '_').replaceAll('/', '_');
|
|
280
|
+
|
|
281
|
+
const getCommonProperties = (type, valueType) => ({
|
|
282
|
+
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{ value: formattedName, type: 7 }],
|
|
283
|
+
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{ value: type, type: 9 }],
|
|
284
|
+
[baEnum.PropertyIdentifier.DESCRIPTION]: [{ value: payload.description ?? '', type: 7 }],
|
|
285
|
+
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{ value: { type: type, instance: that.getObjectIdentifier(type, instanceNumber) }, type: 12 }],
|
|
286
|
+
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: payload.value ?? payload, type: valueType }],
|
|
287
|
+
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: payload.statusFlags ?? 0, type: 8 }],
|
|
288
|
+
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: payload.eventState ?? 0, type: 9 }],
|
|
289
|
+
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: payload.outOfService ?? 0, type: 9 }],
|
|
290
|
+
});
|
|
341
291
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
} else if (foundIndex !== -1) {
|
|
345
|
-
let foundObject = that.objectStore[baEnum.ObjectType.BINARY_VALUE][foundIndex];
|
|
346
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
347
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
348
|
-
}
|
|
349
|
-
} else if (objectType == "string") {
|
|
350
|
-
let foundIndex = that.objectStore[baEnum.ObjectType.CHARACTERSTRING_VALUE].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
292
|
+
const addObjectToStore = (type, valueType, extraProperties = {}) => {
|
|
293
|
+
let foundIndex = that.objectStore[type].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
351
294
|
if (foundIndex == -1) {
|
|
352
|
-
let
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: value, type: 7 }],
|
|
359
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
360
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
361
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
362
|
-
[baEnum.PropertyIdentifier.UNITS]: [{ value: 95, type: 9 }]
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
that.objectList.push({ value: { type: baEnum.ObjectType.CHARACTERSTRING_VALUE, instance: objectId }, type: 12 })
|
|
295
|
+
let newObject = {
|
|
296
|
+
...getCommonProperties(type, valueType),
|
|
297
|
+
...extraProperties
|
|
298
|
+
};
|
|
299
|
+
that.objectStore[type].push(newObject);
|
|
300
|
+
that.objectList.push({ value: { type: type, instance: newObject[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER][0].value.instance }, type: 12 });
|
|
366
301
|
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
367
|
-
} else
|
|
368
|
-
let foundObject = that.objectStore[
|
|
369
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
302
|
+
} else {
|
|
303
|
+
let foundObject = that.objectStore[type][foundIndex];
|
|
304
|
+
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = payload.value ?? payload;
|
|
370
305
|
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
371
306
|
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
if (objectType === "number") {
|
|
310
|
+
addObjectToStore(baEnum.ObjectType.ANALOG_VALUE, 4, {
|
|
311
|
+
[baEnum.PropertyIdentifier.UNITS]: [{ value: payload.units ?? 95, type: 9 }],
|
|
312
|
+
[baEnum.PropertyIdentifier.MAX_PRES_VALUE]: [{ value: payload.value ?? payload, type: 4 }],
|
|
313
|
+
[baEnum.PropertyIdentifier.MIN_PRES_VALUE]: [{ value: payload.value ?? payload, type: 4 }],
|
|
314
|
+
[baEnum.PropertyIdentifier.RESOLUTION]: [{ value: payload.resolution ?? 0, type: 4 }],
|
|
315
|
+
[baEnum.PropertyIdentifier.PRIORITY_ARRAY]: [{ value: payload.priorityArray ?? 0, type: 9 }],
|
|
316
|
+
[baEnum.PropertyIdentifier.PROPERTY_LIST]: [
|
|
317
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
318
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
319
|
+
{ value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
320
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
321
|
+
{ value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 },
|
|
322
|
+
{ value: baEnum.PropertyIdentifier.STATUS_FLAGS, type: 9 },
|
|
323
|
+
{ value: baEnum.PropertyIdentifier.EVENT_STATE, type: 9 },
|
|
324
|
+
{ value: baEnum.PropertyIdentifier.OUT_OF_SERVICE, type: 9 },
|
|
325
|
+
{ value: baEnum.PropertyIdentifier.UNITS, type: 9 },
|
|
326
|
+
{ value: baEnum.PropertyIdentifier.PRIORITY_ARRAY, type: 9 },
|
|
327
|
+
{ value: baEnum.PropertyIdentifier.MAX_PRES_VALUE, type: 9 },
|
|
328
|
+
{ value: baEnum.PropertyIdentifier.MIN_PRES_VALUE, type: 9 },
|
|
329
|
+
{ value: baEnum.PropertyIdentifier.RESOLUTION, type: 9 },
|
|
330
|
+
]
|
|
331
|
+
});
|
|
332
|
+
} else if (objectType === "boolean") {
|
|
333
|
+
addObjectToStore(baEnum.ObjectType.BINARY_VALUE, 1, {
|
|
334
|
+
[baEnum.PropertyIdentifier.ACTIVE_TEXT]: [{ value: 'ACTIVE', type: 7 }],
|
|
335
|
+
[baEnum.PropertyIdentifier.INACTIVE_TEXT]: [{ value: 'INACTIVE', type: 7 }]
|
|
336
|
+
});
|
|
337
|
+
} else if (objectType === "string") {
|
|
338
|
+
addObjectToStore(baEnum.ObjectType.CHARACTERSTRING_VALUE, 7, {
|
|
339
|
+
[baEnum.PropertyIdentifier.UNITS]: [{ value: payload.units ?? 95, type: 9 }]
|
|
340
|
+
});
|
|
372
341
|
}
|
|
373
342
|
}
|
|
374
343
|
Store_Config_Server(JSON.stringify({ objectList: that.objectList, objectStore: that.objectStore }));
|
|
@@ -376,7 +345,7 @@ class BacnetServer extends EventEmitter {
|
|
|
376
345
|
|
|
377
346
|
/**
|
|
378
347
|
* Retrieves a specific property of an object based on the object ID, property ID, and instance number.
|
|
379
|
-
*
|
|
348
|
+
*
|
|
380
349
|
* @param {number} objectId - The ID of the object type.
|
|
381
350
|
* @param {number} propId - The ID of the property to retrieve.
|
|
382
351
|
* @param {number} instance - The instance number of the object.
|
|
@@ -405,7 +374,7 @@ class BacnetServer extends EventEmitter {
|
|
|
405
374
|
|
|
406
375
|
/**
|
|
407
376
|
* Retrieves a specific property of an object based on the object ID, property ID, and instance number and modify his value.
|
|
408
|
-
*
|
|
377
|
+
*
|
|
409
378
|
* @param {number} objectId - The ID of the object type.
|
|
410
379
|
* @param {number} propId - The ID of the property to retrieve.
|
|
411
380
|
* @param {number} instance - The instance number of the object.
|
|
@@ -436,7 +405,7 @@ class BacnetServer extends EventEmitter {
|
|
|
436
405
|
|
|
437
406
|
/**
|
|
438
407
|
* Retrieves the properties of a specific object instance from the objectStore based on the provided parameters.
|
|
439
|
-
*
|
|
408
|
+
*
|
|
440
409
|
* @param {number} objectId - The type of the object to retrieve.
|
|
441
410
|
* @param {number} propId - The property identifier to retrieve.
|
|
442
411
|
* @param {number} instance - The instance number of the object to retrieve.
|
|
@@ -534,7 +503,7 @@ class BacnetServer extends EventEmitter {
|
|
|
534
503
|
|
|
535
504
|
/**
|
|
536
505
|
* Removes a server point from the objectStore and objectList based on the provided JSON data.
|
|
537
|
-
*
|
|
506
|
+
*
|
|
538
507
|
* @param {Object} json - The JSON data containing information about the server point to be removed.
|
|
539
508
|
* @param {string} json.body.type - The type of the server point ('SV' for CharacterString, 'BV' for BinaryValue, default is AnalogValue).
|
|
540
509
|
* @param {number} json.body.instance - The instance number of the server point to be removed.
|
|
@@ -597,7 +566,7 @@ class BacnetServer extends EventEmitter {
|
|
|
597
566
|
* - name: The name of the object.
|
|
598
567
|
* - type: The type of the object (AV for Analog Value, SV for Character String Value, BV for Binary Value).
|
|
599
568
|
* - instance: The instance number of the object.
|
|
600
|
-
*
|
|
569
|
+
*
|
|
601
570
|
* @returns {Promise<Array>} A promise that resolves with an array of points sorted by instance number.
|
|
602
571
|
* @throws {Error} If an error occurs during the retrieval process.
|
|
603
572
|
*/
|
|
@@ -688,7 +657,7 @@ class BacnetServer extends EventEmitter {
|
|
|
688
657
|
|
|
689
658
|
/**
|
|
690
659
|
* Determines the BACnet object type based on the provided value.
|
|
691
|
-
*
|
|
660
|
+
*
|
|
692
661
|
* @param {any} value - The value to determine the BACnet object type for.
|
|
693
662
|
* @returns {string|null} The BACnet object type as a string ('string', 'number', 'boolean') or null if the type is not recognized.
|
|
694
663
|
*/
|
|
@@ -702,6 +671,8 @@ class BacnetServer extends EventEmitter {
|
|
|
702
671
|
return "number"
|
|
703
672
|
case "boolean":
|
|
704
673
|
return "boolean"
|
|
674
|
+
case "object":
|
|
675
|
+
return "object"
|
|
705
676
|
default:
|
|
706
677
|
return null
|
|
707
678
|
}
|
|
@@ -709,7 +680,7 @@ class BacnetServer extends EventEmitter {
|
|
|
709
680
|
|
|
710
681
|
/**
|
|
711
682
|
* Returns the object identifier for the given type and instance number.
|
|
712
|
-
*
|
|
683
|
+
*
|
|
713
684
|
* @param {string} type - The type of the object.
|
|
714
685
|
* @param {number} instanceNumber - The instance number of the object.
|
|
715
686
|
* @returns {number} The object identifier.
|
|
@@ -728,4 +699,4 @@ class BacnetServer extends EventEmitter {
|
|
|
728
699
|
}
|
|
729
700
|
}
|
|
730
701
|
|
|
731
|
-
module.exports = { BacnetServer };
|
|
702
|
+
module.exports = { BacnetServer };
|