@bitpoolos/edge-bacnet 1.2.7 → 1.2.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/bacnet_client.js CHANGED
@@ -2,1719 +2,1977 @@
2
2
  MIT License Copyright 2021, 2024 - Bitpool Pty Ltd
3
3
  */
4
4
 
5
- const bacnet = require('./resources/node-bacstack-ts/dist/index.js');
5
+ const bacnet = require("./resources/node-bacstack-ts/dist/index.js");
6
6
  const baEnum = bacnet.enum;
7
7
  const bacnetIdMax = baEnum.ASN1_MAX_PROPERTY_ID;
8
- const { EventEmitter } = require('events');
9
- const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync, isNumber } = require('./common');
10
- const { ToadScheduler, SimpleIntervalJob, Task } = require('toad-scheduler');
11
- const { BacnetDevice } = require('./bacnet_device');
12
- const {Mutex} = require("async-mutex");
8
+ const { EventEmitter } = require("events");
9
+ const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync, isNumber } = require("./common");
10
+ const { ToadScheduler, SimpleIntervalJob, Task } = require("toad-scheduler");
11
+ const { BacnetDevice } = require("./bacnet_device");
12
+ const { Mutex } = require("async-mutex");
13
13
 
14
14
  class BacnetClient extends EventEmitter {
15
+ //client constructor
16
+ constructor(config) {
17
+ super();
18
+ let that = this;
19
+ that.config = config;
20
+ that.deviceList = [];
21
+ that.manualDiscoverQueue = [];
22
+ that.networkTree = {};
23
+ that.lastWhoIs = null;
24
+ that.client = null;
25
+ that.lastNetworkPoll = null;
26
+ that.scheduler = new ToadScheduler();
27
+ that.mutex = new Mutex();
28
+ that.manualMutex = new Mutex();
29
+ that.pollInProgress = false;
30
+ that.scanMatrix = [];
31
+ that.renderListCount = 0;
32
+
33
+ try {
34
+ if (that.config.cacheFileEnabled) {
35
+ let cachedData = JSON.parse(Read_Config_Sync());
36
+ if (cachedData && typeof cachedData == "object") {
37
+ if (cachedData.renderList) that.renderList = cachedData.renderList;
38
+ if (cachedData.deviceList) {
39
+ cachedData.deviceList.forEach(function (device) {
40
+ let newBacnetDevice = new BacnetDevice(true, device);
41
+ that.deviceList.push(newBacnetDevice);
42
+ });
43
+ }
44
+ if (cachedData.pointList) that.networkTree = cachedData.pointList;
45
+ if (cachedData.renderListCount) that.renderListCount = cachedData.renderListCount;
46
+ }
47
+ }
48
+
49
+ that.roundDecimal = config.roundDecimal;
50
+ that.apduSize = config.apduSize;
51
+ that.maxSegments = config.maxSegments;
52
+ that.discover_polling_schedule = config.discover_polling_schedule;
53
+ that.deviceId = config.deviceId;
54
+ that.broadCastAddr = config.broadCastAddr;
55
+ that.manual_instance_range_enabled = config.manual_instance_range_enabled;
56
+ that.manual_instance_range_start = config.manual_instance_range_start;
57
+ that.manual_instance_range_end = config.manual_instance_range_end;
58
+ that.device_read_schedule = config.device_read_schedule;
59
+ that.deviceRetryCount = parseInt(config.retries);
60
+ that.sanitise_device_schedule = config.sanitise_device_schedule;
61
+
62
+ that.readPropertyMultipleOptions = {
63
+ maxSegments: 112,
64
+ maxApdu: 5,
65
+ };
66
+
67
+ try {
68
+ that.client = new bacnet.Client({
69
+ apduTimeout: config.apduTimeout,
70
+ interface: config.localIpAdrress,
71
+ port: config.port,
72
+ broadcastAddress: config.broadCastAddr,
73
+ });
74
+ that.setMaxListeners(1);
15
75
 
16
- //client constructor
17
- constructor(config) {
18
- super();
19
- let that = this;
20
- that.deviceList = [];
21
- that.manualDiscoverQueue = [];
22
- that.networkTree = {};
23
- that.lastWhoIs = null;
24
- that.client = null;
25
- that.lastNetworkPoll = null;
26
- that.scheduler = new ToadScheduler();
27
- that.mutex = new Mutex();
28
- that.manualMutex = new Mutex();
29
- that.pollInProgress = false;
30
- that.scanMatrix = [];
31
- that.renderListCount = 0;
32
-
33
- try {
34
-
35
- if(config.cacheFileEnabled) {
36
- let cachedData = JSON.parse(Read_Config_Sync());
37
- if(cachedData && typeof cachedData == "object") {
38
- if(cachedData.renderList) that.renderList = cachedData.renderList;
39
- if(cachedData.deviceList) {
40
- cachedData.deviceList.forEach(function(device) {
41
- let newBacnetDevice = new BacnetDevice(true, device);
42
- that.deviceList.push(newBacnetDevice);
43
- });
44
- }
45
- if(cachedData.pointList) that.networkTree = cachedData.pointList;
46
- if(cachedData.renderListCount) that.renderListCount = cachedData.renderListCount;
47
- }
48
- }
49
-
50
- that.config = config;
51
- that.roundDecimal = config.roundDecimal;
52
- that.apduSize = config.apduSize;
53
- that.maxSegments = config.maxSegments;
54
- that.discover_polling_schedule = config.discover_polling_schedule;
55
- that.deviceId = config.deviceId;
56
- that.broadCastAddr = config.broadCastAddr;
57
- that.manual_instance_range_enabled = config.manual_instance_range_enabled;
58
- that.manual_instance_range_start = config.manual_instance_range_start;
59
- that.manual_instance_range_end = config.manual_instance_range_end;
60
- that.device_read_schedule = config.device_read_schedule;
61
- that.deviceRetryCount = parseInt(config.retries);
62
-
63
- that.readPropertyMultipleOptions = {
64
- maxSegments: 112,
65
- maxApdu: 5
66
- };
67
-
68
- try {
69
-
70
- that.client = new bacnet.Client({ apduTimeout: config.apduTimeout, interface: config.localIpAdrress, port: config.port, broadcastAddress: config.broadCastAddr});
71
- that.setMaxListeners(1);
72
-
73
- const task = new Task('simple task', () => {
74
- that.globalWhoIs();
75
- });
76
+ const task = new Task("simple task", () => {
77
+ that.globalWhoIs();
78
+ });
76
79
 
77
- const job = new SimpleIntervalJob({ seconds: parseInt(that.discover_polling_schedule), }, task)
78
-
79
- that.scheduler.addSimpleIntervalJob(job);
80
+ const job = new SimpleIntervalJob({ seconds: parseInt(that.discover_polling_schedule) }, task);
80
81
 
81
- //query device task
82
- const queryDevices = new Task('simple task', () => {
83
- if(!that.pollInProgress) that.queryDevices();
84
- that.sanitizeDeviceList();
85
- });
82
+ that.scheduler.addSimpleIntervalJob(job);
86
83
 
87
- const queryJob = new SimpleIntervalJob({ seconds: parseInt(that.device_read_schedule), }, queryDevices)
88
-
89
- that.scheduler.addSimpleIntervalJob(queryJob);
84
+ //query device task
85
+ const queryDevices = new Task("simple task", () => {
86
+ if (!that.pollInProgress) that.queryDevices();
87
+ that.sanitizeDeviceList();
88
+ });
90
89
 
91
- //buildNetworkTreeData task
92
- const buildNetworkTree = new Task('simple task', () => {
93
- that.buildNetworkTreeData().then(function() {
94
- that.countDevices();
95
- });
96
- });
90
+ const queryJob = new SimpleIntervalJob({ seconds: parseInt(that.device_read_schedule) }, queryDevices);
97
91
 
98
- const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10, }, buildNetworkTree)
99
-
100
- that.scheduler.addSimpleIntervalJob(buildNetworkTreeJob);
92
+ that.scheduler.addSimpleIntervalJob(queryJob);
101
93
 
102
- that.globalWhoIs();
94
+ //buildNetworkTreeData task
95
+ const buildNetworkTree = new Task("simple task", () => {
96
+ that.buildNetworkTreeData().then(function () {
97
+ that.countDevices();
98
+ });
99
+ });
103
100
 
104
- setTimeout(() => {
105
- that.queryDevices();
106
- that.sanitizeDeviceList();
107
- that.buildNetworkTreeData().then(function() {
108
- that.countDevices();
109
- });
110
- }, "5000")
101
+ const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10 }, buildNetworkTree);
102
+
103
+ that.scheduler.addSimpleIntervalJob(buildNetworkTreeJob);
104
+
105
+ that.globalWhoIs();
106
+
107
+ setTimeout(() => {
108
+ that.queryDevices();
109
+ that.sanitizeDeviceList();
110
+ that.buildNetworkTreeData().then(function () {
111
+ that.countDevices();
112
+ });
113
+ }, "5000");
114
+ } catch (e) {
115
+ that.logOut("Issue initializing client: ", e);
116
+ }
117
+
118
+ //who is callback
119
+ that.client.on("iAm", (device) => {
120
+ //console.log("found iAm device: ", device);
121
+ if (device.address !== that.config.localIpAdrress) {
122
+ if (that.scanMatrix.length > 0) {
123
+ let matrixMap = that.scanMatrix.filter((ele) => device.deviceId >= ele.start && device.deviceId <= ele.end);
124
+ if (matrixMap.length > 0) {
125
+ //only add unique device to array
126
+ let foundIndex = that.deviceList.findIndex((ele) => ele.getDeviceId() == device.deviceId);
127
+ if (foundIndex == -1) {
128
+ let newBacnetDevice = new BacnetDevice(false, device);
129
+ newBacnetDevice.setLastSeen(Date.now());
130
+ that.updateDeviceName(newBacnetDevice);
131
+ if (newBacnetDevice.getIsMstpDevice()) {
132
+ that.addToParentMstpNetwork(newBacnetDevice);
133
+ }
134
+ that.deviceList.push(newBacnetDevice);
135
+ } else if (foundIndex !== -1) {
136
+ that.deviceList[foundIndex].updateDeviceConfig(device);
137
+ that.deviceList[foundIndex].setLastSeen(Date.now());
138
+ that.updateDeviceName(that.deviceList[foundIndex]);
139
+
140
+ if (that.deviceList[foundIndex].getIsMstpDevice()) {
141
+ that.addToParentMstpNetwork(that.deviceList[foundIndex]);
142
+ }
143
+ }
111
144
 
112
- } catch(e) {
113
- that.logOut("Issue initializing client: ", e)
145
+ //emit event for node-red to log
146
+ that.emit("deviceFound", device);
147
+ }
148
+ } else {
149
+ //only add unique device to array
150
+ let foundIndex = that.deviceList.findIndex((ele) => ele.getDeviceId() == device.deviceId);
151
+ if (foundIndex == -1) {
152
+ let newBacnetDevice = new BacnetDevice(false, device);
153
+ newBacnetDevice.setLastSeen(Date.now());
154
+ that.updateDeviceName(newBacnetDevice);
155
+ if (newBacnetDevice.getIsMstpDevice()) {
156
+ that.addToParentMstpNetwork(newBacnetDevice);
157
+ }
158
+ that.deviceList.push(newBacnetDevice);
159
+ } else if (foundIndex !== -1) {
160
+ that.deviceList[foundIndex].updateDeviceConfig(device);
161
+ that.deviceList[foundIndex].setLastSeen(Date.now());
162
+ that.updateDeviceName(that.deviceList[foundIndex]);
163
+
164
+ if (that.deviceList[foundIndex].getIsMstpDevice()) {
165
+ that.addToParentMstpNetwork(that.deviceList[foundIndex]);
166
+ }
114
167
  }
115
168
 
116
- //who is callback
117
- that.client.on('iAm', (device) => {
118
- //console.log("found iAm device: ", device);
119
- if(device.address !== that.config.localIpAdrress) {
120
- if(that.scanMatrix.length > 0) {
121
- let matrixMap = that.scanMatrix.filter(ele => device.deviceId >= ele.start && device.deviceId <= ele.end);
122
- if(matrixMap.length > 0) {
123
- //only add unique device to array
124
- let foundIndex = that.deviceList.findIndex(ele => ele.getDeviceId() == device.deviceId);
125
- if(foundIndex == -1) {
126
- let newBacnetDevice = new BacnetDevice(false, device);
127
- newBacnetDevice.setLastSeen(Date.now());
128
- that.updateDeviceName(newBacnetDevice);
129
- if(newBacnetDevice.getIsMstpDevice()) {
130
- that.addToParentMstpNetwork(newBacnetDevice);
131
- }
132
- that.deviceList.push(newBacnetDevice);
133
-
134
- } else if(foundIndex !== -1) {
135
- that.deviceList[foundIndex].updateDeviceConfig(device);
136
- that.deviceList[foundIndex].setLastSeen(Date.now());
137
- that.updateDeviceName(that.deviceList[foundIndex]);
138
-
139
- if(that.deviceList[foundIndex].getIsMstpDevice()) {
140
- that.addToParentMstpNetwork(that.deviceList[foundIndex]);
141
- }
142
- }
143
-
144
- //emit event for node-red to log
145
- that.emit('deviceFound', device);
146
- }
147
- } else {
148
- //only add unique device to array
149
- let foundIndex = that.deviceList.findIndex(ele => ele.getDeviceId() == device.deviceId);
150
- if(foundIndex == -1) {
151
- let newBacnetDevice = new BacnetDevice(false, device);
152
- newBacnetDevice.setLastSeen(Date.now());
153
- that.updateDeviceName(newBacnetDevice);
154
- if(newBacnetDevice.getIsMstpDevice()) {
155
- that.addToParentMstpNetwork(newBacnetDevice);
156
- }
157
- that.deviceList.push(newBacnetDevice);
158
- } else if(foundIndex !== -1) {
159
- that.deviceList[foundIndex].updateDeviceConfig(device);
160
- that.deviceList[foundIndex].setLastSeen(Date.now());
161
- that.updateDeviceName(that.deviceList[foundIndex]);
162
-
163
- if(that.deviceList[foundIndex].getIsMstpDevice()) {
164
- that.addToParentMstpNetwork(that.deviceList[foundIndex]);
165
- }
169
+ //emit event for node-red to log
170
+ that.emit("deviceFound", device);
171
+ }
172
+ }
173
+ });
174
+ } catch (e) {
175
+ that.logOut("Issue with creating bacnet client, see error: ", e);
176
+ }
166
177
 
167
- }
168
-
169
- //emit event for node-red to log
170
- that.emit('deviceFound', device);
171
- }
172
- }
173
- });
178
+ that.client.on("error", (err) => {
179
+ that.logOut("Error occurred: ", err);
180
+
181
+ if (err.errno == -4090) {
182
+ that.logOut("Invalid Client information or incorrect IP address provided");
183
+ } else if (err.errno == -49) {
184
+ that.logOut("Invalid IP address provided");
185
+ } else {
186
+ that.reinitializeClient(that.config);
187
+ }
188
+ });
189
+ }
190
+
191
+ testFunction(address, type, instance, property) {
192
+ let that = this;
193
+
194
+ console.log("test function ");
195
+
196
+ that.client.readProperty(
197
+ address,
198
+ { type: type, instance: instance },
199
+ property,
200
+ that.readPropertyMultipleOptions,
201
+ (err, value) => {
202
+ if (err) {
203
+ console.log("err: ", err);
204
+ }
174
205
 
175
- } catch(e) {
176
- that.logOut("Issue with creating bacnet client, see error: ", e);
206
+ if (value) {
207
+ console.log("value: ", value);
177
208
  }
209
+ }
210
+ );
211
+ }
212
+
213
+ addToParentMstpNetwork(device) {
214
+ let that = this;
215
+ let address = device.getAddress().address;
216
+ let deviceId = device.getDeviceId();
217
+ let foundParentIndex = that.deviceList.findIndex((ele) => ele.getAddress() == address);
218
+ if (foundParentIndex !== -1) {
219
+ that.deviceList[foundParentIndex].addChildDevice(deviceId);
220
+ device.setParentDeviceId(that.deviceList[foundParentIndex].getDeviceId());
221
+ }
222
+ }
178
223
 
