@bitpoolos/edge-bacnet 1.2.2 → 1.2.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/bacnet_client.js +136 -68
- package/bacnet_device.js +61 -0
- package/bacnet_gateway.js +15 -0
- package/bacnet_read.html +0 -9
- package/bacnet_read.js +19 -1
- package/package.json +2 -1
package/bacnet_client.js
CHANGED
|
@@ -80,7 +80,6 @@ class BacnetClient extends EventEmitter {
|
|
|
80
80
|
const queryDevices = new Task('simple task', () => {
|
|
81
81
|
if(!that.pollInProgress) that.queryDevices();
|
|
82
82
|
that.sanitizeDeviceList();
|
|
83
|
-
//that.queryDevicesManually();
|
|
84
83
|
});
|
|
85
84
|
|
|
86
85
|
const queryJob = new SimpleIntervalJob({ seconds: parseInt(that.device_read_schedule), }, queryDevices)
|
|
@@ -199,90 +198,138 @@ class BacnetClient extends EventEmitter {
|
|
|
199
198
|
query(index);
|
|
200
199
|
|
|
201
200
|
function query(index) {
|
|
202
|
-
|
|
201
|
+
that.queryPriorityDevices().then(function() {
|
|
203
202
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
that.
|
|
213
|
-
|
|
203
|
+
let device = that.deviceList[index];
|
|
204
|
+
|
|
205
|
+
if(index < that.deviceList.length) {
|
|
206
|
+
index++;
|
|
207
|
+
|
|
208
|
+
if(typeof device == "object") {
|
|
209
|
+
if(!device.getManualDiscoveryMode()) {
|
|
210
|
+
try {
|
|
211
|
+
that.getDevicePointList(device).then(function() {
|
|
212
|
+
that.removeDeviceFromManualQueue(device);
|
|
213
|
+
that.buildJsonObject(device, null).then(function() {
|
|
214
|
+
query(index);
|
|
215
|
+
}).catch(function(e) {
|
|
216
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
217
|
+
query(index);
|
|
218
|
+
});
|
|
214
219
|
}).catch(function(e) {
|
|
215
220
|
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
221
|
+
that.addDeviceToManualQueue(device);
|
|
216
222
|
query(index);
|
|
217
223
|
});
|
|
218
|
-
}
|
|
219
|
-
that.logOut(
|
|
220
|
-
that.addDeviceToManualQueue(device);
|
|
224
|
+
} catch(e) {
|
|
225
|
+
that.logOut("Error while querying devices: ", e);
|
|
221
226
|
query(index);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
that.logOut("Error while querying devices: ", e);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
225
229
|
query(index);
|
|
226
230
|
}
|
|
227
231
|
} else {
|
|
232
|
+
that.logOut("queryDevices: invalid device found: ", device);
|
|
228
233
|
query(index);
|
|
229
234
|
}
|
|
230
|
-
} else {
|
|
231
|
-
that.logOut("queryDevices: invalid device found: ", device);
|
|
232
|
-
query(index);
|
|
233
|
-
}
|
|
234
|
-
} else if(index == that.deviceList.length) {
|
|
235
|
+
} else if(index == that.deviceList.length) {
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
if(that.manualDiscoverQueue.length > 0) {
|
|
238
|
+
that.queryDevicesManually();
|
|
239
|
+
} else {
|
|
240
|
+
that.pollInProgress = false;
|
|
241
|
+
}
|
|
242
|
+
|
|
240
243
|
}
|
|
241
|
-
|
|
242
|
-
}
|
|
244
|
+
});
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
247
|
|
|
246
248
|
queryDevicesManually() {
|
|
247
249
|
let that = this;
|
|
248
|
-
|
|
249
250
|
let index = 0;
|
|
250
|
-
|
|
251
251
|
query(index);
|
|
252
252
|
|
|
253
253
|
function query(index) {
|
|
254
|
-
|
|
254
|
+
that.queryPriorityDevices().then(function() {
|
|
255
|
+
let device = that.manualDiscoverQueue[index];
|
|
256
|
+
if(index < that.manualDiscoverQueue.length) {
|
|
257
|
+
index++;
|
|
258
|
+
if(typeof device == "object") {
|
|
259
|
+
try {
|
|
260
|
+
if(device.shouldBeInManualMode()) {
|
|
261
|
+
that.getDevicePointListWithoutObjectList(device).then(function() {
|
|
262
|
+
that.buildJsonObject(device, null).then(function() {
|
|
263
|
+
query(index);
|
|
264
|
+
}).catch(function(e) {
|
|
265
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
266
|
+
query(index);
|
|
267
|
+
});
|
|
268
|
+
}).catch(function(e){
|
|
269
|
+
query(index);
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
that.removeDeviceFromManualQueue(device);
|
|
273
|
+
query(index);
|
|
274
|
+
}
|
|
275
|
+
} catch(e) {
|
|
276
|
+
query(index);
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
query(index);
|
|
280
|
+
}
|
|
281
|
+
} else if(index == that.manualDiscoverQueue.length) {
|
|
282
|
+
that.pollInProgress = false;
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
255
287
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
288
|
+
queryPriorityDevices() {
|
|
289
|
+
let that = this;
|
|
290
|
+
return new Promise((resolve, reject) => {
|
|
291
|
+
let priorityDevices = that.getPriorityDevices();
|
|
292
|
+
|
|
293
|
+
if(priorityDevices.length > 0) {
|
|
294
|
+
let index = 0;
|
|
295
|
+
|
|
296
|
+
query(index);
|
|
297
|
+
|
|
298
|
+
function query(index) {
|
|
299
|
+
let device = priorityDevices[index];
|
|
300
|
+
|
|
301
|
+
if(index < priorityDevices.length) {
|
|
302
|
+
index++;
|
|
303
|
+
|
|
304
|
+
if(typeof device == "object" && ((Date.now() - device.getLastPriorityQueueTS()) / 1000) > parseInt(that.device_read_schedule) ) {
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
let points = device.getPriorityQueue();
|
|
308
|
+
that.buildJsonObject(device, points).then(function() {
|
|
309
|
+
device.setLastPriorityQueueTS();
|
|
264
310
|
query(index);
|
|
265
311
|
}).catch(function(e) {
|
|
266
|
-
that.logOut(`
|
|
312
|
+
that.logOut(`queryPriorityDevices error: ${device.getAddress()}`, e);
|
|
267
313
|
query(index);
|
|
268
314
|
});
|
|
269
|
-
|
|
315
|
+
|
|
316
|
+
} catch(e) {
|
|
317
|
+
that.logOut("Error while querying priority devices: ", e);
|
|
270
318
|
query(index);
|
|
271
|
-
}
|
|
319
|
+
}
|
|
320
|
+
|
|
272
321
|
} else {
|
|
273
|
-
that.
|
|
322
|
+
that.logOut("queryPriorityDevices: invalid device found: ", device);
|
|
274
323
|
query(index);
|
|
275
324
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
325
|
+
} else if(index == priorityDevices.length) {
|
|
326
|
+
resolve()
|
|
278
327
|
}
|
|
279
|
-
} else {
|
|
280
|
-
query(index);
|
|
281
328
|
}
|
|
282
|
-
} else if(
|
|
283
|
-
|
|
329
|
+
} else if(priorityDevices.length == 0) {
|
|
330
|
+
resolve()
|
|
284
331
|
}
|
|
285
|
-
}
|
|
332
|
+
});
|
|
286
333
|
}
|
|
287
334
|
|
|
288
335
|
addDeviceToManualQueue(device) {
|
|
@@ -316,7 +363,7 @@ class BacnetClient extends EventEmitter {
|
|
|
316
363
|
let timeoutThreshold = parseInt(that.discover_polling_schedule);
|
|
317
364
|
|
|
318
365
|
that.deviceList.forEach(function(device, index) {
|
|
319
|
-
if(((Date.now() - device.
|
|
366
|
+
if(((Date.now() - device.getLastSeen()) / 1000) > timeoutThreshold && device.getPriorityQueueIsActive() == false) {
|
|
320
367
|
//render device hasnt responded to whoIs for over an hour
|
|
321
368
|
|
|
322
369
|
let renderListIndex = that.renderList.findIndex(ele => ele.deviceId == device.getDeviceId());
|
|
@@ -326,9 +373,7 @@ class BacnetClient extends EventEmitter {
|
|
|
326
373
|
|
|
327
374
|
delete that.networkTree[deviceKey];
|
|
328
375
|
|
|
329
|
-
|
|
330
|
-
that.renderList.splice(renderListIndex, 1);
|
|
331
|
-
}
|
|
376
|
+
that.renderList.splice(renderListIndex, 1);
|
|
332
377
|
|
|
333
378
|
that.deviceList.splice(index, 1);
|
|
334
379
|
}
|
|
@@ -943,6 +988,40 @@ class BacnetClient extends EventEmitter {
|
|
|
943
988
|
});
|
|
944
989
|
}
|
|
945
990
|
|
|
991
|
+
updatePriorityQueue(req) {
|
|
992
|
+
let that = this;
|
|
993
|
+
return new Promise(async function(resolve, reject) {
|
|
994
|
+
try {
|
|
995
|
+
let keys = Object.keys(req.body);
|
|
996
|
+
if(keys.length > 0) {
|
|
997
|
+
keys.forEach(function(key) {
|
|
998
|
+
let device = that.deviceList.find(ele => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
|
|
999
|
+
let points = req.body[key];
|
|
1000
|
+
device.setPriorityQueue(points);
|
|
1001
|
+
});
|
|
1002
|
+
} else if(keys.length == 0) {
|
|
1003
|
+
that.clearPriorityQueues();
|
|
1004
|
+
}
|
|
1005
|
+
resolve(true);
|
|
1006
|
+
} catch(e){
|
|
1007
|
+
reject(e);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
clearPriorityQueues() {
|
|
1013
|
+
let that = this;
|
|
1014
|
+
that.deviceList.forEach(function(device) {
|
|
1015
|
+
device.clearPriorityQueue();
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
getPriorityDevices() {
|
|
1020
|
+
let that = this;
|
|
1021
|
+
let priorityDevices = that.deviceList.filter(device => device.getPriorityQueueIsActive() == true);
|
|
1022
|
+
return priorityDevices;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
946
1025
|
sortDevices(a, b) {
|
|
947
1026
|
if (a.deviceId < b.deviceId) {
|
|
948
1027
|
return -1;
|
|
@@ -1065,21 +1144,10 @@ class BacnetClient extends EventEmitter {
|
|
|
1065
1144
|
});
|
|
1066
1145
|
}
|
|
1067
1146
|
|
|
1068
|
-
|
|
1069
|
-
let that = this;
|
|
1070
|
-
|
|
1071
|
-
that.deviceList.forEach(function(device) {
|
|
1072
|
-
that.buildJsonObject(device).then(function() {
|
|
1073
|
-
}).catch(function(e) {
|
|
1074
|
-
that.logOut(device.getAddress(), e)
|
|
1075
|
-
});
|
|
1076
|
-
});
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
buildJsonObject(device) {
|
|
1147
|
+
buildJsonObject(device, priorityQueue) {
|
|
1080
1148
|
let that = this;
|
|
1081
1149
|
let address = device.address;
|
|
1082
|
-
let pointList = device.getPointsList();
|
|
1150
|
+
let pointList = priorityQueue !== null ? priorityQueue : device.getPointsList();
|
|
1083
1151
|
let requestMutex = new Mutex();
|
|
1084
1152
|
|
|
1085
1153
|
return new Promise(function(resolve, reject) {
|
package/bacnet_device.js
CHANGED
|
@@ -16,6 +16,9 @@ class BacnetDevice {
|
|
|
16
16
|
that.manualDiscoveryMode = config.manualDiscoveryMode;
|
|
17
17
|
that.mDiscoverInstanceRange = config.mDiscoverInstanceRange;
|
|
18
18
|
that.pointListRetryCount = config.pointListRetryCount;
|
|
19
|
+
that.priorityQueueIsActive = config.priorityQueueIsActive;
|
|
20
|
+
that.priorityQueue = config.priorityQueue;
|
|
21
|
+
that.lastPriorityQueueTS = config.lastPriorityQueueTS;
|
|
19
22
|
|
|
20
23
|
} else if(fromImport == false) {
|
|
21
24
|
if(config.net && config.adr) {
|
|
@@ -36,9 +39,67 @@ class BacnetDevice {
|
|
|
36
39
|
that.manualDiscoveryMode = false;
|
|
37
40
|
that.mDiscoverInstanceRange = {start: 0, end: 100};
|
|
38
41
|
that.pointListRetryCount = 0;
|
|
42
|
+
that.priorityQueueIsActive = false;
|
|
43
|
+
that.priorityQueue = [];
|
|
44
|
+
that.lastPriorityQueueTS = null;
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
setLastPriorityQueueTS() {
|
|
49
|
+
this.lastPriorityQueueTS = Date.now();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getLastPriorityQueueTS() {
|
|
53
|
+
return this.lastPriorityQueueTS;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setPriorityQueueIsActive(bool) {
|
|
57
|
+
this.priorityQueueIsActive = bool;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getPriorityQueueIsActive() {
|
|
61
|
+
return this.priorityQueueIsActive;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
updatePriorityQueue(point) {
|
|
65
|
+
let foundIndex = this.priorityQueue.findIndex(ele => ele.value.type == point.value.type && ele.value.instance == point.value.instance);
|
|
66
|
+
if(foundIndex == -1 ) {
|
|
67
|
+
//not found
|
|
68
|
+
this.priorityQueue.push(point);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if(this.priorityQueue.length > 0) {
|
|
72
|
+
this.setPriorityQueueIsActive(true);
|
|
73
|
+
} else if(this.priorityQueue.length == 0) {
|
|
74
|
+
this.setPriorityQueueIsActive(false);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setPriorityQueue(points) {
|
|
79
|
+
let queue = [];
|
|
80
|
+
let keys = Object.keys(points);
|
|
81
|
+
if(keys.length > 0) {
|
|
82
|
+
keys.forEach(function(key) {
|
|
83
|
+
let point = points[key];
|
|
84
|
+
let pointRequestObject = {type: 12, value: point.meta.objectId}
|
|
85
|
+
queue.push(pointRequestObject);
|
|
86
|
+
});
|
|
87
|
+
this.priorityQueue = queue;
|
|
88
|
+
this.setPriorityQueueIsActive(true);
|
|
89
|
+
} else if(keys.length == 0) {
|
|
90
|
+
this.setPriorityQueueIsActive(false);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getPriorityQueue(){
|
|
95
|
+
return this.priorityQueue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
clearPriorityQueue() {
|
|
99
|
+
this.priorityQueue = [];
|
|
100
|
+
this.setPriorityQueueIsActive(false);
|
|
101
|
+
}
|
|
102
|
+
|
|
42
103
|
updateDeviceConfig(config) {
|
|
43
104
|
if(config.address !== "" && config.address !== null && config.address !== "undefined") {
|
|
44
105
|
if(config.net && config.adr) {
|
package/bacnet_gateway.js
CHANGED
|
@@ -264,6 +264,21 @@ module.exports = function (RED) {
|
|
|
264
264
|
}
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
+
//route handler for priority queue
|
|
268
|
+
RED.httpAdmin.post('/bitpool-bacnet-data/priorityQueue', function (req, res) {
|
|
269
|
+
if (!node.bacnetClient) {
|
|
270
|
+
logOut("Issue with the bacnetClient while getting device list: ", node.bacnetClient);
|
|
271
|
+
res.send(false);
|
|
272
|
+
} else {
|
|
273
|
+
node.bacnetClient.updatePriorityQueue(req).then(function (result) {
|
|
274
|
+
res.send(result);
|
|
275
|
+
}).catch(function (error) {
|
|
276
|
+
res.send(error);
|
|
277
|
+
logOut("Error updating priorityQueue: ", error);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
267
282
|
node.on('close', function () {
|
|
268
283
|
//do nothing
|
|
269
284
|
});
|
package/bacnet_read.html
CHANGED
|
@@ -436,21 +436,12 @@
|
|
|
436
436
|
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
437
437
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
438
438
|
if (node.vm.$data.pointsToRead) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
439
|
-
|
|
440
|
-
// if (node.vm.$data.devices && node.vm.$data.devices.length > 0) node.devices = node.vm.$data.devices;
|
|
441
|
-
// if (node.vm.$data.readDevices && node.vm.$data.readDevices.length > 0) node.readDevices = node.vm.$data.readDevices;
|
|
442
|
-
// if (node.vm.$data.pointsToRead && node.vm.$data.pointsToRead.length > 0) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
443
|
-
|
|
444
439
|
},
|
|
445
440
|
oneditcancel: function () {
|
|
446
441
|
let node = this;
|
|
447
442
|
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
448
443
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
449
444
|
if (node.vm.$data.pointsToRead) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
450
|
-
|
|
451
|
-
// if (node.vm.$data.devices && node.vm.$data.devices.length > 0) node.devices = node.vm.$data.devices;
|
|
452
|
-
// if (node.vm.$data.readDevices && node.vm.$data.readDevices.length > 0) node.readDevices = node.vm.$data.readDevices;
|
|
453
|
-
// if (node.vm.$data.pointsToRead && node.vm.$data.pointsToRead.length > 0) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
454
445
|
}
|
|
455
446
|
});
|
|
456
447
|
|
package/bacnet_read.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
module.exports = function (RED) {
|
|
8
|
+
const fetch = require('node-fetch');
|
|
9
|
+
const http = require("http");
|
|
8
10
|
const { ReadCommandConfig } = require('./common');
|
|
9
11
|
const baEnum = require('./resources/node-bacstack-ts/dist/index.js').enum;
|
|
10
12
|
|
|
@@ -49,7 +51,23 @@ module.exports = function (RED) {
|
|
|
49
51
|
return propArr;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
//send point list status for device priority queue
|
|
55
|
+
let headers = {
|
|
56
|
+
'Content-Type' : "application/json"
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const agent = new http.Agent({
|
|
60
|
+
rejectUnauthorized: false
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
fetch('http://localhost:1880/bitpool-bacnet-data/priorityQueue', {method: 'POST', headers: headers, agent: agent, body: JSON.stringify(node.pointsToRead)})
|
|
64
|
+
.then(function(res) {
|
|
65
|
+
//do nothing
|
|
66
|
+
}).catch(function(error) {
|
|
67
|
+
//do nothing
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
|
|
53
71
|
|
|
54
72
|
node.on('input', function(msg) {
|
|
55
73
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitpoolos/edge-bacnet",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "A bacnet gateway for node-red",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@plus4nodered/ts-node-bacnet": "^1.0.0-beta.2",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"cronosjs": "^1.7.1",
|
|
9
9
|
"debug": "^4.1.1",
|
|
10
10
|
"iconv-lite": "^0.5.1",
|
|
11
|
+
"node-fetch": "^2.6.1",
|
|
11
12
|
"toad-scheduler": "^1.6.0",
|
|
12
13
|
"underscore": "^1.10.2",
|
|
13
14
|
"winston": "^3.2.1"
|