@bitpoolos/edge-bacnet 1.2.1 → 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 +137 -64
- 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,84 +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
|
-
|
|
232
|
-
|
|
235
|
+
} else if(index == that.deviceList.length) {
|
|
236
|
+
|
|
237
|
+
if(that.manualDiscoverQueue.length > 0) {
|
|
238
|
+
that.queryDevicesManually();
|
|
239
|
+
} else {
|
|
240
|
+
that.pollInProgress = false;
|
|
241
|
+
}
|
|
242
|
+
|
|
233
243
|
}
|
|
234
|
-
}
|
|
235
|
-
that.queryDevicesManually();
|
|
236
|
-
}
|
|
244
|
+
});
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
queryDevicesManually() {
|
|
241
249
|
let that = this;
|
|
242
|
-
|
|
243
250
|
let index = 0;
|
|
244
|
-
|
|
245
251
|
query(index);
|
|
246
252
|
|
|
247
253
|
function query(index) {
|
|
248
|
-
|
|
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
|
+
}
|
|
249
287
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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();
|
|
258
310
|
query(index);
|
|
259
311
|
}).catch(function(e) {
|
|
260
|
-
that.logOut(`
|
|
312
|
+
that.logOut(`queryPriorityDevices error: ${device.getAddress()}`, e);
|
|
261
313
|
query(index);
|
|
262
314
|
});
|
|
263
|
-
|
|
315
|
+
|
|
316
|
+
} catch(e) {
|
|
317
|
+
that.logOut("Error while querying priority devices: ", e);
|
|
264
318
|
query(index);
|
|
265
|
-
}
|
|
319
|
+
}
|
|
320
|
+
|
|
266
321
|
} else {
|
|
267
|
-
that.
|
|
322
|
+
that.logOut("queryPriorityDevices: invalid device found: ", device);
|
|
268
323
|
query(index);
|
|
269
324
|
}
|
|
270
|
-
}
|
|
271
|
-
|
|
325
|
+
} else if(index == priorityDevices.length) {
|
|
326
|
+
resolve()
|
|
272
327
|
}
|
|
273
|
-
} else {
|
|
274
|
-
query(index);
|
|
275
328
|
}
|
|
276
|
-
} else if(
|
|
277
|
-
|
|
329
|
+
} else if(priorityDevices.length == 0) {
|
|
330
|
+
resolve()
|
|
278
331
|
}
|
|
279
|
-
}
|
|
332
|
+
});
|
|
280
333
|
}
|
|
281
334
|
|
|
282
335
|
addDeviceToManualQueue(device) {
|
|
@@ -310,7 +363,7 @@ class BacnetClient extends EventEmitter {
|
|
|
310
363
|
let timeoutThreshold = parseInt(that.discover_polling_schedule);
|
|
311
364
|
|
|
312
365
|
that.deviceList.forEach(function(device, index) {
|
|
313
|
-
if(((Date.now() - device.
|
|
366
|
+
if(((Date.now() - device.getLastSeen()) / 1000) > timeoutThreshold && device.getPriorityQueueIsActive() == false) {
|
|
314
367
|
//render device hasnt responded to whoIs for over an hour
|
|
315
368
|
|
|
316
369
|
let renderListIndex = that.renderList.findIndex(ele => ele.deviceId == device.getDeviceId());
|
|
@@ -320,9 +373,7 @@ class BacnetClient extends EventEmitter {
|
|
|
320
373
|
|
|
321
374
|
delete that.networkTree[deviceKey];
|
|
322
375
|
|
|
323
|
-
|
|
324
|
-
that.renderList.splice(renderListIndex, 1);
|
|
325
|
-
}
|
|
376
|
+
that.renderList.splice(renderListIndex, 1);
|
|
326
377
|
|
|
327
378
|
that.deviceList.splice(index, 1);
|
|
328
379
|
}
|
|
@@ -385,7 +436,6 @@ class BacnetClient extends EventEmitter {
|
|
|
385
436
|
const queryDevices = new Task('simple task', () => {
|
|
386
437
|
if(!that.pollInProgress) that.queryDevices();
|
|
387
438
|
that.sanitizeDeviceList();
|
|
388
|
-
//that.queryDevicesManually();
|
|
389
439
|
});
|
|
390
440
|
|
|
391
441
|
const queryJob = new SimpleIntervalJob({ seconds: parseInt(config.device_read_schedule), }, queryDevices)
|
|
@@ -938,6 +988,40 @@ class BacnetClient extends EventEmitter {
|
|
|
938
988
|
});
|
|
939
989
|
}
|
|
940
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
|
+
|
|
941
1025
|
sortDevices(a, b) {
|
|
942
1026
|
if (a.deviceId < b.deviceId) {
|
|
943
1027
|
return -1;
|
|
@@ -1060,21 +1144,10 @@ class BacnetClient extends EventEmitter {
|
|
|
1060
1144
|
});
|
|
1061
1145
|
}
|
|
1062
1146
|
|
|
1063
|
-
|
|
1064
|
-
let that = this;
|
|
1065
|
-
|
|
1066
|
-
that.deviceList.forEach(function(device) {
|
|
1067
|
-
that.buildJsonObject(device).then(function() {
|
|
1068
|
-
}).catch(function(e) {
|
|
1069
|
-
that.logOut(device.getAddress(), e)
|
|
1070
|
-
});
|
|
1071
|
-
});
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
buildJsonObject(device) {
|
|
1147
|
+
buildJsonObject(device, priorityQueue) {
|
|
1075
1148
|
let that = this;
|
|
1076
1149
|
let address = device.address;
|
|
1077
|
-
let pointList = device.getPointsList();
|
|
1150
|
+
let pointList = priorityQueue !== null ? priorityQueue : device.getPointsList();
|
|
1078
1151
|
let requestMutex = new Mutex();
|
|
1079
1152
|
|
|
1080
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"
|