179
- that.client.on('error', (err) => {
180
- that.logOut('Error occurred: ', err);
224
+ logOut(param1, param2) {
225
+ let that = this;
226
+ that.emit("bacnetErrorLog", param1, param2);
227
+ }
181
228
 
182
- if(err.errno == -4090){
183
- that.logOut("Invalid Client information or incorrect IP address provided");
184
- } else if(err.errno == -49) {
185
- that.logOut("Invalid IP address provided");
229
+ rebuildDataModel() {
230
+ let that = this;
231
+ return new Promise((resolve, reject) => {
232
+ try {
233
+ that.deviceList = [];
234
+ that.renderList = [];
235
+ that.networkTree = {};
236
+ that.pollInProgress = false;
237
+ that.renderListCount = 0;
238
+ resolve(true);
239
+ } catch (e) {
240
+ that.logOut("Error clearing BACnet data model: ", e);
241
+ reject(e);
242
+ }
243
+ });
244
+ }
245
+
246
+ queryDevices() {
247
+ let that = this;
248
+
249
+ that.pollInProgress = true;
250
+
251
+ let index = 0;
252
+
253
+ query(index);
254
+
255
+ function query(index) {
256
+ that.queryPriorityDevices().then(function () {
257
+ let device = that.deviceList[index];
258
+
259
+ if (index < that.deviceList.length) {
260
+ index++;
261
+
262
+ if (typeof device == "object") {
263
+ if (!device.getManualDiscoveryMode()) {
264
+ try {
265
+ that
266
+ .getDevicePointList(device)
267
+ .then(function () {
268
+ that.removeDeviceFromManualQueue(device);
269
+ that
270
+ .buildJsonObject(device, null)
271
+ .then(function () {
272
+ query(index);
273
+ })
274
+ .catch(function (e) {
275
+ that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
276
+ query(index);
277
+ });
278
+ })
279
+ .catch(function (e) {
280
+ that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
281
+ device.setManualDiscoveryMode(true);
282
+ that
283
+ .getDevicePointListWithoutObjectList(device)
284
+ .then(function () {
285
+ that
286
+ .buildJsonObject(device, null)
287
+ .then(function () {
288
+ query(index);
289
+ })
290
+ .catch(function (e) {
291
+ that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
292
+ query(index);
293
+ });
294
+ })
295
+ .catch(function (e) {
296
+ query(index);
297
+ });
298
+ });
299
+ } catch (e) {
300
+ that.logOut("Error while querying devices: ", e);
301
+ query(index);
302
+ }
186
303
  } else {
187
- that.reinitializeClient(that.config);
304
+ query(index);
188
305
  }
189
- });
190
- }
191
-
192
- testFunction() {
193
- console.log("test function ");
194
-
195
-
196
-
197
- }
198
-
199
- addToParentMstpNetwork(device) {
200
- let that = this;
201
- let address = device.getAddress().address;
202
- let deviceId = device.getDeviceId();
203
- let foundParentIndex = that.deviceList.findIndex(ele => ele.getAddress() == address);
204
- if(foundParentIndex !== -1) {
205
- that.deviceList[foundParentIndex].addChildDevice(deviceId);
206
- device.setParentDeviceId(that.deviceList[foundParentIndex].getDeviceId());
306
+ } else {
307
+ that.logOut("queryDevices: invalid device found: ", device);
308
+ query(index);
309
+ }
310
+ } else if (index == that.deviceList.length) {
311
+ if (that.manualDiscoverQueue.length > 0) {
312
+ that.queryDevicesManually();
313
+ } else {
314
+ that.pollInProgress = false;
315
+ }
207
316
  }
317
+ });
208
318
  }
209
-
210
- logOut(param1, param2) {
211
- let that = this;
212
- that.emit('bacnetErrorLog', param1, param2);
213
- }
214
-
215
- rebuildDataModel() {
216
- let that = this;
217
- return new Promise((resolve, reject) => {
319
+ }
320
+
321
+ queryDevicesManually() {
322
+ let that = this;
323
+ let index = 0;
324
+ query(index);
325
+
326
+ function query(index) {
327
+ that.queryPriorityDevices().then(function () {
328
+ let device = that.manualDiscoverQueue[index];
329
+ if (index < that.manualDiscoverQueue.length) {
330
+ index++;
331
+ if (typeof device == "object") {
218
332
  try {
219
- that.deviceList = [];
220
- that.renderList = [];
221
- that.networkTree = {};
222
- that.pollInProgress = false;
223
- that.renderListCount = 0;
224
- resolve(true);
225
- } catch(e) {
226
- that.logOut("Error clearing BACnet data model: ", e);
227
- reject(e);
333
+ if (device.shouldBeInManualMode()) {
334
+ that
335
+ .getDevicePointListWithoutObjectList(device)
336
+ .then(function () {
337
+ that
338
+ .buildJsonObject(device, null)
339
+ .then(function () {
340
+ query(index);
341
+ })
342
+ .catch(function (e) {
343
+ that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
344
+ query(index);
345
+ });
346
+ })
347
+ .catch(function (e) {
348
+ query(index);
349
+ });
350
+ } else {
351
+ that.removeDeviceFromManualQueue(device);
352
+ query(index);
353
+ }
354
+ } catch (e) {
355
+ query(index);
228
356
  }
229
- });
357
+ } else {
358
+ query(index);
359
+ }
360
+ } else if (index == that.manualDiscoverQueue.length) {
361
+ that.pollInProgress = false;
362
+ }
363
+ });
230
364
  }
365
+ }
231
366
 
232
- queryDevices() {
233
- let that = this;
234
-
235
- that.pollInProgress = true;
367
+ queryPriorityDevices() {
368
+ let that = this;
369
+ return new Promise((resolve, reject) => {
370
+ let priorityDevices = that.getPriorityDevices();
236
371
 
372
+ if (priorityDevices.length > 0) {
237
373
  let index = 0;
238
-
239
- query(index);
240
374
 
241
- function query(index) {
242
-
243
- that.queryPriorityDevices().then(function() {
244
-
245
- let device = that.deviceList[index];
246
-
247
- if(index < that.deviceList.length) {
248
- index++;
249
-
250
- if(typeof device == "object") {
251
- if(!device.getManualDiscoveryMode()) {
252
- try {
253
- that.getDevicePointList(device).then(function() {
254
- that.removeDeviceFromManualQueue(device);
255
- that.buildJsonObject(device, null).then(function() {
256
- query(index);
257
- }).catch(function(e) {
258
- that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
259
- query(index);
260
- });
261
- }).catch(function(e) {
262
- that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
263
- device.setManualDiscoveryMode(true);
264
- that.getDevicePointListWithoutObjectList(device).then(function() {
265
- that.buildJsonObject(device, null).then(function() {
266
- query(index);
267
- }).catch(function(e) {
268
- that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
269
- query(index);
270
- });
271
- }).catch(function(e){
272
- query(index);
273
- });
274
- });
275
- } catch(e) {
276
- that.logOut("Error while querying devices: ", e);
277
- query(index);
278
- }
279
- } else {
280
- query(index);
281
- }
282
- } else {
283
- that.logOut("queryDevices: invalid device found: ", device);
284
- query(index);
285
- }
286
- } else if(index == that.deviceList.length) {
287
-
288
- if(that.manualDiscoverQueue.length > 0) {
289
- that.queryDevicesManually();
290
- } else {
291
- that.pollInProgress = false;
292
- }
293
- }
294
- });
295
- }
296
-
297
- }
298
-
299
- queryDevicesManually() {
300
- let that = this;
301
- let index = 0;
302
375
  query(index);
303
376
 
304
377
  function query(index) {
305
- that.queryPriorityDevices().then(function() {
306
- let device = that.manualDiscoverQueue[index];
307
- if(index < that.manualDiscoverQueue.length) {
308
- index++;
309
- if(typeof device == "object") {
310
- try {
311
- if(device.shouldBeInManualMode()) {
312
- that.getDevicePointListWithoutObjectList(device).then(function() {
313
- that.buildJsonObject(device, null).then(function() {
314
- query(index);
315
- }).catch(function(e) {
316
- that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
317
- query(index);
318
- });
319
- }).catch(function(e){
320
- query(index);
321
- });
322
- } else {
323
- that.removeDeviceFromManualQueue(device);
324
- query(index);
325
- }
326
- } catch(e) {
327
- query(index);
328
- }
329
- } else {
330
- query(index);
331
- }
332
- } else if(index == that.manualDiscoverQueue.length) {
333
- that.pollInProgress = false;
334
- }
335
- });
336
- }
337
- }
338
-
339
- queryPriorityDevices() {
340
- let that = this;
341
- return new Promise((resolve, reject) => {
342
- let priorityDevices = that.getPriorityDevices();
343
-
344
- if(priorityDevices.length > 0) {
345
- let index = 0;
346
-
378
+ let device = priorityDevices[index];
379
+
380
+ if (index < priorityDevices.length) {
381
+ index++;
382
+
383
+ if (
384
+ typeof device == "object" &&
385
+ (Date.now() - device.getLastPriorityQueueTS()) / 1000 > parseInt(that.device_read_schedule)
386
+ ) {
387
+ try {
388
+ let points = device.getPriorityQueue();
389
+ that
390
+ .buildJsonObject(device, points)
391
+ .then(function () {
392
+ device.setLastPriorityQueueTS();
393
+ query(index);
394
+ })
395
+ .catch(function (e) {
396
+ that.logOut(`queryPriorityDevices error: ${device.getAddress()}`, e);
397
+ query(index);
398
+ });
399
+ } catch (e) {
400
+ that.logOut("Error while querying priority devices: ", e);
347
401
  query(index);
348
-
349
- function query(index) {
350
- let device = priorityDevices[index];
351
-
352
- if(index < priorityDevices.length) {
353
- index++;
354
-
355
- if(typeof device == "object" && ((Date.now() - device.getLastPriorityQueueTS()) / 1000) > parseInt(that.device_read_schedule) ) {
356
-
357
- try {
358
- let points = device.getPriorityQueue();
359
- that.buildJsonObject(device, points).then(function() {
360
- device.setLastPriorityQueueTS();
361
- query(index);
362
- }).catch(function(e) {
363
- that.logOut(`queryPriorityDevices error: ${device.getAddress()}`, e);
364
- query(index);
365
- });
366
-
367
- } catch(e) {
368
- that.logOut("Error while querying priority devices: ", e);
369
- query(index);
370
- }
371
-
372
- } else {
373
- query(index);
374
- }
375
- } else if(index == priorityDevices.length) {
376
- resolve()
377
- }
378
- }
379
- } else if(priorityDevices.length == 0) {
380
- resolve()
381
- }
382
- });
383
- }
384
-
385
- addDeviceToManualQueue(device) {
386
- let that = this;
387
-
388
- if(device.getPointListRetryCount() > that.deviceRetryCount) {
389
- device.setManualDiscoveryMode(true);
390
- let index = that.manualDiscoverQueue.findIndex(ele => ele.getDeviceId() == device.getDeviceId());
391
- if(index == -1) {
392
- that.manualDiscoverQueue.push(device);
402
+ }
403
+ } else {
404
+ query(index);
393
405
  }
394
- } else {
395
- device.incrementPointListRetryCount();
406
+ } else if (index == priorityDevices.length) {
407
+ resolve();
408
+ }
396
409
  }
410
+ } else if (priorityDevices.length == 0) {
411
+ resolve();
412
+ }
413
+ });
414
+ }
415
+
416
+ addDeviceToManualQueue(device) {
417
+ let that = this;
418
+
419
+ if (device.getPointListRetryCount() > that.deviceRetryCount) {
420
+ device.setManualDiscoveryMode(true);
421
+ let index = that.manualDiscoverQueue.findIndex((ele) => ele.getDeviceId() == device.getDeviceId());
422
+ if (index == -1) {
423
+ that.manualDiscoverQueue.push(device);
424
+ }
425
+ } else {
426
+ device.incrementPointListRetryCount();
397
427
  }
398
-
399
- removeDeviceFromManualQueue(device) {
400
- let that = this;
401
- device.setManualDiscoveryMode(false);
402
- device.clearPointListRetryCount()
403
- let index = that.manualDiscoverQueue.findIndex(ele => ele.getDeviceId() == device.getDeviceId());
404
- if(index !== -1) {
405
- that.manualDiscoverQueue.splice(index, 1);
406
- }
428
+ }
429
+
430
+ removeDeviceFromManualQueue(device) {
431
+ let that = this;
432
+ device.setManualDiscoveryMode(false);
433
+ device.clearPointListRetryCount();
434
+ let index = that.manualDiscoverQueue.findIndex((ele) => ele.getDeviceId() == device.getDeviceId());
435
+ if (index !== -1) {
436
+ that.manualDiscoverQueue.splice(index, 1);
407
437
  }
408
-
409
- sanitizeDeviceList() {
410
- let that = this;
411
-
412
- //Discover frequencey x 2
413
- let timeoutThreshold = parseInt(that.discover_polling_schedule) * 2;
414
-
415
- that.deviceList.forEach(function(device, index) {
416
- if(((Date.now() - device.getLastSeen()) / 1000) > timeoutThreshold && device.getPriorityQueueIsActive() == false) {
417
- //render device hasnt responded to whoIs for disover frequency x 2
418
-
419
- let renderListIndex = that.renderList.findIndex(ele => ele.deviceId == device.getDeviceId());
420
-
421
- let ipAddr = typeof device.getAddress() == "object" ? device.getAddress().address : device.getAddress();
422
- let deviceKey = ipAddr + "-" + device.getDeviceId();
423
-
424
- delete that.networkTree[deviceKey];
425
-
426
- that.renderList.splice(renderListIndex, 1);
427
-
428
- that.deviceList.splice(index, 1);
429
- }
430
- });
431
-
432
- }
433
-
434
- updateDeviceName(device) {
435
- let that = this;
436
- that._getDeviceName(device.getAddress(), device.getDeviceId()).then(function(deviceObject) {
437
- if(typeof deviceObject.name == "string") {
438
- device.setDeviceName(deviceObject.name);
439
- device.setPointsList(deviceObject.devicePointEntry);
440
- }
441
- });
438
+ }
439
+
440
+ sanitizeDeviceList() {
441
+ let that = this;
442
+
443
+ //that.sanitise_device_schedule - from gateway node
444
+ let timeoutThreshold = parseInt(that.sanitise_device_schedule);
445
+ that.deviceList.forEach(function (device, index) {
446
+ if ((Date.now() - device.getLastSeen()) / 1000 > timeoutThreshold && device.getPriorityQueueIsActive() == false) {
447
+ //render device hasnt responded to whoIs for sanitise_device_schedule
448
+ let renderListIndex = that.renderList.findIndex((ele) => ele.deviceId == device.getDeviceId());
449
+ let ipAddr = typeof device.getAddress() == "object" ? device.getAddress().address : device.getAddress();
450
+ let deviceKey = ipAddr + "-" + device.getDeviceId();
451
+ delete that.networkTree[deviceKey];
452
+ that.renderList.splice(renderListIndex, 1);
453
+ that.deviceList.splice(index, 1);
454
+ }
455
+ });
456
+ }
457
+
458
+ updateDeviceName(device) {
459
+ let that = this;
460
+ that._getDeviceName(device.getAddress(), device.getDeviceId()).then(function (deviceObject) {
461
+ if (typeof deviceObject.name == "string") {
462
+ device.setDeviceName(deviceObject.name);
463
+ device.setPointsList(deviceObject.devicePointEntry);
464
+ }
465
+ });
466
+ }
467
+
468
+ reinitializeClient(config) {
469
+ let that = this;
470
+
471
+ that.config = config;
472
+ that.roundDecimal = config.roundDecimal;
473
+ that.apduSize = config.apduSize;
474
+ that.maxSegments = config.maxSegments;
475
+ that.discover_polling_schedule = config.discover_polling_schedule;
476
+ that.deviceId = config.deviceId;
477
+ that.broadCastAddr = config.broadCastAddr;
478
+ that.manual_instance_range_enabled = config.manual_instance_range_enabled;
479
+ that.manual_instance_range_start = config.manual_instance_range_start;
480
+ that.manual_instance_range_end = config.manual_instance_range_end;
481
+ that.device_read_schedule = config.device_read_schedule;
482
+
483
+ if (that.scheduler !== null) {
484
+ that.scheduler.stop();
442
485
  }
443
486
 
444
- reinitializeClient(config) {
445
- let that = this;
446
-
447
- that.config = config;
448
- that.roundDecimal = config.roundDecimal;
449
- that.apduSize = config.apduSize;
450
- that.maxSegments = config.maxSegments;
451
- that.discover_polling_schedule = config.discover_polling_schedule;
452
- that.deviceId = config.deviceId;
453
- that.broadCastAddr = config.broadCastAddr;
454
- that.manual_instance_range_enabled = config.manual_instance_range_enabled;
455
- that.manual_instance_range_start = config.manual_instance_range_start;
456
- that.manual_instance_range_end = config.manual_instance_range_end;
457
- that.device_read_schedule = config.device_read_schedule;
458
-
459
- if(that.scheduler !== null) {
460
- that.scheduler.stop();
461
- }
487
+ try {
488
+ that.client._settings.apduTimeout = config.apduTimeout;
489
+ that.client._settings.interface = config.localIpAdrress;
490
+ that.client._settings.port = config.port;
491
+ that.client._settings.broadcastAddress = config.broadCastAddr;
462
492
 
463
- try {
464
- that.client._settings.apduTimeout = config.apduTimeout;
465
- that.client._settings.interface = config.localIpAdrress;
466
- that.client._settings.port = config.port;
467
- that.client._settings.broadcastAddress = config.broadCastAddr;
493
+ that.client._transport.interface = config.localIpAdrress;
494
+ that.client._transport.port = config.port;
495
+ that.client._transport.broadcastAddress = config.broadCastAddr;
468
496
 
469
- that.client._transport.interface = config.localIpAdrress;
470
- that.client._transport.port = config.port;
471
- that.client._transport.broadcastAddress = config.broadCastAddr;
497
+ const task = new Task("simple task", () => {
498
+ that.globalWhoIs();
499
+ });
472
500
 
473
- const task = new Task('simple task', () => {
474
- that.globalWhoIs();
475
- });
501
+ const job = new SimpleIntervalJob({ seconds: parseInt(config.discover_polling_schedule) }, task);
476
502
 
477
- const job = new SimpleIntervalJob({ seconds: parseInt(config.discover_polling_schedule), }, task)
478
-
479
- that.scheduler.addSimpleIntervalJob(job);
503
+ that.scheduler.addSimpleIntervalJob(job);
480
504
 
505
+ // //query device task
506
+ const queryDevices = new Task("simple task", () => {
507
+ if (!that.pollInProgress) that.queryDevices();
508
+ that.sanitizeDeviceList();
509
+ });
481
510
 
482
- // //query device task
483
- const queryDevices = new Task('simple task', () => {
484
- if(!that.pollInProgress) that.queryDevices();
485
- that.sanitizeDeviceList();
486
- });
511
+ const queryJob = new SimpleIntervalJob({ seconds: parseInt(config.device_read_schedule) }, queryDevices);
487
512
 
488
- const queryJob = new SimpleIntervalJob({ seconds: parseInt(config.device_read_schedule), }, queryDevices)
489
-
490
- that.scheduler.addSimpleIntervalJob(queryJob);
513
+ that.scheduler.addSimpleIntervalJob(queryJob);
491
514
 
492
- //buildNetworkTreeData task
493
- const buildNetworkTree = new Task('simple task', () => {
494
- that.buildNetworkTreeData();
495
- that.countDevices();
496
- });
515
+ //buildNetworkTreeData task
516
+ const buildNetworkTree = new Task("simple task", () => {
517
+ that.buildNetworkTreeData();
518
+ that.countDevices();
519
+ });
497
520
 
498
- const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10, }, buildNetworkTree)
499
-
500
- that.scheduler.addSimpleIntervalJob(buildNetworkTreeJob);
521
+ const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 10 }, buildNetworkTree);
501
522
 
502
- } catch(e){
503
- that.logOut("Error reinitializing bacnet client: ", e)
504
- }
505
- };
506
-
507
- getValidPointProperties(point, requestedProps) {
508
- let that = this;
509
- let availableProps = point.propertyList;
510
- let newProps = [];
511
-
512
- try{
513
- requestedProps.forEach(function(prop) {
514
- let foundInAvailable = availableProps.find(ele => ele === prop.id);
515
- if(foundInAvailable) newProps.push(prop);
516
- });
517
- //add object name for use in formatting
518
- newProps.push({id: baEnum.PropertyIdentifier.OBJECT_NAME});
519
- } catch(e){
520
- that.logOut("Issue finding valid object properties, see error: ", e);
521
- }
522
-
523
- return newProps;
523
+ that.scheduler.addSimpleIntervalJob(buildNetworkTreeJob);
524
+ } catch (e) {
525
+ that.logOut("Error reinitializing bacnet client: ", e);
526
+ }
527
+ }
528
+
529
+ getValidPointProperties(point, requestedProps) {
530
+ let that = this;
531
+ let availableProps = point.propertyList;
532
+ let newProps = [];
533
+
534
+ try {
535
+ requestedProps.forEach(function (prop) {
536
+ let foundInAvailable = availableProps.find((ele) => ele === prop.id);
537
+ if (foundInAvailable) newProps.push(prop);
538
+ });
539
+ //add object name for use in formatting
540
+ newProps.push({ id: baEnum.PropertyIdentifier.OBJECT_NAME });
541
+ } catch (e) {
542
+ that.logOut("Issue finding valid object properties, see error: ", e);
524
543
  }
525
544
 
526
- doRead(readConfig, outputType, objectPropertyType, readNodeName) {
527
- let that = this;
528
- that.roundDecimal = readConfig.precision;
529
- let devicesToRead = Object.keys(readConfig.pointsToRead);
530
- try {
531
- let bacnetResults = {};
532
- devicesToRead.forEach(function(key, index) {
533
- let device = that.deviceList.find(ele => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
534
- if(device) {
535
- let deviceName = device.getDeviceName();
536
- let deviceKey = (typeof device.getAddress() == "object") ? device.getAddress().address + "-" + device.getDeviceId() : device.getAddress() + "-" + device.getDeviceId();
537
- let deviceObject = that.networkTree[deviceKey];
538
- if(!bacnetResults[deviceName]) bacnetResults[deviceName] = {};
539
- if(deviceObject) {
540
- for(const pointName in readConfig.pointsToRead[key]) {
541
- let bac_obj = that.getObjectType(readConfig.pointsToRead[key][pointName].meta.objectId.type);
542
- let objectId = pointName + "_" + bac_obj + '_' + readConfig.pointsToRead[key][pointName].meta.objectId.instance;
543
- let point = deviceObject[objectId];
544
-
545
- that.updatePoint(device, point).then(function(result) {
546
- if(isNumber(result.values[0].value)) {
547
- point.presentValue = roundDecimalPlaces(result.values[0].value, that.roundDecimal);
548
- } else {
549
- point.presentValue = result.values[0].value;
550
- }
551
- bacnetResults[deviceName][pointName] = point;
552
- }).catch(function(err) {
553
- //do nothing for now
554
- });
555
-
556
- }
557
- }
558
- }
559
-
560
- setTimeout(() => {
561
- if(index == devicesToRead.length - 1 && Object.keys(readConfig.pointsToRead).length > 0) that.emit('values', bacnetResults, outputType, objectPropertyType, readNodeName);
562
- }, 3000);
563
- });
564
- } catch(e) {
565
- that.logOut("Issue doing read, see error: ", e);
545
+ return newProps;
546
+ }
547
+
548
+ doRead(readConfig, outputType, objectPropertyType, readNodeName) {
549
+ let that = this;
550
+ that.roundDecimal = readConfig.precision;
551
+ let devicesToRead = Object.keys(readConfig.pointsToRead);
552
+ try {
553
+ let bacnetResults = {};
554
+ devicesToRead.forEach(function (key, index) {
555
+ let device = that.deviceList.find((ele) => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
556
+ if (device) {
557
+ let deviceName = device.getDeviceName();
558
+ let deviceKey =
559
+ typeof device.getAddress() == "object"
560
+ ? device.getAddress().address + "-" + device.getDeviceId()
561
+ : device.getAddress() + "-" + device.getDeviceId();
562
+ let deviceObject = that.networkTree[deviceKey];
563
+ if (!bacnetResults[deviceName]) bacnetResults[deviceName] = {};
564
+ if (deviceObject) {
565
+ for (const pointName in readConfig.pointsToRead[key]) {
566
+ let bac_obj = that.getObjectType(readConfig.pointsToRead[key][pointName].meta.objectId.type);
567
+ let objectId =
568
+ pointName + "_" + bac_obj + "_" + readConfig.pointsToRead[key][pointName].meta.objectId.instance;
569
+ let point = deviceObject[objectId];
570
+
571
+ that
572
+ .updatePoint(device, point)
573
+ .then(function (result) {
574
+ if (isNumber(result.values[0].value)) {
575
+ point.presentValue = roundDecimalPlaces(result.values[0].value, that.roundDecimal);
576
+ } else {
577
+ point.presentValue = result.values[0].value;
578
+ }
579
+ bacnetResults[deviceName][pointName] = point;
580
+ })
581
+ .catch(function (err) {
582
+ //do nothing for now
583
+ });
584
+ }
585
+ }
566
586
  }
567
- }
568
587
 
569
- updatePoint(device, point) {
570
- let that = this;
571
- return new Promise((resolve, reject) => {
572
-
573
- that.client.readProperty(
574
- device.getAddress(),
575
- {type: point.objectID.type, instance: point.objectID.instance },
576
- baEnum.PropertyIdentifier.PRESENT_VALUE,
577
- {},
578
- (err, value) => {
579
- if(err) {
580
- //console.log("err ", err);
581
- reject(err);
582
- }
583
-
584
- if(value) {
585
- resolve(value);
586
- }
587
- }
588
- );
589
- });
588
+ setTimeout(() => {
589
+ if (index == devicesToRead.length - 1 && Object.keys(readConfig.pointsToRead).length > 0)
590
+ that.emit("values", bacnetResults, outputType, objectPropertyType, readNodeName);
591
+ }, 3000);
592
+ });
593
+ } catch (e) {
594
+ that.logOut("Issue doing read, see error: ", e);
590
595
  }
591
-
592
- getDeviceAddress(device) {
593
- switch(typeof device.getAddress()) {
594
- case "object":
595
- return device.getAddress().address;
596
- case "string":
597
- return device.getAddress();
598
- default:
599
- return device.getAddress();
596
+ }
597
+
598
+ updatePoint(device, point) {
599
+ let that = this;
600
+ return new Promise((resolve, reject) => {
601
+ that.client.readProperty(
602
+ device.getAddress(),
603
+ { type: point.objectID.type, instance: point.objectID.instance },
604
+ baEnum.PropertyIdentifier.PRESENT_VALUE,
605
+ {},
606
+ (err, value) => {
607
+ if (err) {
608
+ //console.log("err ", err);
609
+ reject(err);
610
+ }
611
+
612
+ if (value) {
613
+ resolve(value);
614
+ }
600
615
  }
616
+ );
617
+ });
618
+ }
619
+
620
+ getDeviceAddress(device) {
621
+ switch (typeof device.getAddress()) {
622
+ case "object":
623
+ return device.getAddress().address;
624
+ case "string":
625
+ return device.getAddress();
626
+ default:
627
+ return device.getAddress();
601
628
  }
602
-
603
- _getDeviceName(address, deviceId) {
604
- let that = this;
605
- return new Promise((resolve, reject) => {
606
- that._readDeviceName(address, deviceId, (err, result) => {
607
- if(result) {
608
- try {
609
- if(result.values[0].value) {
610
- const deviceObject = {
611
- name: result.values[0].value,
612
- devicePointEntry: [{ value: { type: 8, instance: deviceId }, type: 12 }]
613
- };
614
- resolve(deviceObject);
615
- } else {
616
- that.logOut("Issue with deviceName payload, see object: ", object);
617
- }
618
- } catch(e){
619
- that.logOut("Unable to get device name: ", e);
620
- }
621
- }
622
- });
623
- });
624
- }
625
-
626
- getPropertiesForType(props, type) {
627
- let that = this;
628
- let newProps = [];
629
- props.forEach(function(prop) {
630
- //that.logOut(prop);
631
- switch(type){
632
- case 0: //analog-input
633
- newProps.push(prop);
634
- break;
635
- case 1: //analog-output
636
- newProps.push(prop);
637
- break;
638
- case 2: //analog-value
639
- newProps.push(prop);
640
- break;
641
- case 3: //binary-input
642
- newProps.push(prop);
643
- break;
644
- case 4: //binary-output
645
- newProps.push(prop);
646
- break;
647
- case 5: //binary-value
648
- newProps.push(prop);
649
- break;
650
- case 13:
651
- if(prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME) newProps.push(prop);
652
- break;
653
- case 14:
654
- if(prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME) newProps.push(prop);
655
- break;
656
- case 19:
657
- if(prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME) newProps.push(prop);
658
- break;
629
+ }
630
+
631
+ _getDeviceName(address, deviceId) {
632
+ let that = this;
633
+ return new Promise((resolve, reject) => {
634
+ that._readDeviceName(address, deviceId, (err, result) => {
635
+ if (result) {
636
+ try {
637
+ if (result.values[0].value) {
638
+ const deviceObject = {
639
+ name: result.values[0].value,
640
+ devicePointEntry: [{ value: { type: 8, instance: deviceId }, type: 12 }],
641
+ };
642
+ resolve(deviceObject);
643
+ } else {
644
+ that.logOut("Issue with deviceName payload, see object: ", object);
659
645
  }
660
- });
661
- return newProps;
662
- }
646
+ } catch (e) {
647
+ that.logOut("Unable to get device name: ", e);
648
+ }
649
+ }
650
+ });
651
+ });
652
+ }
653
+
654
+ getPropertiesForType(props, type) {
655
+ let that = this;
656
+ let newProps = [];
657
+ props.forEach(function (prop) {
658
+ //that.logOut(prop);
659
+ switch (type) {
660
+ case 0: //analog-input
661
+ newProps.push(prop);
662
+ break;
663
+ case 1: //analog-output
664
+ newProps.push(prop);
665
+ break;
666
+ case 2: //analog-value
667
+ newProps.push(prop);
668
+ break;
669
+ case 3: //binary-input
670
+ newProps.push(prop);
671
+ break;
672
+ case 4: //binary-output
673
+ newProps.push(prop);
674
+ break;
675
+ case 5: //binary-value
676
+ newProps.push(prop);
677
+ break;
678
+ case 13:
679
+ if (prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME)
680
+ newProps.push(prop);
681
+ break;
682
+ case 14:
683
+ if (prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME)
684
+ newProps.push(prop);
685
+ break;
686
+ case 19:
687
+ if (prop.id == baEnum.PropertyIdentifier.PRESENT_VALUE || prop.id == baEnum.PropertyIdentifier.OBJECT_NAME)
688
+ newProps.push(prop);
689
+ break;
690
+ }
691
+ });
692
+ return newProps;
693
+ }
694
+
695
+ getDevicePointList(device) {
696
+ let that = this;
697
+ return new Promise(async function (resolve, reject) {
698
+ try {
699
+ device.setManualDiscoveryMode(false);
700
+ let result = await that.scanDevice(device);
701
+ device.setPointsList(result);
702
+ resolve(result);
703
+ } catch (e) {
704
+ that.logOut(`Error getting point list for ${device.getAddress().toString()} - ${device.getDeviceId()}: `, e);
705
+ reject(e);
706
+ }
707
+ });
708
+ }
709
+
710
+ getDevicePointListWithoutObjectList(device) {
711
+ let that = this;
712
+ return new Promise(function (resolve, reject) {
713
+ try {
714
+ that
715
+ .scanDeviceManually(device)
716
+ .then(function (result) {
717
+ device.setPointsList(result);
718
+ resolve(result);
719
+ })
720
+ .catch(function (error) {
721
+ reject(error);
722
+ });
723
+ } catch (e) {
724
+ that.logOut("Error getting point list: ", e);
725
+ reject(e);
726
+ }
727
+ });
728
+ }
729
+
730
+ scanDeviceManually(device) {
731
+ let that = this;
732
+
733
+ return new Promise(function (resolve, reject) {
734
+ let address = device.getAddress();
735
+ let deviceId = device.getDeviceId();
736
+ let discoveredPointList = [];
737
+
738
+ let index = 1;
739
+
740
+ send(index);
741
+
742
+ function send(index) {
743
+ let readOptions = {
744
+ maxSegments: that.readPropertyMultipleOptions.maxSegments,
745
+ maxApdu: that.readPropertyMultipleOptions.maxApdu,
746
+ arrayIndex: index,
747
+ };
663
748
 
664
- getDevicePointList(device) {
665
- let that = this;
666
- return new Promise(async function(resolve, reject) {
667
- try {
668
- device.setManualDiscoveryMode(false);
669
- let result = await that.scanDevice(device);
670
- device.setPointsList(result);
671
- resolve(result);
672
- } catch(e) {
673
- that.logOut(`Error getting point list for ${device.getAddress().toString()} - ${device.getDeviceId()}: `, e);
674
- reject(e);
749
+ that.client.readProperty(
750
+ address,
751
+ { type: baEnum.ObjectType.DEVICE, instance: deviceId },
752
+ baEnum.PropertyIdentifier.OBJECT_LIST,
753
+ readOptions,
754
+ (err, value) => {
755
+ if (err) {
756
+ resolve(discoveredPointList);
675
757
  }
676
- });
677
- }
678
-
679
- getDevicePointListWithoutObjectList(device) {
680
- let that = this;
681
- return new Promise(function(resolve, reject) {
682
- try {
683
- that.scanDeviceManually(device).then(function(result) {
684
- device.setPointsList(result);
685
- resolve(result);
686
- }).catch(function(error) {
687
- reject(error);
688
- });
689
758
 
690
- } catch(e) {
691
- that.logOut("Error getting point list: ", e);
692
- reject(e);
759
+ if (value) {
760
+ discoveredPointList.push(value.values[0]);
761
+ index++;
762
+ send(index);
693
763
  }
694
-
764
+ }
765
+ );
766
+ }
767
+ });
768
+ }
769
+
770
+ _readObjectWithRequestArray(deviceAddress, requestArray, readOptions) {
771
+ let that = this;
772
+ return new Promise((resolve, reject) => {
773
+ this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
774
+ resolve({
775
+ error: error,
776
+ value: value,
695
777
  });
778
+ });
779
+ });
780
+ }
781
+
782
+ _readDeviceName(deviceAddress, deviceId, callback) {
783
+ let that = this;
784
+ that.client.readProperty(
785
+ deviceAddress,
786
+ { type: baEnum.ObjectType.DEVICE, instance: deviceId },
787
+ baEnum.PropertyIdentifier.OBJECT_NAME,
788
+ that.readPropertyMultipleOptions,
789
+ callback
790
+ );
791
+ }
792
+
793
+ _readObjectList(deviceAddress, deviceId, readOptions, callback) {
794
+ let that = this;
795
+
796
+ try {
797
+ that.client.readProperty(
798
+ deviceAddress,
799
+ { type: baEnum.ObjectType.DEVICE, instance: deviceId },
800
+ baEnum.PropertyIdentifier.OBJECT_LIST,
801
+ readOptions,
802
+ callback
803
+ );
804
+ } catch (e) {
805
+ that.logOut("Error reading object list: ", e);
696
806
  }
807
+ }
808
+
809
+ _readObject(deviceAddress, type, instance, properties, readOptions) {
810
+ let that = this;
811
+ return new Promise((resolve, reject) => {
812
+ const requestArray = [
813
+ {
814
+ objectId: { type: type, instance: instance },
815
+ properties: properties,
816
+ },
817
+ ];
818
+ this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
819
+ resolve({
820
+ error: error,
821
+ value: value,
822
+ });
823
+ });
824
+ });
825
+ }
826
+
827
+ _readObjectFull(device, deviceAddress, type, instance) {
828
+ let that = this;
829
+ const readOptions = {
830
+ maxSegments: that.readPropertyMultipleOptions.maxSegments,
831
+ maxApdu: that.readPropertyMultipleOptions.maxApdu,
832
+ };
697
833
 
698
- scanDeviceManually(device) {
699
- let that = this;
700
-
701
- return new Promise(function(resolve, reject) {
702
-
703
- let address = device.getAddress();
704
- let deviceId = device.getDeviceId();
705
- let discoveredPointList = [];
834
+ const allProperties = [
835
+ { id: baEnum.PropertyIdentifier.PRESENT_VALUE },
836
+ { id: baEnum.PropertyIdentifier.DESCRIPTION },
837
+ { id: baEnum.PropertyIdentifier.UNITS },
838
+ { id: baEnum.PropertyIdentifier.OBJECT_NAME },
839
+ { id: baEnum.PropertyIdentifier.OBJECT_TYPE },
840
+ { id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER },
841
+ { id: baEnum.PropertyIdentifier.SYSTEM_STATUS },
842
+ { id: baEnum.PropertyIdentifier.MODIFICATION_DATE },
843
+ { id: baEnum.PropertyIdentifier.PROGRAM_STATE },
844
+ { id: baEnum.PropertyIdentifier.RECORD_COUNT },
845
+ { id: baEnum.PropertyIdentifier.PRIORITY_ARRAY },
846
+ ];
847
+
848
+ return new Promise((resolve, reject) => {
849
+ that
850
+ ._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }], readOptions)
851
+ .then(function (result) {
852
+ if (result.value) {
853
+ resolve(result);
854
+ }
855
+
856
+ if (result.error) {
857
+ let i = 0;
858
+ readIndividualProperties(i);
859
+ }
860
+ })
861
+ .catch(function (error) {
862
+ let i = 0;
863
+ readIndividualProperties(i);
864
+ });
706
865
 
707
- let index = 1;
866
+ let resultArray = [];
867
+ let errorArray = [];
708
868
 
709
- send(index);
710
-
869
+ function readIndividualProperties(index) {
870
+ const property = allProperties[index];
711
871
 
712
- function send(index) {
872
+ that.client.readProperty(
873
+ deviceAddress,
874
+ { type: type, instance: instance },
875
+ property.id,
876
+ readOptions,
877
+ (err, value) => {
878
+ if (err) {
879
+ errorArray.push(err);
880
+ }
713
881
 
714
- let readOptions = {
715
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
716
- maxApdu: that.readPropertyMultipleOptions.maxApdu,
717
- arrayIndex: index
718
- }
882
+ if (value) {
883
+ const structuredResult = {
884
+ id: value.property.id,
885
+ index: value.property.index,
886
+ value: value.values,
887
+ };
719
888
 
720
- that.client.readProperty(
721
- address,
722
- {type: baEnum.ObjectType.DEVICE, instance: deviceId },
723
- baEnum.PropertyIdentifier.OBJECT_LIST,
724
- readOptions,
725
- (err, value) => {
726
- if(err) {
727
- resolve(discoveredPointList);
728
- }
729
-
730
- if(value) {
731
- discoveredPointList.push(value.values[0]);
732
- index++;
733
- send(index);
734
- }
735
- }
736
- );
889
+ resultArray.push(structuredResult);
737
890
  }
738
- });
739
- }
740
891
 
741
- _readObjectWithRequestArray(deviceAddress, requestArray, readOptions) {
742
- let that = this;
743
- return new Promise((resolve, reject) => {
744
- this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
745
- resolve({
746
- error: error,
747
- value: value
748
- });
749
- });
750
- });
892
+ if (index == allProperties.length - 1) {
893
+ resolve({
894
+ error: null,
895
+ value: {
896
+ values: [
897
+ {
898
+ objectId: {
899
+ type: type,
900
+ instance: instance,
901
+ },
902
+ values: resultArray,
903
+ },
904
+ ],
905
+ },
906
+ });
907
+ } else if (index < allProperties.length - 1) {
908
+ index++;
909
+ readIndividualProperties(index);
910
+ }
911
+ }
912
+ );
913
+ }
914
+ });
915
+ }
916
+
917
+ _readObjectPropList(deviceAddress, type, instance) {
918
+ return this._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.PROPERTY_LIST }]);
919
+ }
920
+
921
+ _readObjectId(deviceAddress, type, instance) {
922
+ return this._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER }]);
923
+ }
924
+
925
+ _readObjectPresentValue(deviceAddress, type, instance) {
926
+ return this._readObject(deviceAddress, type, instance, [
927
+ { id: baEnum.PropertyIdentifier.PRESENT_VALUE },
928
+ { id: baEnum.PropertyIdentifier.OBJECT_NAME },
929
+ ]);
930
+ }
931
+
932
+ doWrite(value, options) {
933
+ let that = this;
934
+ let valuesArray = [];
935
+ options.pointsToWrite.forEach(function (point) {
936
+ let deviceAddress = point.deviceAddress;
937
+ let writeObject = {
938
+ address: deviceAddress,
939
+ objectId: {
940
+ type: point.meta.objectId.type,
941
+ instance: point.meta.objectId.instance,
942
+ },
943
+ values: {
944
+ property: {
945
+ id: 85,
946
+ index: point.meta.arrayIndex,
947
+ },
948
+ value: [
949
+ {
950
+ type: options.appTag,
951
+ value: value,
952
+ },
953
+ ],
954
+ },
955
+ options: {
956
+ maxSegments: that.readPropertyMultipleOptions.maxSegments,
957
+ maxApdu: that.readPropertyMultipleOptions.maxApdu,
958
+ arrayIndex: point.meta.arrayIndex,
959
+ priority: options.priority,
960
+ },
961
+ };
962
+
963
+ valuesArray.push(writeObject);
964
+ });
965
+
966
+ return that._writePropertyMultiple(valuesArray);
967
+ }
968
+
969
+ _writePropertyMultiple(values) {
970
+ let that = this;
971
+ try {
972
+ values.forEach(function (point) {
973
+ that.client.writeProperty(
974
+ point.address,
975
+ point.objectId,
976
+ baEnum.PropertyIdentifier.PRESENT_VALUE,
977
+ point.values.value,
978
+ point.options,
979
+ (err, value) => {
980
+ if (err) {
981
+ that.logOut(err);
982
+ }
983
+ }
984
+ );
985
+ });
986
+ } catch (error) {
987
+ that.logOut(error);
751
988
  }
752
-
753
- _readDeviceName(deviceAddress, deviceId, callback) {
754
- let that = this;
755
- that.client.readProperty(
756
- deviceAddress,
757
- {type: baEnum.ObjectType.DEVICE, instance: deviceId },
758
- baEnum.PropertyIdentifier.OBJECT_NAME,
759
- that.readPropertyMultipleOptions,
760
- callback
761
- );
989
+ }
990
+
991
+ _findValueById(properties, id) {
992
+ const property = properties.find(function (element) {
993
+ return element.id === id;
994
+ });
995
+ if (property && property.value && property.value.length > 0) {
996
+ return property.value[0].value;
997
+ } else {
998
+ return null;
762
999
  }
763
-
764
- _readObjectList(deviceAddress, deviceId, readOptions, callback) {
765
- let that = this;
766
-
767
- try {
768
- that.client.readProperty(
769
- deviceAddress,
770
- {type: baEnum.ObjectType.DEVICE, instance: deviceId },
771
- baEnum.PropertyIdentifier.OBJECT_LIST,
772
- readOptions,
773
- callback
774
- );
775
-
776
- } catch(e) {
777
- that.logOut("Error reading object list: ", e);
1000
+ }
1001
+
1002
+ scanDevice(device) {
1003
+ let that = this;
1004
+ return new Promise((resolve, reject) => {
1005
+ const readOptions = {
1006
+ maxSegments: that.readPropertyMultipleOptions.maxSegments,
1007
+ maxApdu: that.readPropertyMultipleOptions.maxApdu,
1008
+ };
1009
+ this._readObjectList(device.getAddress(), device.getDeviceId(), readOptions, (err, result) => {
1010
+ if (!err) {
1011
+ try {
1012
+ resolve(result.values);
1013
+ } catch (e) {
1014
+ that.logOut("Issue with getting device point list, see error: ", e);
1015
+ }
1016
+ } else {
1017
+ that.logOut(`Error while fetching objects: ${err}`);
1018
+ reject(err);
778
1019
  }
1020
+ });
1021
+ });
1022
+ }
1023
+
1024
+ //closes bacnet client
1025
+ shutDownClient() {
1026
+ let that = this;
1027
+ if (that.client)
1028
+ that.client.close((err, result) => {
1029
+ that.logOut(err, result);
1030
+ });
1031
+ }
1032
+
1033
+ globalWhoIs() {
1034
+ let that = this;
1035
+ if (that.client) {
1036
+ that.client.whoIs({ net: 65535 });
1037
+ } else {
1038
+ that.reinitializeClient(that.config);
779
1039
  }
780
-
781
- _readObject(deviceAddress, type, instance, properties, readOptions) {
782
- let that = this;
783
- return new Promise((resolve, reject) => {
784
- const requestArray = [{
785
- objectId: { type: type, instance: instance },
786
- properties: properties
787
- }];
788
- this.client.readPropertyMultiple(deviceAddress, requestArray, readOptions, (error, value) => {
789
- resolve({
790
- error: error,
791
- value: value
792
- });
793
- });
1040
+ that.lastWhoIs = Date.now();
1041
+ }
1042
+
1043
+ getNetworkTreeData() {
1044
+ let that = this;
1045
+ return new Promise(async function (resolve, reject) {
1046
+ try {
1047
+ const reducedDeviceList = JSON.parse(JSON.stringify(that.deviceList));
1048
+ reducedDeviceList.forEach((device) => {
1049
+ delete device["pointsList"];
794
1050
  });
795
- }
796
-
797
- _readObjectFull(device, deviceAddress, type, instance) {
798
- let that = this;
799
- const readOptions = {
800
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
801
- maxApdu: that.readPropertyMultipleOptions.maxApdu
802
- };
803
-
804
- const allProperties = [
805
- { id: baEnum.PropertyIdentifier.PRESENT_VALUE },
806
- { id: baEnum.PropertyIdentifier.DESCRIPTION },
807
- { id: baEnum.PropertyIdentifier.UNITS },
808
- { id: baEnum.PropertyIdentifier.OBJECT_NAME },
809
- { id: baEnum.PropertyIdentifier.OBJECT_TYPE },
810
- { id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER },
811
- { id: baEnum.PropertyIdentifier.SYSTEM_STATUS },
812
- { id: baEnum.PropertyIdentifier.MODIFICATION_DATE },
813
- { id: baEnum.PropertyIdentifier.PROGRAM_STATE },
814
- { id: baEnum.PropertyIdentifier.RECORD_COUNT }
815
- ];
816
-
817
- return new Promise((resolve, reject) => {
818
- that._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }], readOptions).then(function(result) {
819
-
820
- if(result.value) {
821
- resolve(result);
822
- }
823
-
824
- if(result.error) {
825
- let i = 0;
826
- readIndividualProperties(i);
827
- }
828
-
829
- }).catch(function(error) {
830
- let i = 0;
831
- readIndividualProperties(i);
832
- });
833
-
834
- let resultArray = [];
835
- let errorArray = [];
836
-
837
- function readIndividualProperties(index) {
838
-
839
- const property = allProperties[index];
840
-
841
- that.client.readProperty(
842
- deviceAddress,
843
- {type: type, instance: instance },
844
- property.id,
845
- readOptions,
846
- (err, value) => {
847
- if(err) {
848
- errorArray.push(err);
849
- }
850
-
851
- if(value) {
852
- let formattedResult = {
853
- len: value.len,
854
- objectId: value.objectId,
855
- values: [
856
- {
857
- id: value.property.id,
858
- index: value.property.index,
859
- value: value.values
860
- }
861
- ]
862
- };
863
-
864
- resultArray.push({error: null, value: formattedResult});
865
- }
866
-
867
- if(index == allProperties.length - 1) {
868
- resolve(resultArray);
869
-
870
- // if(resultArray.length > 0) {
871
- // resolve(resultArray);
872
- // } else if(errorArray.length > 0){
873
- // reject(errorArray);
874
- // }
875
- } else if( index < allProperties.length - 1) {
876
- index++;
877
- readIndividualProperties(index);
878
- }
879
- }
880
- );
881
- };
1051
+ resolve({
1052
+ renderList: that.renderList,
1053
+ deviceList: reducedDeviceList,
1054
+ pointList: that.networkTree,
1055
+ pollFrequency: that.discover_polling_schedule,
1056
+ renderListCount: that.renderListCount,
1057
+ });
1058
+ } catch (e) {
1059
+ reject(e);
1060
+ }
1061
+ });
1062
+ }
1063
+
1064
+ getDeviceList() {
1065
+ let that = this;
1066
+ return new Promise(async function (resolve, reject) {
1067
+ try {
1068
+ resolve({ deviceList: that.deviceList });
1069
+ } catch (e) {
1070
+ reject(e);
1071
+ }
1072
+ });
1073
+ }
1074
+
1075
+ updateDeviceList(json) {
1076
+ let that = this;
1077
+ return new Promise(async function (resolve, reject) {
1078
+ try {
1079
+ let deviceL = json.body.deviceList;
1080
+ deviceL.forEach(function (device) {
1081
+ let foundIndex = that.deviceList.findIndex((ele) => ele.getDeviceId() == device.deviceId);
1082
+ if (foundIndex == -1) {
1083
+ let newBacnetDevice = new BacnetDevice(true, device);
1084
+ newBacnetDevice.setLastSeen(Date.now());
1085
+ that.deviceList.push(newBacnetDevice);
1086
+ } else if (foundIndex !== -1) {
1087
+ that.deviceList[foundIndex].updateDeviceConfig(device);
1088
+ that.deviceList[foundIndex].setLastSeen(Date.now());
1089
+ }
882
1090
  });
883
- };
884
-
885
- _readObjectPropList(deviceAddress, type, instance) {
886
-
887
- return this._readObject(deviceAddress, type, instance, [
888
- { id: baEnum.PropertyIdentifier.PROPERTY_LIST }
889
- ]);
890
- };
891
-
892
- _readObjectId(deviceAddress, type, instance) {
893
1091
 
894
- return this._readObject(deviceAddress, type, instance, [
895
- { id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER }
896
- ]);
1092
+ resolve(true);
1093
+ } catch (e) {
1094
+ reject(e);
1095
+ }
1096
+ });
1097
+ }
1098
+
1099
+ updatePriorityQueue(priorityDevices) {
1100
+ let that = this;
1101
+ return new Promise(async function (resolve, reject) {
1102
+ try {
1103
+ let keys = Object.keys(priorityDevices);
1104
+ if (keys.length > 0) {
1105
+ keys.forEach(function (key) {
1106
+ let device = that.deviceList.find((ele) => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
1107
+ let points = priorityDevices[key];
1108
+ if (device) {
1109
+ device.setPriorityQueue(points);
1110
+ }
1111
+ });
1112
+ } else if (keys.length == 0) {
1113
+ that.clearPriorityQueues();
1114
+ }
1115
+ resolve(true);
1116
+ } catch (e) {
1117
+ reject(e);
1118
+ }
1119
+ });
1120
+ }
1121
+
1122
+ clearPriorityQueues() {
1123
+ let that = this;
1124
+ that.deviceList.forEach(function (device) {
1125
+ device.clearPriorityQueue();
1126
+ });
1127
+ }
1128
+
1129
+ getPriorityDevices() {
1130
+ let that = this;
1131
+ let priorityDevices = that.deviceList.filter((device) => device.getPriorityQueueIsActive() == true);
1132
+ return priorityDevices;
1133
+ }
1134
+
1135
+ sortDevices(a, b) {
1136
+ if (a.deviceId < b.deviceId) {
1137
+ return -1;
1138
+ } else if (a.deviceId > b.deviceId) {
1139
+ return 1;
897
1140
  }
898
-
899
- _readObjectPresentValue(deviceAddress, type, instance) {
900
-
901
- return this._readObject(deviceAddress, type, instance, [
902
- { id: baEnum.PropertyIdentifier.PRESENT_VALUE },
903
- { id: baEnum.PropertyIdentifier.OBJECT_NAME}
904
- ]);
1141
+ return 0; // deviceIds are equal
1142
+ }
1143
+
1144
+ sortPoints(a, b) {
1145
+ if (a.bacnetType > b.bacnetType) {
1146
+ return 1;
1147
+ } else if (a.bacnetType < b.bacnetType) {
1148
+ return -1;
1149
+ } else if (a.bacnetType == b.bacnetType) {
1150
+ return 0;
905
1151
  }
906
1152
 
907
- doWrite(value, options){
908
- let that = this;
909
- let valuesArray = [];
910
- options.pointsToWrite.forEach(function(point){
911
- let deviceAddress = point.deviceAddress;
912
- let writeObject = {
913
- address: deviceAddress,
914
- objectId: {
915
- type: point.meta.objectId.type,
916
- instance: point.meta.objectId.instance
917
- },
918
- values: {
919
- property: {
920
- id: 85,
921
- index: point.meta.arrayIndex
922
- },
923
- value: [{
924
- type: options.appTag,
925
- value: value
926
- }],
927
-
928
- },
929
- options: {
930
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
931
- maxApdu: that.readPropertyMultipleOptions.maxApdu,
932
- arrayIndex: point.meta.arrayIndex,
933
- priority: options.priority
934
- }
935
- };
936
-
937
- valuesArray.push(writeObject);
938
- });
939
-
940
- return that._writePropertyMultiple(valuesArray);
1153
+ return a.label.localeCompare(b.label);
1154
+ }
1155
+
1156
+ buildNetworkTreeData() {
1157
+ let that = this;
1158
+ that.buildTreeMutex = new Mutex();
1159
+ let displayNameCharThreshold = 40;
1160
+
1161
+ if (that.config.cacheFileEnabled) {
1162
+ Store_Config(
1163
+ JSON.stringify({
1164
+ renderList: that.renderList,
1165
+ deviceList: that.deviceList,
1166
+ pointList: that.networkTree,
1167
+ renderListCount: that.renderListCount,
1168
+ })
1169
+ );
941
1170
  }
942
1171
 
943
- _writePropertyMultiple(values) {
944
- let that = this;
945
- try {
946
- values.forEach(function(point) {
947
-
948
- that.client.writeProperty(
949
- point.address,
950
- point.objectId,
951
- baEnum.PropertyIdentifier.PRESENT_VALUE,
952
- point.values.value,
953
- point.options,
954
- (err, value) => {
955
- if(err) {
956
- that.logOut(err);
957
- }
1172
+ return new Promise(async function (resolve, reject) {
1173
+ if (!that.renderList) that.renderList = [];
1174
+ if (that.deviceList && that.networkTree) {
1175
+ that.deviceList.forEach(function (deviceInfo, index) {
1176
+ that.buildTreeMutex.acquire().then(function (release) {
1177
+ let ipAddr =
1178
+ typeof deviceInfo.getAddress() == "object" ? deviceInfo.getAddress().address : deviceInfo.getAddress();
1179
+ let deviceId = deviceInfo.getDeviceId();
1180
+ let deviceName = deviceInfo.getDeviceName() == null ? ipAddr : deviceInfo.getDeviceName();
1181
+ let deviceKey = ipAddr + "-" + deviceInfo.getDeviceId();
1182
+ let deviceObject = that.networkTree[deviceKey];
1183
+ let isMstpDevice = deviceInfo.getIsMstpDevice();
1184
+ let manualDiscoveryMode = deviceInfo.getManualDiscoveryMode();
1185
+
1186
+ if (deviceObject && typeof deviceName !== "object") {
1187
+ let children = [];
1188
+ let pointIndex = 0;
1189
+
1190
+ for (const pointName in deviceObject) {
1191
+ let pointProperties = [];
1192
+ let values = deviceObject[pointName];
1193
+
1194
+ let displayName = pointName;
1195
+ if (pointName.length > displayNameCharThreshold) {
1196
+ displayName = "";
1197
+ let charArray = pointName.split("");
1198
+ for (let i = 0; i < charArray.length; i++) {
1199
+ if (i < displayNameCharThreshold) {
1200
+ displayName += charArray[i];
958
1201
  }
959
- );
960
- });
1202
+ }
1203
+ displayName += "...";
1204
+ }
961
1205
 
962
- } catch (error) {
963
- that.logOut(error);
964
- }
965
- }
1206
+ if (values.objectName) {
1207
+ pointProperties.push({
1208
+ key: `${index}-0-${pointIndex}-0`,
1209
+ label: `Name: ${values.objectName}`,
1210
+ data: values.objectName,
1211
+ icon: "pi pi-cog",
1212
+ children: null,
1213
+ });
1214
+ }
1215
+ if (
1216
+ values.objectType &&
1217
+ values.hasOwnProperty("objectID") &&
1218
+ values.objectID.hasOwnProperty("type") &&
1219
+ values.objectID.type !== 8
1220
+ ) {
1221
+ pointProperties.push({
1222
+ key: `${index}-0-${pointIndex}-1`,
1223
+ label: `Object Type: ${values.objectType}`,
1224
+ data: values.objectType,
1225
+ icon: "pi pi-cog",
1226
+ children: null,
1227
+ });
1228
+ }
1229
+ if (values.objectID && values.objectID.instance) {
1230
+ pointProperties.push({
1231
+ key: `${index}-0-${pointIndex}-2`,
1232
+ label: `Object Instance: ${values.objectID.instance}`,
1233
+ data: values.objectID.instance,
1234
+ icon: "pi pi-cog",
1235
+ children: null,
1236
+ });
1237
+ }
1238
+ if (values.description) {
1239
+ pointProperties.push({
1240
+ key: `${index}-0-${pointIndex}-3`,
1241
+ label: `Description: ${values.description}`,
1242
+ data: `${values.description}`,
1243
+ icon: "pi pi-cog",
1244
+ children: null,
1245
+ });
1246
+ }
1247
+ if (values.units) {
1248
+ pointProperties.push({
1249
+ key: `${index}-0-${pointIndex}-4`,
1250
+ label: `Units: ${values.units}`,
1251
+ data: `${values.units}`,
1252
+ icon: "pi pi-cog",
1253
+ children: null,
1254
+ });
1255
+ }
1256
+ if (
1257
+ values.presentValue !== "undefined" &&
1258
+ values.presentValue !== null &&
1259
+ typeof values.presentValue !== "undefined"
1260
+ ) {
1261
+ pointProperties.push({
1262
+ key: `${index}-0-${pointIndex}-5`,
1263
+ label: `Present Value: ${values.presentValue}`,
1264
+ data: `${values.presentValue}`,
1265
+ icon: "pi pi-cog",
1266
+ children: null,
1267
+ });
1268
+ }
1269
+ if (
1270
+ values.systemStatus !== null &&
1271
+ typeof values.systemStatus !== "undefined" &&
1272
+ values.systemStatus !== ""
1273
+ ) {
1274
+ pointProperties.push({
1275
+ key: `${index}-0-${pointIndex}-6`,
1276
+ label: `System Status: ${values.systemStatus}`,
1277
+ data: `${values.systemStatus}`,
1278
+ icon: "pi pi-cog",
1279
+ children: null,
1280
+ });
1281
+ }
1282
+ if (values.modificationDate && !values.modificationDate.errorClass) {
1283
+ pointProperties.push({
1284
+ key: `${index}-0-${pointIndex}-7`,
1285
+ label: `Modification Date: ${values.modificationDate}`,
1286
+ data: `${values.modificationDate}`,
1287
+ icon: "pi pi-cog",
1288
+ children: null,
1289
+ });
1290
+ }
1291
+ if (values.programState) {
1292
+ pointProperties.push({
1293
+ key: `${index}-0-${pointIndex}-8`,
1294
+ label: `Program State: ${values.programState}`,
1295
+ data: `${values.programState}`,
1296
+ icon: "pi pi-cog",
1297
+ children: null,
1298
+ });
1299
+ }
1300
+ if (values.recordCount && !values.recordCount.errorClass) {
1301
+ pointProperties.push({
1302
+ key: `${index}-0-${pointIndex}-9`,
1303
+ label: `Record Count: ${values.recordCount}`,
1304
+ data: `${values.recordCount}`,
1305
+ icon: "pi pi-cog",
1306
+ children: null,
1307
+ });
1308
+ }
1309
+ if (
1310
+ values.hasOwnProperty("objectID") &&
1311
+ values.objectID.hasOwnProperty("type") &&
1312
+ values.objectID.type == 8
1313
+ ) {
1314
+ //device point, add segmentation supported, and apdu size
1315
+ pointProperties.push({
1316
+ key: `${index}-0-${pointIndex}-10`,
1317
+ label: `Segmentation Supported: ${deviceInfo.getSegmentation()}`,
1318
+ data: `${deviceInfo.getSegmentation()}`,
1319
+ icon: "pi pi-cog",
1320
+ children: null,
1321
+ });
1322
+ pointProperties.push({
1323
+ key: `${index}-0-${pointIndex}-11`,
1324
+ label: `APDU Size: ${deviceInfo.getMaxApdu()}`,
1325
+ data: `${deviceInfo.getMaxApdu()}`,
1326
+ icon: "pi pi-cog",
1327
+ children: null,
1328
+ });
1329
+ }
966
1330
 
967
- _findValueById(properties, id) {
968
- const property = properties.find(function (element) {
969
- return element.id === id;
970
- });
971
- if (property && property.value && property.value.length > 0) {
972
- return property.value[0].value;
973
- } else {
974
- return null;
975
- }
976
- };
1331
+ children.push({
1332
+ key: `${index}-0-${pointIndex}`,
1333
+ label: displayName,
1334
+ data: displayName,
1335
+ pointName: pointName,
1336
+ icon: that.getPointIcon(values),
1337
+ children: pointProperties,
1338
+ type: "point",
1339
+ parentDevice: deviceName,
1340
+ showAdded: false,
1341
+ bacnetType: values.meta.objectId.type,
1342
+ });
1343
+ pointIndex++;
1344
+ }
1345
+ let foundIndex = that.renderList.findIndex((ele) => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
1346
+ if (foundIndex !== -1) {
1347
+ let folderJson = [];
1348
+ if (deviceInfo.hasChildDevices()) {
1349
+ folderJson = [
1350
+ {
1351
+ key: `${index}-0`,
1352
+ label: "Points",
1353
+ data: "Points Folder",
1354
+ icon: "pi pi-circle-fill",
1355
+ type: "pointFolder",
1356
+ children: children.sort(that.sortPoints),
1357
+ },
1358
+ {
1359
+ key: `${index}-1`,
1360
+ label: "MSTP Network",
1361
+ data: "Devices Folder",
1362
+ icon: "pi pi-database",
1363
+ type: "deviceFolder",
1364
+ children: [],
1365
+ },
1366
+ ];
1367
+ } else {
1368
+ folderJson = [
1369
+ {
1370
+ key: `${index}-0`,
1371
+ label: "Points",
1372
+ data: "Points Folder",
1373
+ icon: "pi pi-circle-fill",
1374
+ type: "pointFolder",
1375
+ children: children.sort(that.sortPoints),
1376
+ },
1377
+ ];
1378
+ }
977
1379
 
978
- scanDevice(device) {
979
- let that = this;
980
- return new Promise((resolve, reject) => {
981
- const readOptions = {
982
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
983
- maxApdu: that.readPropertyMultipleOptions.maxApdu
984
- };
985
- this._readObjectList(device.getAddress(), device.getDeviceId(), readOptions, (err, result) => {
986
- if (!err) {
987
- try {
988
- resolve(result.values);
989
- } catch(e) {
990
- that.logOut("Issue with getting device point list, see error: ", e);
1380
+ if (!isMstpDevice) {
1381
+ that.renderList[foundIndex] = {
1382
+ key: index,
1383
+ label: deviceName,
1384
+ data: deviceName,
1385
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1386
+ children: that.renderList[foundIndex].children,
1387
+ type: "device",
1388
+ lastSeen: deviceInfo.getLastSeen(),
1389
+ showAdded: false,
1390
+ ipAddr: ipAddr,
1391
+ deviceId: deviceId,
1392
+ isMstpDevice: isMstpDevice,
1393
+ };
1394
+ } else if (isMstpDevice) {
1395
+ let parentDeviceId = deviceInfo.getParentDeviceId();
1396
+ let parentDeviceIndex = that.renderList.findIndex(
1397
+ (ele) => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr
1398
+ );
1399
+
1400
+ if (parentDeviceIndex !== -1 && that.renderList[parentDeviceIndex].children[1].children) {
1401
+ let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(
1402
+ (ele) => ele.deviceId == deviceId && ele.ipAddr == ipAddr
1403
+ );
1404
+ if (mstpDeviceIndex == -1) {
1405
+ //that.renderListCount++;
1406
+ that.renderList[parentDeviceIndex].children[1].children.push({
1407
+ key: index,
1408
+ label: deviceName,
1409
+ data: deviceName,
1410
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1411
+ children: folderJson,
1412
+ type: "device",
1413
+ lastSeen: deviceInfo.getLastSeen(),
1414
+ showAdded: false,
1415
+ ipAddr: ipAddr,
1416
+ deviceId: deviceId,
1417
+ isMstpDevice: isMstpDevice,
1418
+ });
1419
+ } else {
1420
+ that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {
1421
+ key: index,
1422
+ label: deviceName,
1423
+ data: deviceName,
1424
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1425
+ children: folderJson,
1426
+ type: "device",
1427
+ lastSeen: deviceInfo.getLastSeen(),
1428
+ showAdded: false,
1429
+ ipAddr: ipAddr,
1430
+ deviceId: deviceId,
1431
+ isMstpDevice: isMstpDevice,
1432
+ };
991
1433
  }
1434
+ }
1435
+ }
1436
+ } else if (foundIndex == -1) {
1437
+ let folderJson = [];
1438
+ if (deviceInfo.hasChildDevices()) {
1439
+ folderJson = [
1440
+ {
1441
+ key: `${index}-0`,
1442
+ label: "Points",
1443
+ data: "Points Folder",
1444
+ icon: "pi pi-circle-fill",
1445
+ type: "pointFolder",
1446
+ children: children.sort(that.sortPoints),
1447
+ },
1448
+ {
1449
+ key: `${index}-1`,
1450
+ label: "MSTP Network",
1451
+ data: "Devices Folder",
1452
+ icon: "pi pi-database",
1453
+ type: "deviceFolder",
1454
+ children: [],
1455
+ },
1456
+ ];
992
1457
  } else {
993
- that.logOut(`Error while fetching objects: ${err}`);
994
- reject(err);
1458
+ folderJson = [
1459
+ {
1460
+ key: `${index}-0`,
1461
+ label: "Points",
1462
+ data: "Points Folder",
1463
+ icon: "pi pi-circle-fill",
1464
+ type: "pointFolder",
1465
+ children: children.sort(that.sortPoints),
1466
+ },
1467
+ ];
995
1468
  }
996
- });
997
- });
998
- }
999
-
1000
- //closes bacnet client
1001
- shutDownClient() {
1002
- let that = this;
1003
- if(that.client) that.client.close((err, result) => {
1004
- that.logOut(err, result);
1005
- });
1006
- };
1007
-
1008
- globalWhoIs() {
1009
- let that = this;
1010
- if(that.client) {
1011
- that.client.whoIs({'net': 65535});
1012
- } else {
1013
- that.reinitializeClient(that.config);
1014
- }
1015
- that.lastWhoIs = Date.now();
1016
- }
1017
1469
 
1470
+ if (!isMstpDevice) {
1471
+ //that.renderListCount++;
1472
+ that.renderList.push({
1473
+ key: index,
1474
+ label: deviceName,
1475
+ data: deviceName,
1476
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1477
+ children: folderJson,
1478
+ type: "device",
1479
+ lastSeen: deviceInfo.getLastSeen(),
1480
+ showAdded: false,
1481
+ ipAddr: ipAddr,
1482
+ deviceId: deviceId,
1483
+ isMstpDevice: isMstpDevice,
1484
+ });
1485
+ } else if (isMstpDevice) {
1486
+ let parentDeviceId = deviceInfo.getParentDeviceId();
1487
+ let parentDeviceIndex = that.renderList.findIndex(
1488
+ (ele) => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr
1489
+ );
1490
+
1491
+ if (
1492
+ parentDeviceIndex !== -1 &&
1493
+ that.renderList[parentDeviceIndex].children &&
1494
+ that.renderList[parentDeviceIndex].children[1].children
1495
+ ) {
1496
+ let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(
1497
+ (ele) => ele.deviceId == deviceId && ele.ipAddr == ipAddr
1498
+ );
1499
+
1500
+ if (mstpDeviceIndex == -1) {
1501
+ // that.renderListCount++;
1502
+ that.renderList[parentDeviceIndex].children[1].children.push({
1503
+ key: index,
1504
+ label: deviceName,
1505
+ data: deviceName,
1506
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1507
+ children: folderJson,
1508
+ type: "device",
1509
+ lastSeen: deviceInfo.getLastSeen(),
1510
+ showAdded: false,
1511
+ ipAddr: ipAddr,
1512
+ deviceId: deviceId,
1513
+ isMstpDevice: isMstpDevice,
1514
+ });
1515
+ } else {
1516
+ that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {
1517
+ key: index,
1518
+ label: deviceName,
1519
+ data: deviceName,
1520
+ icon: that.getDeviceIcon(isMstpDevice, manualDiscoveryMode),
1521
+ children: folderJson,
1522
+ type: "device",
1523
+ lastSeen: deviceInfo.getLastSeen(),
1524
+ showAdded: false,
1525
+ ipAddr: ipAddr,
1526
+ deviceId: deviceId,
1527
+ isMstpDevice: isMstpDevice,
1528
+ };
1529
+ }
1530
+ }
1531
+ }
1532
+ }
1018
1533
 
1019
- getNetworkTreeData() {
1020
- let that = this;
1021
- return new Promise(async function(resolve, reject) {
1022
- try {
1023
- const reducedDeviceList = JSON.parse(JSON.stringify(that.deviceList));
1024
- reducedDeviceList.forEach((device) => {
1025
- delete device["pointsList"];
1534
+ if (index == that.deviceList.length - 1) {
1535
+ that.renderList.sort(that.sortDevices);
1536
+ resolve({
1537
+ renderList: that.renderList,
1538
+ deviceList: that.deviceList,
1539
+ pointList: that.networkTree,
1540
+ pollFrequency: that.discover_polling_schedule,
1026
1541
  });
1027
- resolve({renderList: that.renderList, deviceList: reducedDeviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule, renderListCount: that.renderListCount});
1028
- } catch(e){
1029
- reject(e);
1030
- }
1031
- });
1032
- }
1033
-
1034
- getDeviceList() {
1035
- let that = this;
1036
- return new Promise(async function(resolve, reject) {
1037
- try {
1038
- resolve({"deviceList": that.deviceList});
1039
- } catch(e){
1040
- reject(e);
1041
- }
1042
- });
1043
- }
1044
-
1045
- updateDeviceList(json) {
1046
- let that = this;
1047
- return new Promise(async function(resolve, reject) {
1048
- try {
1049
- let deviceL = json.body.deviceList;
1050
- deviceL.forEach(function(device) {
1051
- let foundIndex = that.deviceList.findIndex(ele => ele.getDeviceId() == device.deviceId);
1052
- if(foundIndex == -1) {
1053
- let newBacnetDevice = new BacnetDevice(true, device);
1054
- newBacnetDevice.setLastSeen(Date.now());
1055
- that.deviceList.push(newBacnetDevice);
1056
-
1057
- } else if(foundIndex !== -1) {
1058
- that.deviceList[foundIndex].updateDeviceConfig(device);
1059
- that.deviceList[foundIndex].setLastSeen(Date.now());
1060
- }
1542
+ }
1543
+ } else {
1544
+ if (index == that.deviceList.length - 1) {
1545
+ that.renderList.sort(that.sortDevices);
1546
+ resolve({
1547
+ renderList: that.renderList,
1548
+ deviceList: that.deviceList,
1549
+ pointList: that.networkTree,
1550
+ pollFrequency: that.discover_polling_schedule,
1061
1551
  });
1062
-
1063
- resolve(true);
1064
- } catch(e) {
1065
- reject(e);
1066
- }
1067
- });
1068
- }
1069
-
1070
- updatePriorityQueue(priorityDevices) {
1071
- let that = this;
1072
- return new Promise(async function(resolve, reject) {
1073
- try {
1074
- let keys = Object.keys(priorityDevices);
1075
- if(keys.length > 0) {
1076
- keys.forEach(function(key) {
1077
- let device = that.deviceList.find(ele => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
1078
- let points = priorityDevices[key];
1079
- if(device) {
1080
- device.setPriorityQueue(points);
1081
- }
1082
- });
1083
- } else if(keys.length == 0) {
1084
- that.clearPriorityQueues();
1085
- }
1086
- resolve(true);
1087
- } catch(e){
1088
- reject(e);
1552
+ }
1089
1553
  }
1090
- });
1091
- }
1092
1554
 
1093
- clearPriorityQueues() {
1094
- let that = this;
1095
- that.deviceList.forEach(function(device) {
1096
- device.clearPriorityQueue();
1555
+ release();
1556
+ });
1097
1557
  });
1098
- }
1099
-
1100
- getPriorityDevices() {
1101
- let that = this;
1102
- let priorityDevices = that.deviceList.filter(device => device.getPriorityQueueIsActive() == true);
1103
- return priorityDevices;
1104
- }
1105
-
1106
- sortDevices(a, b) {
1107
- if (a.deviceId < b.deviceId) {
1108
- return -1;
1109
- } else if (a.deviceId > b.deviceId) {
1110
- return 1;
1111
- }
1112
- return 0; // deviceIds are equal
1113
- }
1114
-
1115
- sortPoints(a, b) {
1116
- if(a.bacnetType > b.bacnetType) {
1117
- return 1;
1118
- } else if(a.bacnetType < b.bacnetType) {
1119
- return -1;
1120
- } else if(a.bacnetType == b.bacnetType) {
1121
- return 0;
1558
+ }
1559
+ });
1560
+ }
1561
+
1562
+ countDevices() {
1563
+ let that = this;
1564
+
1565
+ let deviceCount = 0;
1566
+
1567
+ that.renderList.forEach(function (device, index) {
1568
+ if (device) {
1569
+ if (
1570
+ device.children[1] &&
1571
+ device.children[1].label == "MSTP Network" &&
1572
+ device.children[1].children &&
1573
+ device.children[1].children.length > 0
1574
+ ) {
1575
+ //increment for parent device / mstp router
1576
+ deviceCount++;
1577
+ //increment for mstp device list
1578
+ deviceCount += device.children[1].children.length;
1579
+ } else {
1580
+ deviceCount++;
1122
1581
  }
1582
+ }
1583
+ if (index == that.renderList.length - 1) {
1584
+ that.renderListCount = deviceCount;
1585
+ }
1586
+ });
1587
+ }
1588
+
1589
+ buildJsonObject(device, priorityQueue) {
1590
+ let that = this;
1591
+ let address = device.address;
1592
+ let pointList = priorityQueue !== null ? priorityQueue : device.getPointsList();
1593
+ let requestMutex = new Mutex();
1594
+
1595
+ return new Promise(function (resolve, reject) {
1596
+ let promiseArray = [];
1597
+ if (typeof pointList !== "undefined" && pointList.length > 0) {
1598
+ pointList.forEach(function (point, pointListIndex) {
1599
+ requestMutex.acquire().then(function (release) {
1600
+ that
1601
+ ._readObjectFull(device, address, point.value.type, point.value.instance)
1602
+ .then(function (result) {
1603
+ if (!result.error) {
1604
+ if (result.length > 0 && Array.isArray(result)) {
1605
+ promiseArray = result;
1606
+ } else {
1607
+ promiseArray.push(result);
1608
+ }
1609
+ }
1123
1610
 
1124
- return a.label.localeCompare(b.label)
1125
- }
1126
-
1127
- buildNetworkTreeData() {
1128
- let that = this;
1129
- that.buildTreeMutex = new Mutex();
1130
- let displayNameCharThreshold = 40;
1131
-
1132
- Store_Config(JSON.stringify({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, renderListCount: that.renderListCount}));
1133
-
1134
- return new Promise(async function(resolve, reject) {
1135
- if(!that.renderList) that.renderList = [];
1136
- if(that.deviceList && that.networkTree) {
1137
- that.deviceList.forEach(function(deviceInfo, index) {
1138
- that.buildTreeMutex
1139
- .acquire()
1140
- .then(function(release) {
1141
-
1142
- let ipAddr = typeof deviceInfo.getAddress() == "object" ? deviceInfo.getAddress().address : deviceInfo.getAddress();
1143
- let deviceId = deviceInfo.getDeviceId();
1144
- let deviceName = deviceInfo.getDeviceName() == null ? ipAddr : deviceInfo.getDeviceName();
1145
- let deviceKey = ipAddr + "-" + deviceInfo.getDeviceId();
1146
- let deviceObject = that.networkTree[deviceKey];
1147
- let isMstpDevice = deviceInfo.getIsMstpDevice();
1148
- let manualDiscoveryMode = deviceInfo.getManualDiscoveryMode();
1149
-
1150
- if(deviceObject && typeof deviceName !== "object") {
1151
- let children = [];
1152
- let pointIndex = 0;
1153
-
1154
- for(const pointName in deviceObject) {
1155
- let pointProperties = [];
1156
- let values = deviceObject[pointName];
1157
-
1158
- let displayName = pointName;
1159
- if(pointName.length > displayNameCharThreshold) {
1160
- displayName = "";
1161
- let charArray = pointName.split("");
1162
- for(let i = 0; i < charArray.length; i++) {
1163
- if(i < displayNameCharThreshold){
1164
- displayName += charArray[i];
1165
- }
1166
- }
1167
- displayName += "...";
1168
- }
1169
-
1170
- if(values.objectName){
1171
- pointProperties.push({"key": `${index}-0-${pointIndex}-0`, "label": `Name: ${values.objectName}`, "data": values.objectName, "icon": "pi pi-cog", "children": null});
1172
- }
1173
- if(values.objectType && values.objectID.type !== 8){
1174
- pointProperties.push({"key": `${index}-0-${pointIndex}-1`, "label": `Object Type: ${values.objectType}`, "data": values.objectType, "icon": "pi pi-cog", "children": null});
1175
- }
1176
- if(values.objectID && values.objectID.instance) {
1177
- pointProperties.push({"key": `${index}-0-${pointIndex}-2`, "label": `Object Instance: ${values.objectID.instance}`, "data": values.objectID.instance, "icon": "pi pi-cog", "children": null});
1178
- }
1179
- if(values.description){
1180
- pointProperties.push({"key": `${index}-0-${pointIndex}-3`, "label": `Description: ${values.description}`, "data": `${values.description}`, "icon": "pi pi-cog", "children": null});
1181
- }
1182
- if(values.units){
1183
- pointProperties.push({"key": `${index}-0-${pointIndex}-4`, "label": `Units: ${values.units}`, "data": `${values.units}`, "icon": "pi pi-cog", "children": null});
1184
- }
1185
- if(values.presentValue !== "undefined" && values.presentValue !== null && typeof values.presentValue !== "undefined") {
1186
- pointProperties.push({"key": `${index}-0-${pointIndex}-5`, "label": `Present Value: ${values.presentValue}`, "data": `${values.presentValue}`, "icon": "pi pi-cog", "children": null});
1187
- }
1188
- if(values.systemStatus !== null && typeof values.systemStatus !== "undefined" && values.systemStatus !== ""){
1189
- pointProperties.push({"key": `${index}-0-${pointIndex}-6`, "label": `System Status: ${values.systemStatus}`, "data": `${values.systemStatus}`, "icon": "pi pi-cog", "children": null});
1190
- }
1191
- if(values.modificationDate && !values.modificationDate.errorClass) {
1192
- pointProperties.push({"key": `${index}-0-${pointIndex}-7`, "label": `Modification Date: ${values.modificationDate}`, "data": `${values.modificationDate}`, "icon": "pi pi-cog", "children": null});
1193
- }
1194
- if(values.programState){
1195
- pointProperties.push({"key": `${index}-0-${pointIndex}-8`, "label": `Program State: ${values.programState}`, "data": `${values.programState}`, "icon": "pi pi-cog", "children": null});
1196
- }
1197
- if(values.recordCount && !values.recordCount.errorClass){
1198
- pointProperties.push({"key": `${index}-0-${pointIndex}-9`, "label": `Record Count: ${values.recordCount}`, "data": `${values.recordCount}`, "icon": "pi pi-cog", "children": null});
1199
- }
1200
- if(values.objectID && values.objectID.type == 8) {
1201
- //device point, add segmentation supported, and apdu size
1202
- pointProperties.push({"key": `${index}-0-${pointIndex}-10`, "label": `Segmentation Supported: ${deviceInfo.getSegmentation()}`, "data": `${deviceInfo.getSegmentation()}`, "icon": "pi pi-cog", "children": null});
1203
- pointProperties.push({"key": `${index}-0-${pointIndex}-11`, "label": `APDU Size: ${deviceInfo.getMaxApdu()}`, "data": `${deviceInfo.getMaxApdu()}`, "icon": "pi pi-cog", "children": null});
1204
- }
1205
-
1206
- children.push({"key": `${index}-0-${pointIndex}`, "label": displayName, "data": displayName, "pointName": pointName, "icon": that.getPointIcon(values.meta.objectId.type), "children": pointProperties, "type": "point", "parentDevice": deviceName, "showAdded": false, "bacnetType": values.meta.objectId.type})
1207
- pointIndex++;
1208
- }
1209
- let foundIndex = that.renderList.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
1210
- if(foundIndex !== -1) {
1211
- let folderJson = [];
1212
- if(deviceInfo.hasChildDevices()) {
1213
- folderJson = [
1214
- {
1215
- key: `${index}-0`,
1216
- label: "Points",
1217
- data: "Points Folder",
1218
- icon: "pi pi-circle-fill",
1219
- type: "pointFolder",
1220
- children: children.sort(that.sortPoints)
1221
- },
1222
- {
1223
- key: `${index}-1`,
1224
- label: "MSTP Network",
1225
- data: "Devices Folder",
1226
- icon: "pi pi-database",
1227
- type: "deviceFolder",
1228
- children: []
1229
- }
1230
- ];
1231
- } else {
1232
- folderJson = [
1233
- {
1234
- key: `${index}-0`,
1235
- label: "Points",
1236
- data: "Points Folder",
1237
- icon: "pi pi-circle-fill",
1238
- type: "pointFolder",
1239
- children: children.sort(that.sortPoints)
1240
- }
1241
- ];
1242
- }
1243
-
1244
- if(!isMstpDevice) {
1245
- that.renderList[foundIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": that.renderList[foundIndex].children, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
1246
- } else if(isMstpDevice) {
1247
- let parentDeviceId = deviceInfo.getParentDeviceId();
1248
- let parentDeviceIndex = that.renderList.findIndex(ele => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr);
1249
-
1250
- if(parentDeviceIndex !== -1 && that.renderList[parentDeviceIndex].children[1].children) {
1251
- let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
1252
- if(mstpDeviceIndex == -1) {
1253
- //that.renderListCount++;
1254
- that.renderList[parentDeviceIndex].children[1].children.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
1255
- } else {
1256
- that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
1257
- }
1258
- }
1259
- }
1260
-
1261
- } else if(foundIndex == -1) {
1262
- let folderJson = [];
1263
- if(deviceInfo.hasChildDevices()) {
1264
- folderJson = [
1265
- {
1266
- key: `${index}-0`,
1267
- label: "Points",
1268
- data: "Points Folder",
1269
- icon: "pi pi-circle-fill",
1270
- type: "pointFolder",
1271
- children: children.sort(that.sortPoints)
1272
- },
1273
- {
1274
- key: `${index}-1`,
1275
- label: "MSTP Network",
1276
- data: "Devices Folder",
1277
- icon: "pi pi-database",
1278
- type: "deviceFolder",
1279
- children: []
1280
- }
1281
- ];
1282
- } else {
1283
- folderJson = [
1284
- {
1285
- key: `${index}-0`,
1286
- label: "Points",
1287
- data: "Points Folder",
1288
- icon: "pi pi-circle-fill",
1289
- type: "pointFolder",
1290
- children: children.sort(that.sortPoints)
1291
- }
1292
- ];
1293
- }
1294
-
1295
- if(!isMstpDevice) {
1296
- //that.renderListCount++;
1297
- that.renderList.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
1298
- } else if(isMstpDevice) {
1299
- let parentDeviceId = deviceInfo.getParentDeviceId();
1300
- let parentDeviceIndex = that.renderList.findIndex(ele => ele.deviceId == parentDeviceId && ele.ipAddr == ipAddr);
1301
-
1302
- if(parentDeviceIndex !== -1 && that.renderList[parentDeviceIndex].children && that.renderList[parentDeviceIndex].children[1].children) {
1303
- let mstpDeviceIndex = that.renderList[parentDeviceIndex].children[1].children.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
1304
-
1305
- if(mstpDeviceIndex == -1) {
1306
- // that.renderListCount++;
1307
- that.renderList[parentDeviceIndex].children[1].children.push({"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice});
1308
- } else {
1309
- that.renderList[parentDeviceIndex].children[1].children[mstpDeviceIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": folderJson, "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
1310
- }
1311
- }
1312
- }
1313
- }
1314
-
1315
- if(index == that.deviceList.length - 1) {
1316
- that.renderList.sort(that.sortDevices);
1317
- resolve({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule});
1318
- }
1319
- } else {
1320
- if(index == that.deviceList.length - 1) {
1321
- that.renderList.sort(that.sortDevices);
1322
- resolve({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule});
1323
- }
1324
- }
1325
-
1326
- release();
1611
+ release();
1612
+
1613
+ if (pointListIndex == pointList.length - 1) {
1614
+ that
1615
+ .buildResponse(promiseArray, device)
1616
+ .then(function () {
1617
+ that.lastNetworkPoll = Date.now();
1618
+ resolve({ deviceList: that.deviceList, pointList: that.networkTree });
1619
+ })
1620
+ .catch(function (e) {
1621
+ that.logOut("Error while building json object: ", e);
1622
+ reject(e);
1327
1623
  });
1328
- });
1329
- }
1330
- });
1331
- }
1332
-
1333
- countDevices() {
1334
- let that = this;
1335
-
1336
- let deviceCount = 0;
1337
-
1338
- that.renderList.forEach(function(device, index) {
1339
- if(device) {
1340
- if(device.children[1] && device.children[1].label == 'MSTP Network' && device.children[1].children && device.children[1].children.length > 0) {
1341
- //increment for parent device / mstp router
1342
- deviceCount++;
1343
- //increment for mstp device list
1344
- deviceCount += device.children[1].children.length;
1345
- } else {
1346
- deviceCount++;
1347
1624
  }
1348
- }
1349
- if(index == that.renderList.length -1) {
1350
- that.renderListCount = deviceCount;
1351
- }
1625
+ })
1626
+ .catch(function (e) {
1627
+ release();
1628
+ that.logOut("_readObjectFull error: ", e);
1629
+
1630
+ if (pointListIndex == pointList.length - 1) {
1631
+ that
1632
+ .buildResponse(promiseArray, device)
1633
+ .then(function () {
1634
+ that.lastNetworkPoll = Date.now();
1635
+ resolve({ deviceList: that.deviceList, pointList: that.networkTree });
1636
+ })
1637
+ .catch(function (e) {
1638
+ that.logOut("Error while building json object: ", e);
1639
+ reject(e);
1640
+ });
1641
+ }
1642
+ });
1643
+ });
1352
1644
  });
1353
- }
1645
+ } else {
1646
+ reject("Unable to build network tree, empty point list");
1647
+ }
1648
+ });
1649
+ }
1650
+
1651
+ // Builds response object for a fully qualified
1652
+ buildResponse(fullObjects, device) {
1653
+ let that = this;
1654
+
1655
+ return new Promise(function (resolve, reject) {
1656
+ let deviceKey =
1657
+ typeof device.getAddress() == "object"
1658
+ ? device.getAddress().address + "-" + device.getDeviceId()
1659
+ : device.getAddress() + "-" + device.getDeviceId();
1660
+ let values = that.networkTree[deviceKey] ? that.networkTree[deviceKey] : {};
1661
+ for (let i = 0; i < fullObjects.length; i++) {
1662
+ let obj = fullObjects[i];
1663
+ let successfulResult = !obj.error ? obj.value : null;
1664
+ if (successfulResult) {
1665
+ successfulResult.values.forEach(function (pointProperty, pointPropertyIndex) {
1666
+ if (!pointProperty.objectId && successfulResult.objectId && !pointProperty.values && successfulResult.values) {
1667
+ pointProperty = successfulResult;
1668
+ }
1354
1669
 
1355
- buildJsonObject(device, priorityQueue) {
1356
- let that = this;
1357
- let address = device.address;
1358
- let pointList = priorityQueue !== null ? priorityQueue : device.getPointsList();
1359
- let requestMutex = new Mutex();
1360
-
1361
- return new Promise(function(resolve, reject) {
1362
- let promiseArray = [];
1363
- if(typeof pointList !== "undefined" && pointList.length > 0) {
1364
- pointList.forEach(function(point, pointListIndex) {
1365
- requestMutex
1366
- .acquire()
1367
- .then(function(release) {
1368
- that._readObjectFull(device, address, point.value.type, point.value.instance).then(function(result) {
1369
-
1370
- if(!result.error) {
1371
- if(result.length > 0 && Array.isArray(result)) {
1372
- promiseArray = result;
1373
- } else {
1374
- promiseArray.push(result);
1375
- }
1670
+ let currobjectId = pointProperty.objectId.type;
1671
+ let bac_obj = that.getObjectType(currobjectId);
1672
+ let objectName = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_NAME);
1673
+ let objectType = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_TYPE);
1674
+ let objectId;
1675
+ if (objectName !== null && typeof objectName == "string") {
1676
+ objectId = objectName + "_" + bac_obj + "_" + pointProperty.objectId.instance;
1677
+
1678
+ try {
1679
+ pointProperty.values.forEach(function (object, objectIndex) {
1680
+ //checks for error code json structure, returned for invalid bacnet requests
1681
+ if (object && object.value && !object.value.errorClass) {
1682
+ if (!values[objectId]) values[objectId] = {};
1683
+ values[objectId].meta = {
1684
+ objectId: pointProperty.objectId,
1685
+ };
1686
+
1687
+ switch (object.id) {
1688
+ case baEnum.PropertyIdentifier.PRESENT_VALUE:
1689
+ if (object.value[0] && object.value[0].value !== "undefined" && object.value[0].value !== null) {
1690
+ //check for binary object type
1691
+ if (objectType == 3 || objectType == 4 || objectType == 5) {
1692
+ if (object.value[0].value == 0) {
1693
+ values[objectId].presentValue = false;
1694
+ } else if (object.value[0].value == 1) {
1695
+ values[objectId].presentValue = true;
1376
1696
  }
1697
+ } else if (objectType == 40) {
1698
+ //character string
1699
+ values[objectId].presentValue = object.value[0].value;
1700
+ } else {
1701
+ values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, 2);
1702
+ }
1703
+ }
1704
+ values[objectId].meta.arrayIndex = object.index;
1705
+ break;
1706
+ case baEnum.PropertyIdentifier.DESCRIPTION:
1707
+ if (object.value[0]) values[objectId].description = object.value[0].value;
1708
+ break;
1709
+ case baEnum.PropertyIdentifier.UNITS:
1710
+ if (object.value[0] && object.value[0].value)
1711
+ values[objectId].units = getUnit(object.value[0].value);
1712
+ break;
1713
+ case baEnum.PropertyIdentifier.OBJECT_NAME:
1714
+ if (object.value[0] && object.value[0].value) values[objectId].objectName = object.value[0].value;
1715
+ break;
1716
+ case baEnum.PropertyIdentifier.OBJECT_TYPE:
1717
+ if (object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
1718
+ break;
1719
+ case baEnum.PropertyIdentifier.OBJECT_IDENTIFIER:
1720
+ if (object.value[0] && object.value[0].value) values[objectId].objectID = object.value[0].value;
1721
+ break;
1722
+ case baEnum.PropertyIdentifier.PROPERTY_LIST:
1723
+ if (object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
1724
+ break;
1725
+
1726
+ case baEnum.PropertyIdentifier.SYSTEM_STATUS:
1727
+ if (object.value[0]) {
1728
+ values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
1729
+ }
1730
+ break;
1377
1731
 
1378
- release();
1732
+ case baEnum.PropertyIdentifier.MODIFICATION_DATE:
1733
+ if (object.value[0]) {
1734
+ values[objectId].modificationDate = object.value[0].value;
1735
+ }
1736
+ break;
1379
1737
 
1380
- if(pointListIndex == pointList.length - 1) {
1381
- that.buildResponse(promiseArray, device).then(function() {
1382
- that.lastNetworkPoll = Date.now();
1383
- resolve({deviceList: that.deviceList, pointList: that.networkTree});
1384
- }).catch(function(e){
1385
- that.logOut("Error while building json object: ", e);
1386
- reject(e);
1387
- });
1388
- }
1389
-
1390
- }).catch(function(e) {
1391
- release();
1392
- that.logOut("_readObjectFull error: ", e);
1393
-
1394
- if(pointListIndex == pointList.length - 1) {
1395
- that.buildResponse(promiseArray, device).then(function() {
1396
- that.lastNetworkPoll = Date.now();
1397
- resolve({deviceList: that.deviceList, pointList: that.networkTree});
1398
- }).catch(function(e){
1399
- that.logOut("Error while building json object: ", e);
1400
- reject(e);
1401
- });
1402
- }
1403
- });
1404
- });
1405
- });
1406
- } else {
1407
- reject("Unable to build network tree, empty point list");
1408
- }
1409
- });
1410
- }
1738
+ case baEnum.PropertyIdentifier.PROGRAM_STATE:
1739
+ if (object.value[0]) {
1740
+ values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
1741
+ }
1742
+ break;
1411
1743
 
1412
- // Builds response object for a fully qualified
1413
- buildResponse(fullObjects, device) {
1414
- let that = this;
1415
-
1416
- return new Promise(function(resolve, reject) {
1417
- let deviceKey = (typeof device.getAddress() == "object") ? device.getAddress().address + "-" + device.getDeviceId() : device.getAddress() + "-" + device.getDeviceId();
1418
- let values = that.networkTree[deviceKey] ? that.networkTree[deviceKey] : {};
1419
- for(let i = 0; i < fullObjects.length; i++) {
1420
- let obj = fullObjects[i];
1421
- let successfulResult = !obj.error ? obj.value : null;
1422
- if(successfulResult) {
1423
- successfulResult.values.forEach(function(pointProperty, pointPropertyIndex) {
1424
-
1425
- if(!pointProperty.objectId && successfulResult.objectId && !pointProperty.values && successfulResult.values) {
1426
- pointProperty = successfulResult;
1427
- }
1428
-
1429
- let currobjectId = pointProperty.objectId.type
1430
- let bac_obj = that.getObjectType(currobjectId);
1431
- let objectName = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_NAME);
1432
- let objectType = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_TYPE);
1433
- let objectId;
1434
- if(objectName !== null && typeof objectName == "string") {
1435
- objectId = objectName + "_" + bac_obj + '_' + pointProperty.objectId.instance;
1436
-
1437
- try {
1438
- pointProperty.values.forEach(function(object, objectIndex) {
1439
- //checks for error code json structure, returned for invalid bacnet requests
1440
- if(object && object.value && !object.value.errorClass) {
1441
-
1442
- if(!values[objectId]) values[objectId] = {};
1443
- values[objectId].meta = {
1444
- objectId: pointProperty.objectId
1445
- };
1446
-
1447
- switch(object.id) {
1448
- case baEnum.PropertyIdentifier.PRESENT_VALUE:
1449
- if(object.value[0] && object.value[0].value !== "undefined" && object.value[0].value !== null) {
1450
- //check for binary object type
1451
- if(objectType == 3 || objectType == 4 || objectType == 5) {
1452
- if(object.value[0].value == 0) {
1453
- values[objectId].presentValue = false;
1454
- } else if(object.value[0].value == 1) {
1455
- values[objectId].presentValue = true;
1456
- }
1457
- } else if(objectType == 40) {
1458
- //character string
1459
- values[objectId].presentValue = object.value[0].value;
1460
- } else {
1461
- values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, 2);
1462
- }
1463
- }
1464
- values[objectId].meta.arrayIndex = object.index;
1465
- break;
1466
- case baEnum.PropertyIdentifier.DESCRIPTION:
1467
- if(object.value[0]) values[objectId].description = object.value[0].value;
1468
- break;
1469
- case baEnum.PropertyIdentifier.UNITS:
1470
- if(object.value[0] && object.value[0].value) values[objectId].units = getUnit(object.value[0].value);
1471
- break;
1472
- case baEnum.PropertyIdentifier.OBJECT_NAME:
1473
- if(object.value[0] && object.value[0].value) values[objectId].objectName = object.value[0].value;
1474
- break;
1475
- case baEnum.PropertyIdentifier.OBJECT_TYPE:
1476
- if(object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
1477
- break;
1478
- case baEnum.PropertyIdentifier.OBJECT_IDENTIFIER:
1479
- if(object.value[0] && object.value[0].value) values[objectId].objectID = object.value[0].value;
1480
- break;
1481
- case baEnum.PropertyIdentifier.PROPERTY_LIST:
1482
- if(object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
1483
- break;
1484
-
1485
- case baEnum.PropertyIdentifier.SYSTEM_STATUS:
1486
- if(object.value[0]){
1487
- values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
1488
- }
1489
- break;
1490
-
1491
- case baEnum.PropertyIdentifier.MODIFICATION_DATE:
1492
- if(object.value[0]) {
1493
- values[objectId].modificationDate = object.value[0].value;
1494
- }
1495
- break;
1496
-
1497
- case baEnum.PropertyIdentifier.PROGRAM_STATE:
1498
- if(object.value[0]){
1499
- values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
1500
- }
1501
- break;
1502
-
1503
- case baEnum.PropertyIdentifier.RECORD_COUNT:
1504
- if(object.value[0] ) {
1505
- values[objectId].recordCount = object.value[0].value;
1506
- }
1507
- break;
1508
- }
1509
- }
1510
- if(pointPropertyIndex == successfulResult.values.length - 1 && objectIndex == pointProperty.values.length - 1 && i == fullObjects.length - 1) {
1511
- that.networkTree[deviceKey] = values;
1512
- resolve(that.networkTree);
1513
- }
1514
- });
1515
- } catch(e) {
1516
- that.logOut("issue resolving bacnet payload, see error: ", e);
1517
- reject(e);
1518
- }
1744
+ case baEnum.PropertyIdentifier.RECORD_COUNT:
1745
+ if (object.value[0]) {
1746
+ values[objectId].recordCount = object.value[0].value;
1519
1747
  }
1520
- });
1521
- } else {
1522
- //error found in point property
1523
- if(i == fullObjects.length - 1) {
1524
- that.networkTree[deviceKey] = values;
1525
- resolve(that.networkTree);
1748
+ break;
1749
+ case baEnum.PropertyIdentifier.PRIORITY_ARRAY:
1750
+ if (object.value.length > 0) {
1751
+ values[objectId].hasPriorityArray = true;
1752
+ }
1753
+ break;
1526
1754
  }
1527
- }
1755
+ }
1756
+ if (
1757
+ pointPropertyIndex == successfulResult.values.length - 1 &&
1758
+ objectIndex == pointProperty.values.length - 1 &&
1759
+ i == fullObjects.length - 1
1760
+ ) {
1761
+ that.networkTree[deviceKey] = values;
1762
+ resolve(that.networkTree);
1763
+ }
1764
+ });
1765
+ } catch (e) {
1766
+ that.logOut("issue resolving bacnet payload, see error: ", e);
1767
+ reject(e);
1768
+ }
1528
1769
  }
1770
+ });
1771
+ } else {
1772
+ //error found in point property
1773
+ if (i == fullObjects.length - 1) {
1529
1774
  that.networkTree[deviceKey] = values;
1530
1775
  resolve(that.networkTree);
1531
- });
1532
- }
1533
-
1534
- mapPropsToArray(propertyList) {
1535
- let uniquePropArray = [];
1536
- for(let i = 0; i < propertyList.length; i++) {
1537
- if(uniquePropArray.indexOf(propertyList[i].value) === -1) uniquePropArray.push(propertyList[i].value);
1776
+ }
1538
1777
  }
1539
- return uniquePropArray;
1778
+ }
1779
+ that.networkTree[deviceKey] = values;
1780
+ resolve(that.networkTree);
1781
+ });
1782
+ }
1783
+
1784
+ mapPropsToArray(propertyList) {
1785
+ let uniquePropArray = [];
1786
+ for (let i = 0; i < propertyList.length; i++) {
1787
+ if (uniquePropArray.indexOf(propertyList[i].value) === -1) uniquePropArray.push(propertyList[i].value);
1540
1788
  }
1541
-
1542
- getPROP_PROGRAM_STATE(value) {
1543
- switch(value) {
1544
- case 0:
1545
- return "0 - Idle";
1546
- case 1:
1547
- return "1 - Loading";
1548
- case 2:
1549
- return "2 - Running";
1550
- case 3:
1551
- return "3 - Waiting";
1552
- case 4:
1553
- return "4 - Halted";
1554
- case 5:
1555
- return "5 - Unloading";
1556
- default:
1557
- return "";
1558
- }
1789
+ return uniquePropArray;
1790
+ }
1791
+
1792
+ getPROP_PROGRAM_STATE(value) {
1793
+ switch (value) {
1794
+ case 0:
1795
+ return "0 - Idle";
1796
+ case 1:
1797
+ return "1 - Loading";
1798
+ case 2:
1799
+ return "2 - Running";
1800
+ case 3:
1801
+ return "3 - Waiting";
1802
+ case 4:
1803
+ return "4 - Halted";
1804
+ case 5:
1805
+ return "5 - Unloading";
1806
+ default:
1807
+ return "";
1559
1808
  }
1560
-
1561
- getPROP_SYSTEM_STATUS(value) {
1562
- switch(value) {
1563
- case 0:
1564
- return "0 - Operational";
1565
- case 1:
1566
- return "1 - Operational Readonly";
1567
- case 2:
1568
- return "2 - Download Required";
1569
- case 3:
1570
- return "3 - Download In Progress";
1571
- case 4:
1572
- return "4 - Non Operational";
1573
- case 5:
1574
- return "5 - Backup In Progress";
1575
- default:
1576
- return "";
1577
- }
1809
+ }
1810
+
1811
+ getPROP_SYSTEM_STATUS(value) {
1812
+ switch (value) {
1813
+ case 0:
1814
+ return "0 - Operational";
1815
+ case 1:
1816
+ return "1 - Operational Readonly";
1817
+ case 2:
1818
+ return "2 - Download Required";
1819
+ case 3:
1820
+ return "3 - Download In Progress";
1821
+ case 4:
1822
+ return "4 - Non Operational";
1823
+ case 5:
1824
+ return "5 - Backup In Progress";
1825
+ default:
1826
+ return "";
1578
1827
  }
1579
-
1580
- getPointIcon(objectId) {
1581
- switch(objectId) {
1582
- case 0:
1583
- //AI
1584
- return "pi pi-circle";
1585
- case 1:
1586
- //AO
1587
- return "pi pi-circle";
1588
- case 2:
1589
- //AV
1590
- return "pi pi-circle";
1591
- case 3:
1592
- //BI
1593
- return "pi pi-circle";
1594
- case 4:
1595
- //BO
1596
- return "pi pi-circle";
1597
- case 5:
1598
- //BV
1599
- return "pi pi-circle";
1600
- case 8:
1601
- //Device
1602
- return "pi pi-box";
1603
- case 13:
1604
- //MI
1605
- return "pi pi-circle";
1606
- case 14:
1607
- //MO
1608
- return "pi pi-circle";
1609
- case 19:
1610
- //MV
1611
- return "pi pi-circle";
1612
- case 10:
1613
- //File
1614
- return "pi pi-file";
1615
- case 16:
1616
- //Program
1617
- return "pi pi-database";
1618
- case 20:
1619
- //Trendlog
1620
- return "pi pi-chart-line";
1621
- case 15:
1622
- //Notification Class
1623
- return "pi pi-bell";
1624
- case 56:
1625
- return "pi pi-sitemap";
1626
- case 178:
1627
- return "pi pi-lock";
1628
- case 17:
1629
- return "pi pi-calendar";
1630
- case 6:
1631
- return "pi pi-calendar";
1632
- default:
1633
- //Return circle for all other types
1634
- return "pi pi-circle";
1635
- }
1828
+ }
1829
+
1830
+ getPointIcon(values) {
1831
+ const objectId = values.meta.objectId.type;
1832
+ const hasPriorityArray =
1833
+ values.hasPriorityArray && values.hasOwnProperty("hasPriorityArray") ? values.hasPriorityArray : false;
1834
+
1835
+ if (hasPriorityArray) {
1836
+ return "pi writePointIcon";
1837
+ } else {
1838
+ switch (objectId) {
1839
+ case 0:
1840
+ //AI
1841
+ return "pi readPointIcon";
1842
+ case 1:
1843
+ //AO
1844
+ return "pi readPointIcon";
1845
+ case 2:
1846
+ //AV
1847
+ return "pi readPointIcon";
1848
+ case 3:
1849
+ //BI
1850
+ return "pi readPointIcon";
1851
+ case 4:
1852
+ //BO
1853
+ return "pi readPointIcon";
1854
+ case 5:
1855
+ //BV
1856
+ return "pi readPointIcon";
1857
+ case 8:
1858
+ //Device
1859
+ return "pi pi-box";
1860
+ case 13:
1861
+ //MI
1862
+ return "pi readPointIcon";
1863
+ case 14:
1864
+ //MO
1865
+ return "pi readPointIcon";
1866
+ case 19:
1867
+ //MV
1868
+ return "pi readPointIcon";
1869
+ case 10:
1870
+ //File
1871
+ return "pi pi-file";
1872
+ case 16:
1873
+ //Program
1874
+ return "pi pi-database";
1875
+ case 20:
1876
+ //Trendlog
1877
+ return "pi pi-chart-line";
1878
+ case 15:
1879
+ //Notification Class
1880
+ return "pi pi-bell";
1881
+ case 56:
1882
+ return "pi pi-sitemap";
1883
+ case 178:
1884
+ return "pi pi-lock";
1885
+ case 17:
1886
+ return "pi pi-calendar";
1887
+ case 6:
1888
+ return "pi pi-calendar";
1889
+ default:
1890
+ //Return circle for all other types
1891
+ return "pi readPointIcon";
1892
+ }
1636
1893
  }
1637
-
1638
- getObjectType(objectId) {
1639
- switch(objectId) {
1640
- case 0:
1641
- return "AI";
1642
- case 1:
1643
- return "AO";
1644
- case 2:
1645
- return "AV";
1646
- case 3:
1647
- return "BI";
1648
- case 4:
1649
- return "BO";
1650
- case 5:
1651
- return "BV";
1652
- case 8:
1653
- return "Device";
1654
- case 13:
1655
- return "MI";
1656
- case 14:
1657
- return "MO";
1658
- case 19:
1659
- return "MV";
1660
- case 40:
1661
- return "CS";
1662
- default:
1663
- return "";
1664
- }
1665
- }
1666
-
1667
- getPROP_RELIABILITY(value) {
1668
- switch(value) {
1669
- case 0:
1670
- return "No Fault Detected";
1671
- case 1:
1672
- return "No Sensor";
1673
- case 2:
1674
- return "Over Range";
1675
- case 3:
1676
- return "Under Range";
1677
- case 4:
1678
- return "Open Loop";
1679
- case 5:
1680
- return "Shorted Loop";
1681
- case 6:
1682
- return "No Output";
1683
- case 7:
1684
- return "Unreliable Other";
1685
- case 8:
1686
- return "Process Error";
1687
- case 9:
1688
- return "Multi State Fault";
1689
- case 10:
1690
- return "Configuration Error";
1691
- case 11:
1692
- return "Member Fault";
1693
- case 12:
1694
- return "Communication Failure";
1695
- case 13:
1696
- return "Tripped";
1697
- default:
1698
- return "";
1699
- }
1894
+ }
1895
+
1896
+ getObjectType(objectId) {
1897
+ switch (objectId) {
1898
+ case 0:
1899
+ return "AI";
1900
+ case 1:
1901
+ return "AO";
1902
+ case 2:
1903
+ return "AV";
1904
+ case 3:
1905
+ return "BI";
1906
+ case 4:
1907
+ return "BO";
1908
+ case 5:
1909
+ return "BV";
1910
+ case 8:
1911
+ return "Device";
1912
+ case 13:
1913
+ return "MI";
1914
+ case 14:
1915
+ return "MO";
1916
+ case 19:
1917
+ return "MV";
1918
+ case 40:
1919
+ return "CS";
1920
+ default:
1921
+ return "";
1700
1922
  }
1701
-
1702
- getStatusFlags(flags) {
1703
- return flags.value[0].value;
1923
+ }
1924
+
1925
+ getPROP_RELIABILITY(value) {
1926
+ switch (value) {
1927
+ case 0:
1928
+ return "No Fault Detected";
1929
+ case 1:
1930
+ return "No Sensor";
1931
+ case 2:
1932
+ return "Over Range";
1933
+ case 3:
1934
+ return "Under Range";
1935
+ case 4:
1936
+ return "Open Loop";
1937
+ case 5:
1938
+ return "Shorted Loop";
1939
+ case 6:
1940
+ return "No Output";
1941
+ case 7:
1942
+ return "Unreliable Other";
1943
+ case 8:
1944
+ return "Process Error";
1945
+ case 9:
1946
+ return "Multi State Fault";
1947
+ case 10:
1948
+ return "Configuration Error";
1949
+ case 11:
1950
+ return "Member Fault";
1951
+ case 12:
1952
+ return "Communication Failure";
1953
+ case 13:
1954
+ return "Tripped";
1955
+ default:
1956
+ return "";
1704
1957
  }
1705
-
1706
- getDeviceIcon(isMstp, manualDiscoveryMode) {
1707
- if(manualDiscoveryMode == true) {
1708
- return "pi pi-question-circle"
1709
- } else if(manualDiscoveryMode == false) {
1710
- if(isMstp == true) {
1711
- return "pi pi-box"
1712
- } else if(isMstp == false) {
1713
- return "pi pi-server"
1714
- }
1715
- }
1958
+ }
1959
+
1960
+ getStatusFlags(flags) {
1961
+ return flags.value[0].value;
1962
+ }
1963
+
1964
+ getDeviceIcon(isMstp, manualDiscoveryMode) {
1965
+ if (manualDiscoveryMode == true) {
1966
+ return "pi pi-question-circle";
1967
+ } else if (manualDiscoveryMode == false) {
1968
+ if (isMstp == true) {
1969
+ return "pi pi-box";
1970
+ } else if (isMstp == false) {
1716
1971
  return "pi pi-server";
1717
- };
1972
+ }
1973
+ }
1974
+ return "pi pi-server";
1975
+ }
1718
1976
  }
1719
1977
 
1720
1978
  module.exports = { BacnetClient };