@bitpoolos/edge-bacnet 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bacnet_client.js +1 -1
- package/bacnet_gateway.js +4 -4
- package/bacnet_server.js +86 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ A Node-RED node that reads and writes to BACnet devices.
|
|
|
9
9
|
|
|
10
10
|
## Getting Started
|
|
11
11
|
|
|
12
|
-
Use the procedures below to install the Bitpool-Edge BACnet node onto your running instance. Then either use the Node-RED help, or read the [wiki](https://wiki.bitpool.com/
|
|
12
|
+
Use the procedures below to install the Bitpool-Edge BACnet node onto your running instance. Then either use the Node-RED help, or read the [wiki](https://wiki.bitpool.com/bitpool-edge/connectors/bitpool-edge-bacnet) page to get you started on your next new project.
|
|
13
13
|
|
|
14
14
|
*- Examples are available using the Import->Examples->Flows menu.*
|
|
15
15
|
|
|
@@ -50,7 +50,7 @@ $ npm install @bitpoolos/edge-bacnet
|
|
|
50
50
|
|
|
51
51
|
## Contributions
|
|
52
52
|
|
|
53
|
-
This node utilises v0.
|
|
53
|
+
This node utilises v0.2.4 of the node-bacnet package (https://github.com/BiancoRoyal/node-bacstack). None of the functionality here would be possible without the fantastic work done by the contributors of that project.
|
|
54
54
|
|
|
55
55
|
## License
|
|
56
56
|
|
package/bacnet_client.js
CHANGED
package/bacnet_gateway.js
CHANGED
|
@@ -97,7 +97,7 @@ module.exports = function (RED) {
|
|
|
97
97
|
|
|
98
98
|
if(node.bacnetServerEnabled == true && node.bacnetClient) {
|
|
99
99
|
if(node.bacnetServer == null) {
|
|
100
|
-
node.bacnetServer = new BacnetServer(node.bacnetClient, node.deviceId,
|
|
100
|
+
node.bacnetServer = new BacnetServer(node.bacnetClient, node.deviceId, RED.version());
|
|
101
101
|
nodeContext.set("bacnetServer", node.bacnetServer);
|
|
102
102
|
}
|
|
103
103
|
} else if(node.bacnetServerEnabled == false) {
|
|
@@ -151,7 +151,7 @@ module.exports = function (RED) {
|
|
|
151
151
|
|
|
152
152
|
} else {
|
|
153
153
|
// No client information found
|
|
154
|
-
node.status({fill:"red",shape:"dot",text:"Please define client"})
|
|
154
|
+
//node.status({fill:"red",shape:"dot",text:"Please define client"})
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
if(node.nodeName !== "gateway" &&
|
|
@@ -201,7 +201,7 @@ module.exports = function (RED) {
|
|
|
201
201
|
if(!node.bacnetClient) {
|
|
202
202
|
logOut("Issue with the bacnetClient: ", node.bacnetClient);
|
|
203
203
|
//no bacnet client present
|
|
204
|
-
node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
204
|
+
//node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
205
205
|
res.send(false);
|
|
206
206
|
} else {
|
|
207
207
|
node.bacnetClient.getNetworkTreeData().then(function(result) {
|
|
@@ -218,7 +218,7 @@ module.exports = function (RED) {
|
|
|
218
218
|
if(!node.bacnetClient) {
|
|
219
219
|
logOut("Issue with the bacnetClient: ", node.bacnetClient);
|
|
220
220
|
//no bacnet client present
|
|
221
|
-
node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
221
|
+
//node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
222
222
|
res.send(false);
|
|
223
223
|
} else {
|
|
224
224
|
node.bacnetClient.rebuildDataModel().then(function(result) {
|
package/bacnet_server.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const bacnet = require('./resources/node-bacnet/index.js');
|
|
2
|
+
const pjson = require('./package.json');
|
|
2
3
|
const baEnum = bacnet.enum;
|
|
3
4
|
const {Store_Config_Server, Read_Config_Sync_Server } = require('./common');
|
|
4
5
|
|
|
5
6
|
class BacnetServer {
|
|
6
7
|
|
|
7
|
-
constructor(client, deviceId,
|
|
8
|
+
constructor(client, deviceId, nodeRedVersion) {
|
|
8
9
|
let that = this;
|
|
9
10
|
that.bacnetClient = client;
|
|
10
11
|
that.objectIdNumber = 1;
|
|
@@ -15,17 +16,51 @@ class BacnetServer {
|
|
|
15
16
|
];
|
|
16
17
|
that.objectStore = {
|
|
17
18
|
[baEnum.ObjectType.DEVICE]: {
|
|
18
|
-
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{value: {type: baEnum.ObjectType.DEVICE, instance: that.deviceId}, type: 12}],
|
|
19
|
-
[baEnum.PropertyIdentifier.OBJECT_LIST]: that.objectList,
|
|
20
|
-
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{value: 'Bitpool Edge BACnet Gateway', type: 7}],
|
|
21
|
-
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{value: 8, type: 9}],
|
|
22
|
-
[baEnum.PropertyIdentifier.DESCRIPTION]: [{value: 'Bitpool Edge BACnet gateway', type: 7}],
|
|
23
|
-
[baEnum.PropertyIdentifier.SYSTEM_STATUS]: [{value: 0, type: 9}],
|
|
24
|
-
[baEnum.PropertyIdentifier.VENDOR_NAME]: [{value: "Bitpool", type: 7}],
|
|
25
|
-
[baEnum.PropertyIdentifier.VENDOR_IDENTIFIER]: [{value: 1401, type:
|
|
26
|
-
[baEnum.PropertyIdentifier.MODEL_NAME]: [{value: "bitpool-edge", type: 7}],
|
|
27
|
-
[baEnum.PropertyIdentifier.FIRMWARE_REVISION]: [{value: "Node-Red " + that.nodeRedVersion, type: 7}],
|
|
28
|
-
|
|
19
|
+
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{value: {type: baEnum.ObjectType.DEVICE, instance: that.deviceId}, type: 12}],
|
|
20
|
+
[baEnum.PropertyIdentifier.OBJECT_LIST]: that.objectList,
|
|
21
|
+
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{value: 'Bitpool Edge BACnet Gateway', type: 7}],
|
|
22
|
+
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{value: 8, type: 9}],
|
|
23
|
+
[baEnum.PropertyIdentifier.DESCRIPTION]: [{value: 'Bitpool Edge BACnet gateway', type: 7}],
|
|
24
|
+
[baEnum.PropertyIdentifier.SYSTEM_STATUS]: [{value: 0, type: 9}],
|
|
25
|
+
[baEnum.PropertyIdentifier.VENDOR_NAME]: [{value: "Bitpool", type: 7}],
|
|
26
|
+
[baEnum.PropertyIdentifier.VENDOR_IDENTIFIER]: [{value: 1401, type: 2}],
|
|
27
|
+
[baEnum.PropertyIdentifier.MODEL_NAME]: [{value: "bitpool-edge", type: 7}],
|
|
28
|
+
[baEnum.PropertyIdentifier.FIRMWARE_REVISION]: [{value: "Node-Red " + that.nodeRedVersion, type: 7}],
|
|
29
|
+
[baEnum.PropertyIdentifier.PROTOCOL_REVISION]: [{value: 19, type: 2}],
|
|
30
|
+
[baEnum.PropertyIdentifier.PROTOCOL_VERSION]: [{value: 0, type: 2}],
|
|
31
|
+
[baEnum.PropertyIdentifier.APPLICATION_SOFTWARE_VERSION]: [{value: pjson.version, type: 7}],
|
|
32
|
+
[baEnum.PropertyIdentifier.PROTOCOL_SERVICES_SUPPORTED]: [{value: { value: [ 0, 80, 0, 4, 4 ], bitsUsed: 40 }, type: 8}],
|
|
33
|
+
[baEnum.PropertyIdentifier.PROTOCOL_OBJECT_TYPES_SUPPORTED]: [{value: { value: [ 0, 80, 0, 4, 4 ], bitsUsed: 40 }, type: 8}],
|
|
34
|
+
[baEnum.PropertyIdentifier.MAX_APDU_LENGTH_ACCEPTED]: [{value: 1476, type: 2}],
|
|
35
|
+
[baEnum.PropertyIdentifier.SEGMENTATION_SUPPORTED]: [{value: 0, type: 9}],
|
|
36
|
+
[baEnum.PropertyIdentifier.APDU_TIMEOUT]: [{value: that.bacnetClient.config.apduTimeout, type: 2}],
|
|
37
|
+
[baEnum.PropertyIdentifier.NUMBER_OF_APDU_RETRIES]: [{value: 3, type: 2}],
|
|
38
|
+
[baEnum.PropertyIdentifier.DEVICE_ADDRESS_BINDING]: [{value: 0, type: 12}],
|
|
39
|
+
[baEnum.PropertyIdentifier.DATABASE_REVISION]: [{value: 19, type: 2}],
|
|
40
|
+
[baEnum.PropertyIdentifier.PROPERTY_LIST]: [
|
|
41
|
+
{value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
42
|
+
{value: baEnum.PropertyIdentifier.OBJECT_LIST, type: 9 },
|
|
43
|
+
{value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
44
|
+
{value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
45
|
+
{value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
46
|
+
{value: baEnum.PropertyIdentifier.SYSTEM_STATUS, type: 9 },
|
|
47
|
+
{value: baEnum.PropertyIdentifier.VENDOR_NAME, type: 9 },
|
|
48
|
+
{value: baEnum.PropertyIdentifier.VENDOR_IDENTIFIER, type: 9 },
|
|
49
|
+
{value: baEnum.PropertyIdentifier.MODEL_NAME, type: 9 },
|
|
50
|
+
{value: baEnum.PropertyIdentifier.FIRMWARE_REVISION, type: 9 },
|
|
51
|
+
{value: baEnum.PropertyIdentifier.PROTOCOL_REVISION, type: 9 },
|
|
52
|
+
{value: baEnum.PropertyIdentifier.PROTOCOL_VERSION, type: 9 },
|
|
53
|
+
{value: baEnum.PropertyIdentifier.APPLICATION_SOFTWARE_VERSION, type: 9 },
|
|
54
|
+
{value: baEnum.PropertyIdentifier.PROTOCOL_SERVICES_SUPPORTED, type: 9 },
|
|
55
|
+
{value: baEnum.PropertyIdentifier.PROTOCOL_OBJECT_TYPES_SUPPORTED, type: 9 },
|
|
56
|
+
{value: baEnum.PropertyIdentifier.MAX_APDU_LENGTH_ACCEPTED, type: 9 },
|
|
57
|
+
{value: baEnum.PropertyIdentifier.SEGMENTATION_SUPPORTED, type: 9 },
|
|
58
|
+
{value: baEnum.PropertyIdentifier.APDU_TIMEOUT, type: 9 },
|
|
59
|
+
{value: baEnum.PropertyIdentifier.NUMBER_OF_APDU_RETRIES, type: 9 },
|
|
60
|
+
{value: baEnum.PropertyIdentifier.DEVICE_ADDRESS_BINDING, type: 9 },
|
|
61
|
+
{value: baEnum.PropertyIdentifier.DATABASE_REVISION, type: 9 },
|
|
62
|
+
],
|
|
63
|
+
},
|
|
29
64
|
[baEnum.ObjectType.ANALOG_VALUE]: [],
|
|
30
65
|
[baEnum.ObjectType.CHARACTERSTRING_VALUE]: []
|
|
31
66
|
};
|
|
@@ -33,17 +68,20 @@ class BacnetServer {
|
|
|
33
68
|
try {
|
|
34
69
|
let cachedData = JSON.parse(Read_Config_Sync_Server());
|
|
35
70
|
if(typeof cachedData == "object") {
|
|
71
|
+
|
|
36
72
|
if(cachedData.objectList) that.objectList = cachedData.objectList;
|
|
37
|
-
if(cachedData.objectStore)
|
|
73
|
+
if(cachedData.objectStore) {
|
|
74
|
+
that.objectStore[baEnum.ObjectType.ANALOG_VALUE] = cachedData.objectStore[baEnum.ObjectType.ANALOG_VALUE];
|
|
75
|
+
that.objectStore[baEnum.ObjectType.CHARACTERSTRING_VALUE] = cachedData.objectStore[baEnum.ObjectType.CHARACTERSTRING_VALUE];
|
|
76
|
+
}
|
|
38
77
|
}
|
|
39
78
|
} catch (error) {
|
|
40
79
|
//do nothing
|
|
41
80
|
}
|
|
42
81
|
|
|
43
|
-
|
|
44
|
-
|
|
45
82
|
that.bacnetClient.client.on('whoIs', (device) => {
|
|
46
|
-
that.bacnetClient.client.iAmResponse(that.bacnetClient.broadCastAddr, that.deviceId, baEnum.Segmentation.SEGMENTED_BOTH,
|
|
83
|
+
that.bacnetClient.client.iAmResponse(that.bacnetClient.broadCastAddr, that.deviceId, baEnum.Segmentation.SEGMENTED_BOTH, 1401);
|
|
84
|
+
that.lastWhoIsRecived = Date.now();
|
|
47
85
|
});
|
|
48
86
|
|
|
49
87
|
that.bacnetClient.client.on('readPropertyMultiple', (data) => {
|
|
@@ -102,8 +140,11 @@ class BacnetServer {
|
|
|
102
140
|
let propId = data.payload.property.id.toString();
|
|
103
141
|
let responseObj = that.getObject(objectId, propId, objectInstance);
|
|
104
142
|
|
|
143
|
+
if(propId == baEnum.PropertyIdentifier.OBJECT_LIST && ((Date.now() - that.lastWhoIsRecived) / 1000) < 0.7) {
|
|
144
|
+
responseObj = [{value:that.objectList.length, type: 2}];
|
|
145
|
+
}
|
|
105
146
|
if(responseObj !== null && responseObj !== undefined && typeof responseObj !== "undefined") {
|
|
106
|
-
that.bacnetClient.client.readPropertyResponse(data.header.sender.address, data.invokeId, objectId, data.payload.property, responseObj);
|
|
147
|
+
that.bacnetClient.client.readPropertyResponse(data.header.sender.address, data.invokeId, data.payload.objectId, data.payload.property, responseObj);
|
|
107
148
|
} else {
|
|
108
149
|
that.bacnetClient.client.errorResponse(
|
|
109
150
|
data.address,
|
|
@@ -134,7 +175,8 @@ class BacnetServer {
|
|
|
134
175
|
let that = this;
|
|
135
176
|
let objectType = that.getBacnetObjectType(value);
|
|
136
177
|
if(name && objectType) {
|
|
137
|
-
let formattedName = name.replaceAll('.', '');
|
|
178
|
+
let formattedName = name.replaceAll('.', '_');
|
|
179
|
+
formattedName = formattedName.replaceAll('/', '_');
|
|
138
180
|
if(objectType == "number") {
|
|
139
181
|
let foundIndex = that.objectStore[baEnum.ObjectType.ANALOG_VALUE].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
140
182
|
if(foundIndex == -1) {
|
|
@@ -145,14 +187,29 @@ class BacnetServer {
|
|
|
145
187
|
[baEnum.PropertyIdentifier.DESCRIPTION]: [{value: '', type: 7}],
|
|
146
188
|
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{value: {type: baEnum.ObjectType.ANALOG_VALUE, instance: objectId}, type: 12}],
|
|
147
189
|
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{value: value, type: 4}],
|
|
148
|
-
[baEnum.PropertyIdentifier.
|
|
190
|
+
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{value: 0, type: 8}],
|
|
191
|
+
[baEnum.PropertyIdentifier.EVENT_STATE]: [{value: 0, type: 9}],
|
|
192
|
+
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{value: 0, type: 9}],
|
|
193
|
+
[baEnum.PropertyIdentifier.UNITS]: [{value: 95, type: 9}],
|
|
194
|
+
[baEnum.PropertyIdentifier.PRIORITY_ARRAY]: [{value: 0, type: 9}],
|
|
195
|
+
[baEnum.PropertyIdentifier.MAX_PRES_VALUE]: [{value: value, type: 4}],
|
|
196
|
+
[baEnum.PropertyIdentifier.MIN_PRES_VALUE]: [{value: value, type: 4}],
|
|
197
|
+
[baEnum.PropertyIdentifier.RESOLUTION]: [{value: 0, type: 4}],
|
|
198
|
+
[baEnum.PropertyIdentifier.PROPERTY_LIST]:
|
|
149
199
|
[
|
|
150
200
|
{value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
151
201
|
{value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
152
202
|
{value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
153
203
|
{value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
154
|
-
{value: baEnum.PropertyIdentifier.
|
|
155
|
-
{value: baEnum.PropertyIdentifier.
|
|
204
|
+
{value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 },
|
|
205
|
+
{value: baEnum.PropertyIdentifier.STATUS_FLAGS, type: 9 },
|
|
206
|
+
{value: baEnum.PropertyIdentifier.EVENT_STATE, type: 9 },
|
|
207
|
+
{value: baEnum.PropertyIdentifier.OUT_OF_SERVICE, type: 9 },
|
|
208
|
+
{value: baEnum.PropertyIdentifier.UNITS, type: 9 },
|
|
209
|
+
{value: baEnum.PropertyIdentifier.PRIORITY_ARRAY, type: 9 },
|
|
210
|
+
{value: baEnum.PropertyIdentifier.MAX_PRES_VALUE, type: 9 },
|
|
211
|
+
{value: baEnum.PropertyIdentifier.MIN_PRES_VALUE, type: 9 },
|
|
212
|
+
{value: baEnum.PropertyIdentifier.RESOLUTION, type: 9 },
|
|
156
213
|
],
|
|
157
214
|
});
|
|
158
215
|
|
|
@@ -173,15 +230,10 @@ class BacnetServer {
|
|
|
173
230
|
[baEnum.PropertyIdentifier.DESCRIPTION]: [{value: '', type: 7}],
|
|
174
231
|
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{value: {type: baEnum.ObjectType.CHARACTERSTRING_VALUE, instance: objectId}, type: 12}],
|
|
175
232
|
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{value: value, type: 7}],
|
|
176
|
-
[baEnum.PropertyIdentifier.
|
|
177
|
-
[
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
{value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
181
|
-
{value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
182
|
-
{value: baEnum.PropertyIdentifier.PROPERTY_LIST, type: 9 },
|
|
183
|
-
{value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 }
|
|
184
|
-
],
|
|
233
|
+
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{value: 0, type: 8}],
|
|
234
|
+
[baEnum.PropertyIdentifier.EVENT_STATE]: [{value: 0, type: 9}],
|
|
235
|
+
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{value: 0, type: 9}],
|
|
236
|
+
[baEnum.PropertyIdentifier.UNITS]: [{value: 95, type: 9}]
|
|
185
237
|
});
|
|
186
238
|
|
|
187
239
|
that.objectList.push({value: {type: baEnum.ObjectType.CHARACTERSTRING_VALUE, instance: objectId}, type: 12})
|
|
@@ -285,28 +337,13 @@ class BacnetServer {
|
|
|
285
337
|
|
|
286
338
|
clearServerPoints() {
|
|
287
339
|
let that = this;
|
|
288
|
-
|
|
289
|
-
let currentDeviceName = that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_NAME][0].value;
|
|
290
|
-
|
|
340
|
+
|
|
291
341
|
that.objectList = [
|
|
292
342
|
{value: {type: baEnum.ObjectType.DEVICE, instance: that.deviceId}, type: 12}
|
|
293
343
|
];
|
|
294
|
-
that.objectStore =
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
[baEnum.PropertyIdentifier.OBJECT_LIST]: that.objectList, // OBJECT_IDENTIFIER
|
|
298
|
-
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{value: currentDeviceName, type: 7}], // OBJECT_NAME
|
|
299
|
-
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{value: 8, type: 9}], // OBJECT_TYPE
|
|
300
|
-
[baEnum.PropertyIdentifier.DESCRIPTION]: [{value: 'Bitpool Edge BACnet gateway', type: 7}], // DESCRIPTION
|
|
301
|
-
[baEnum.PropertyIdentifier.SYSTEM_STATUS]: [{value: 0, type: 9}], // SYSTEM_STATUS
|
|
302
|
-
[baEnum.PropertyIdentifier.VENDOR_NAME]: [{value: "Bitpool", type: 7}], //VENDOR_NAME
|
|
303
|
-
[baEnum.PropertyIdentifier.VENDOR_IDENTIFIER]: [{value: 1401, type: 7}], //VENDOR_IDENTIFIER
|
|
304
|
-
[baEnum.PropertyIdentifier.MODEL_NAME]: [{value: "bitpool-edge", type: 7}], //MODEL_NAME
|
|
305
|
-
[baEnum.PropertyIdentifier.FIRMWARE_REVISION]: [{value: "Node-Red " + that.nodeRedVersion, type: 7}], //FIRMWARE_REVISION
|
|
306
|
-
},
|
|
307
|
-
[baEnum.ObjectType.ANALOG_VALUE]: [],
|
|
308
|
-
[baEnum.ObjectType.CHARACTERSTRING_VALUE]: []
|
|
309
|
-
};
|
|
344
|
+
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
345
|
+
that.objectStore[baEnum.ObjectType.CHARACTERSTRING_VALUE] = [];
|
|
346
|
+
that.objectStore[baEnum.ObjectType.ANALOG_VALUE] = [];
|
|
310
347
|
|
|
311
348
|
that.objectIdNumber = 1;
|
|
312
349
|
|