@bitpoolos/edge-bacnet 1.2.8 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +23 -2
- package/bacnet_client.js +843 -803
- package/bacnet_device.js +132 -60
- package/bacnet_gateway.html +92 -76
- package/bacnet_gateway.js +161 -46
- package/bacnet_read.html +1048 -598
- package/bacnet_read.js +68 -84
- package/bacnet_server.js +270 -205
- package/bacnet_write.html +329 -24
- package/common.js +23 -5
- package/package.json +2 -2
- package/resources/bitArray.js +167 -0
- package/resources/node-bacstack-ts/dist/lib/asn1.js +16 -5
- package/resources/node-bacstack-ts/dist/lib/client.js +6 -7
- package/resources/style.css +321 -0
- package/treeBuilder.js +545 -0
package/bacnet_client.js
CHANGED
|
@@ -6,10 +6,11 @@ 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
8
|
const { EventEmitter } = require("events");
|
|
9
|
-
const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync, isNumber } = require("./common");
|
|
9
|
+
const { getUnit, roundDecimalPlaces, Store_Config, Read_Config_Sync, isNumber, decodeBitArray } = require("./common");
|
|
10
10
|
const { ToadScheduler, SimpleIntervalJob, Task } = require("toad-scheduler");
|
|
11
11
|
const { BacnetDevice } = require("./bacnet_device");
|
|
12
12
|
const { Mutex } = require("async-mutex");
|
|
13
|
+
const { treeBuilder } = require("./treeBuilder.js");
|
|
13
14
|
|
|
14
15
|
class BacnetClient extends EventEmitter {
|
|
15
16
|
//client constructor
|
|
@@ -18,7 +19,6 @@ class BacnetClient extends EventEmitter {
|
|
|
18
19
|
let that = this;
|
|
19
20
|
that.config = config;
|
|
20
21
|
that.deviceList = [];
|
|
21
|
-
that.manualDiscoverQueue = [];
|
|
22
22
|
that.networkTree = {};
|
|
23
23
|
that.lastWhoIs = null;
|
|
24
24
|
that.client = null;
|
|
@@ -52,12 +52,10 @@ class BacnetClient extends EventEmitter {
|
|
|
52
52
|
that.discover_polling_schedule = config.discover_polling_schedule;
|
|
53
53
|
that.deviceId = config.deviceId;
|
|
54
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
55
|
that.device_read_schedule = config.device_read_schedule;
|
|
59
56
|
that.deviceRetryCount = parseInt(config.retries);
|
|
60
57
|
that.sanitise_device_schedule = config.sanitise_device_schedule;
|
|
58
|
+
that.buildTreeException = false;
|
|
61
59
|
|
|
62
60
|
that.readPropertyMultipleOptions = {
|
|
63
61
|
maxSegments: 112,
|
|
@@ -84,7 +82,6 @@ class BacnetClient extends EventEmitter {
|
|
|
84
82
|
//query device task
|
|
85
83
|
const queryDevices = new Task("simple task", () => {
|
|
86
84
|
if (!that.pollInProgress) that.queryDevices();
|
|
87
|
-
that.sanitizeDeviceList();
|
|
88
85
|
});
|
|
89
86
|
|
|
90
87
|
const queryJob = new SimpleIntervalJob({ seconds: parseInt(that.device_read_schedule) }, queryDevices);
|
|
@@ -93,12 +90,13 @@ class BacnetClient extends EventEmitter {
|
|
|
93
90
|
|
|
94
91
|
//buildNetworkTreeData task
|
|
95
92
|
const buildNetworkTree = new Task("simple task", () => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
|
|
94
|
+
that.doTreeBuilder();
|
|
95
|
+
that.countDevices();
|
|
96
|
+
|
|
99
97
|
});
|
|
100
98
|
|
|
101
|
-
const buildNetworkTreeJob = new SimpleIntervalJob({ seconds:
|
|
99
|
+
const buildNetworkTreeJob = new SimpleIntervalJob({ seconds: 5 }, buildNetworkTree);
|
|
102
100
|
|
|
103
101
|
that.scheduler.addSimpleIntervalJob(buildNetworkTreeJob);
|
|
104
102
|
|
|
@@ -106,10 +104,6 @@ class BacnetClient extends EventEmitter {
|
|
|
106
104
|
|
|
107
105
|
setTimeout(() => {
|
|
108
106
|
that.queryDevices();
|
|
109
|
-
that.sanitizeDeviceList();
|
|
110
|
-
that.buildNetworkTreeData().then(function () {
|
|
111
|
-
that.countDevices();
|
|
112
|
-
});
|
|
113
107
|
}, "5000");
|
|
114
108
|
} catch (e) {
|
|
115
109
|
that.logOut("Issue initializing client: ", e);
|
|
@@ -117,7 +111,6 @@ class BacnetClient extends EventEmitter {
|
|
|
117
111
|
|
|
118
112
|
//who is callback
|
|
119
113
|
that.client.on("iAm", (device) => {
|
|
120
|
-
//console.log("found iAm device: ", device);
|
|
121
114
|
if (device.address !== that.config.localIpAdrress) {
|
|
122
115
|
if (that.scanMatrix.length > 0) {
|
|
123
116
|
let matrixMap = that.scanMatrix.filter((ele) => device.deviceId >= ele.start && device.deviceId <= ele.end);
|
|
@@ -127,21 +120,19 @@ class BacnetClient extends EventEmitter {
|
|
|
127
120
|
if (foundIndex == -1) {
|
|
128
121
|
let newBacnetDevice = new BacnetDevice(false, device);
|
|
129
122
|
newBacnetDevice.setLastSeen(Date.now());
|
|
130
|
-
that.updateDeviceName(newBacnetDevice);
|
|
131
123
|
if (newBacnetDevice.getIsMstpDevice()) {
|
|
132
124
|
that.addToParentMstpNetwork(newBacnetDevice);
|
|
133
125
|
}
|
|
134
126
|
that.deviceList.push(newBacnetDevice);
|
|
127
|
+
that.addToNetworkTree(newBacnetDevice);
|
|
135
128
|
} else if (foundIndex !== -1) {
|
|
136
129
|
that.deviceList[foundIndex].updateDeviceConfig(device);
|
|
137
130
|
that.deviceList[foundIndex].setLastSeen(Date.now());
|
|
138
|
-
that.updateDeviceName(that.deviceList[foundIndex]);
|
|
139
|
-
|
|
140
131
|
if (that.deviceList[foundIndex].getIsMstpDevice()) {
|
|
141
132
|
that.addToParentMstpNetwork(that.deviceList[foundIndex]);
|
|
142
133
|
}
|
|
134
|
+
that.addToNetworkTree(that.deviceList[foundIndex]);
|
|
143
135
|
}
|
|
144
|
-
|
|
145
136
|
//emit event for node-red to log
|
|
146
137
|
that.emit("deviceFound", device);
|
|
147
138
|
}
|
|
@@ -151,19 +142,18 @@ class BacnetClient extends EventEmitter {
|
|
|
151
142
|
if (foundIndex == -1) {
|
|
152
143
|
let newBacnetDevice = new BacnetDevice(false, device);
|
|
153
144
|
newBacnetDevice.setLastSeen(Date.now());
|
|
154
|
-
that.updateDeviceName(newBacnetDevice);
|
|
155
145
|
if (newBacnetDevice.getIsMstpDevice()) {
|
|
156
146
|
that.addToParentMstpNetwork(newBacnetDevice);
|
|
157
147
|
}
|
|
158
148
|
that.deviceList.push(newBacnetDevice);
|
|
149
|
+
that.addToNetworkTree(newBacnetDevice);
|
|
159
150
|
} else if (foundIndex !== -1) {
|
|
160
151
|
that.deviceList[foundIndex].updateDeviceConfig(device);
|
|
161
152
|
that.deviceList[foundIndex].setLastSeen(Date.now());
|
|
162
|
-
that.updateDeviceName(that.deviceList[foundIndex]);
|
|
163
|
-
|
|
164
153
|
if (that.deviceList[foundIndex].getIsMstpDevice()) {
|
|
165
154
|
that.addToParentMstpNetwork(that.deviceList[foundIndex]);
|
|
166
155
|
}
|
|
156
|
+
that.addToNetworkTree(that.deviceList[foundIndex]);
|
|
167
157
|
}
|
|
168
158
|
|
|
169
159
|
//emit event for node-red to log
|
|
@@ -190,26 +180,91 @@ class BacnetClient extends EventEmitter {
|
|
|
190
180
|
|
|
191
181
|
testFunction(address, type, instance, property) {
|
|
192
182
|
let that = this;
|
|
193
|
-
|
|
194
183
|
console.log("test function ");
|
|
195
|
-
|
|
196
184
|
that.client.readProperty(
|
|
197
185
|
address,
|
|
198
186
|
{ type: type, instance: instance },
|
|
199
187
|
property,
|
|
200
188
|
that.readPropertyMultipleOptions,
|
|
201
189
|
(err, value) => {
|
|
202
|
-
|
|
203
|
-
console.log("err: ", err);
|
|
204
|
-
}
|
|
205
|
-
|
|
190
|
+
console.log(value);
|
|
206
191
|
if (value) {
|
|
207
|
-
|
|
192
|
+
// If the result has value, resolve the promise
|
|
193
|
+
console.log(value.values[0]);
|
|
194
|
+
value.values[0].values.forEach(function (value) {
|
|
195
|
+
console.log("value: ", value.value);
|
|
196
|
+
});
|
|
197
|
+
} else {
|
|
198
|
+
console.log(err);
|
|
208
199
|
}
|
|
209
200
|
}
|
|
210
201
|
);
|
|
211
202
|
}
|
|
212
203
|
|
|
204
|
+
addToNetworkTree(device) {
|
|
205
|
+
let that = this;
|
|
206
|
+
try {
|
|
207
|
+
const deviceKey = that.createDeviceKey(device);
|
|
208
|
+
let deviceName = device.getDeviceName();
|
|
209
|
+
if (deviceName !== null) {
|
|
210
|
+
const deviceId = device.getDeviceId();
|
|
211
|
+
if (deviceId !== null) {
|
|
212
|
+
let lastIndex = deviceName.lastIndexOf(deviceId);
|
|
213
|
+
if (lastIndex) {
|
|
214
|
+
let formattedName = deviceName.substring(0, lastIndex);
|
|
215
|
+
formattedName = `${formattedName.trim()}_Device_${deviceId}`;
|
|
216
|
+
if (that.networkTree[deviceKey][formattedName] &&
|
|
217
|
+
Object.keys(that.networkTree[deviceKey][formattedName]).length > 0) {
|
|
218
|
+
delete that.networkTree[deviceKey]["device"];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
const json = {
|
|
224
|
+
"objectId": {
|
|
225
|
+
"type": 8,
|
|
226
|
+
"instance": device.getDeviceId()
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
if (that.networkTree[deviceKey] && that.networkTree[deviceKey]["device"]) {
|
|
231
|
+
that.networkTree[deviceKey]["device"]["meta"] = json;
|
|
232
|
+
} else {
|
|
233
|
+
that.networkTree[deviceKey] = {
|
|
234
|
+
"device": {
|
|
235
|
+
"meta": json
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
} catch (e) {
|
|
241
|
+
that.logOut("addToNetworkTree error: ", e);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getProtocolSupported(device) {
|
|
246
|
+
//return protocols support for device
|
|
247
|
+
let that = this;
|
|
248
|
+
return new Promise((resolve, reject) => {
|
|
249
|
+
that.client.readProperty(
|
|
250
|
+
device.getAddress(),
|
|
251
|
+
{ type: baEnum.ObjectType.DEVICE, instance: device.getDeviceId() },
|
|
252
|
+
baEnum.PropertyIdentifier.PROTOCOL_SERVICES_SUPPORTED,
|
|
253
|
+
that.readPropertyMultipleOptions,
|
|
254
|
+
(err, value) => {
|
|
255
|
+
if (err) {
|
|
256
|
+
reject(err);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (value) {
|
|
260
|
+
resolve(value);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
|
|
213
268
|
addToParentMstpNetwork(device) {
|
|
214
269
|
let that = this;
|
|
215
270
|
let address = device.getAddress().address;
|
|
@@ -243,223 +298,262 @@ class BacnetClient extends EventEmitter {
|
|
|
243
298
|
});
|
|
244
299
|
}
|
|
245
300
|
|
|
246
|
-
|
|
301
|
+
purgeDevice(device) {
|
|
247
302
|
let that = this;
|
|
303
|
+
return new Promise((resolve, reject) => {
|
|
304
|
+
try {
|
|
305
|
+
let renderListIndex = that.renderList.findIndex(
|
|
306
|
+
(ele) => ele.deviceId == device.deviceId && ele.ipAddr == device.address
|
|
307
|
+
);
|
|
308
|
+
let deviceListIndex = that.deviceList.findIndex((ele) => ele.getDeviceId() == device.deviceId);
|
|
309
|
+
let deviceKey = device.address + "-" + device.deviceId;
|
|
310
|
+
delete that.networkTree[deviceKey];
|
|
311
|
+
that.renderList.splice(renderListIndex, 1);
|
|
312
|
+
that.deviceList.splice(deviceListIndex, 1);
|
|
248
313
|
|
|
249
|
-
|
|
314
|
+
that.countDevices();
|
|
250
315
|
|
|
251
|
-
|
|
316
|
+
resolve(true);
|
|
317
|
+
} catch (e) {
|
|
318
|
+
reject(e);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
252
322
|
|
|
253
|
-
|
|
323
|
+
updatePointsForDevice(deviceObject) {
|
|
324
|
+
let that = this;
|
|
325
|
+
return new Promise((resolve, reject) => {
|
|
326
|
+
try {
|
|
327
|
+
let device = that.deviceList.find((ele) => ele.getDeviceId() == deviceObject.deviceId);
|
|
328
|
+
that.updateDeviceName(device);
|
|
254
329
|
|
|
255
|
-
function query(index) {
|
|
256
|
-
that.queryPriorityDevices().then(function () {
|
|
257
|
-
let device = that.deviceList[index];
|
|
258
330
|
|
|
259
|
-
|
|
260
|
-
index++;
|
|
331
|
+
//test
|
|
261
332
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
query(index);
|
|
305
|
-
}
|
|
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
|
-
}
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
333
|
+
that.getProtocolSupported(device).then(function (result) {
|
|
334
|
+
console.log("updatePointsForDevice getProtocolSupported ", result.values[0].originalBitString);
|
|
335
|
+
console.log(result.values[0]);
|
|
336
|
+
console.log(result);
|
|
337
|
+
console.log(result.values[0]);
|
|
338
|
+
let decodedValues = decodeBitArray(8, result.values[0].originalBitString.value);
|
|
339
|
+
device.setProtocolServicesSupported(decodedValues);
|
|
340
|
+
}).catch(function (error) {
|
|
341
|
+
that.logOut("getProtocolSupported error: ", error);
|
|
342
|
+
});
|
|
320
343
|
|
|
321
|
-
|
|
322
|
-
let that = this;
|
|
323
|
-
let index = 0;
|
|
324
|
-
query(index);
|
|
344
|
+
//test
|
|
325
345
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
346
|
+
|
|
347
|
+
if (device.getIsProtocolServicesSet() == false) {
|
|
348
|
+
that.getProtocolSupported(device).then(function (result) {
|
|
349
|
+
console.log("updatePointsForDevice getProtocolSupported ", result.values[0].originalBitString);
|
|
350
|
+
let decodedValues = decodeBitArray(8, result.values[0].originalBitString.value);
|
|
351
|
+
device.setProtocolServicesSupported(decodedValues);
|
|
352
|
+
}).catch(function (error) {
|
|
353
|
+
that.logOut("getProtocolSupported error: ", error);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
that
|
|
358
|
+
.getDevicePointList(device)
|
|
359
|
+
.then(function () {
|
|
360
|
+
that
|
|
361
|
+
.buildJsonObject(device)
|
|
362
|
+
.then(function () {
|
|
363
|
+
// do nothing for now
|
|
364
|
+
resolve(true);
|
|
365
|
+
})
|
|
366
|
+
.catch(function (e) {
|
|
367
|
+
that.logOut(`Update points list error 1: ${that.getDeviceAddress(device)}`, e);
|
|
368
|
+
});
|
|
369
|
+
})
|
|
370
|
+
.catch(function (e) {
|
|
371
|
+
that.logOut(`Update points list error 2: ${that.getDeviceAddress(device)}`, e);
|
|
372
|
+
device.setManualDiscoveryMode(true);
|
|
373
|
+
that
|
|
374
|
+
.getDevicePointListWithoutObjectList(device)
|
|
375
|
+
.then(function () {
|
|
334
376
|
that
|
|
335
|
-
.
|
|
377
|
+
.buildJsonObject(device)
|
|
336
378
|
.then(function () {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
.then(function () {
|
|
340
|
-
query(index);
|
|
341
|
-
})
|
|
342
|
-
.catch(function (e) {
|
|
343
|
-
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
344
|
-
query(index);
|
|
345
|
-
});
|
|
379
|
+
// do nothing for now
|
|
380
|
+
resolve(true);
|
|
346
381
|
})
|
|
347
382
|
.catch(function (e) {
|
|
348
|
-
|
|
383
|
+
that.logOut(`Update points list error 3: ${that.getDeviceAddress(device)}`, e);
|
|
349
384
|
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
} else if (index == that.manualDiscoverQueue.length) {
|
|
361
|
-
that.pollInProgress = false;
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
385
|
+
})
|
|
386
|
+
.catch(function (e) {
|
|
387
|
+
that.logOut(`Update points list error 4: ${that.getDeviceAddress(device)}`, e);
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
} catch (e) {
|
|
391
|
+
reject(e);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
365
394
|
}
|
|
366
395
|
|
|
367
|
-
|
|
396
|
+
setDeviceDisplayName(deviceObject, displayName) {
|
|
368
397
|
let that = this;
|
|
369
398
|
return new Promise((resolve, reject) => {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if (priorityDevices.length > 0) {
|
|
373
|
-
let index = 0;
|
|
399
|
+
try {
|
|
400
|
+
let device = that.deviceList.find((ele) => ele.getDeviceId() == deviceObject.deviceId);
|
|
374
401
|
|
|
375
|
-
|
|
402
|
+
device.setDisplayName(displayName);
|
|
376
403
|
|
|
377
|
-
|
|
378
|
-
let device = priorityDevices[index];
|
|
404
|
+
that.buildTreeException = true;
|
|
379
405
|
|
|
380
|
-
|
|
381
|
-
|
|
406
|
+
resolve(true);
|
|
407
|
+
} catch (e) {
|
|
408
|
+
that.logOut("setDeviceDisplayName error: ", e);
|
|
382
409
|
|
|
383
|
-
|
|
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);
|
|
401
|
-
query(index);
|
|
402
|
-
}
|
|
403
|
-
} else {
|
|
404
|
-
query(index);
|
|
405
|
-
}
|
|
406
|
-
} else if (index == priorityDevices.length) {
|
|
407
|
-
resolve();
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
} else if (priorityDevices.length == 0) {
|
|
411
|
-
resolve();
|
|
410
|
+
reject(e);
|
|
412
411
|
}
|
|
413
412
|
});
|
|
414
413
|
}
|
|
415
414
|
|
|
416
|
-
|
|
415
|
+
setPointDisplayName(deviceKey, pointName, pointDisplayName) {
|
|
417
416
|
let that = this;
|
|
417
|
+
return new Promise((resolve, reject) => {
|
|
418
|
+
try {
|
|
419
|
+
if (that.networkTree[deviceKey][pointName]) {
|
|
420
|
+
that.networkTree[deviceKey][pointName].displayName = pointDisplayName;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
that.buildTreeException = true;
|
|
418
424
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
that.manualDiscoverQueue.push(device);
|
|
425
|
+
resolve(true);
|
|
426
|
+
} catch (e) {
|
|
427
|
+
that.logOut("setPointDisplayName error: ", e);
|
|
428
|
+
reject(e);
|
|
424
429
|
}
|
|
425
|
-
}
|
|
426
|
-
device.incrementPointListRetryCount();
|
|
427
|
-
}
|
|
430
|
+
});
|
|
428
431
|
}
|
|
429
432
|
|
|
430
|
-
|
|
433
|
+
importReadList(payload) {
|
|
431
434
|
let that = this;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
435
|
+
|
|
436
|
+
return new Promise((resolve, reject) => {
|
|
437
|
+
try {
|
|
438
|
+
that.buildTreeException = true;
|
|
439
|
+
|
|
440
|
+
for (let key in payload) {
|
|
441
|
+
let device = payload[key];
|
|
442
|
+
for (let pointName in device) {
|
|
443
|
+
let pointObject = device[pointName]
|
|
444
|
+
if (that.networkTree[key][pointName]) {
|
|
445
|
+
that.networkTree[key][pointName] = pointObject;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
resolve(true);
|
|
450
|
+
} catch (e) {
|
|
451
|
+
that.logOut("importReadList error: ", e);
|
|
452
|
+
reject(e);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
438
455
|
}
|
|
439
456
|
|
|
440
|
-
|
|
457
|
+
queryDevices() {
|
|
441
458
|
let that = this;
|
|
442
459
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
460
|
+
that.pollInProgress = true;
|
|
461
|
+
|
|
462
|
+
let index = 0;
|
|
463
|
+
|
|
464
|
+
query(index);
|
|
465
|
+
|
|
466
|
+
function query(index) {
|
|
467
|
+
let device = that.deviceList[index];
|
|
468
|
+
|
|
469
|
+
if (index < that.deviceList.length) {
|
|
470
|
+
index++;
|
|
471
|
+
|
|
472
|
+
if (typeof device == "object") {
|
|
473
|
+
if (device.getIsProtocolServicesSet() == false) {
|
|
474
|
+
that.getProtocolSupported(device).then(function (result) {
|
|
475
|
+
let decodedValues = decodeBitArray(8, result.values[0].originalBitString.value);
|
|
476
|
+
device.setProtocolServicesSupported(decodedValues);
|
|
477
|
+
}).catch(function (error) {
|
|
478
|
+
that.logOut("getProtocolSupported error: ", error);
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
try {
|
|
482
|
+
|
|
483
|
+
if (device.getSegmentation() !== 3) {
|
|
484
|
+
that.updateDeviceName(device);
|
|
485
|
+
that
|
|
486
|
+
.getDevicePointList(device)
|
|
487
|
+
.then(function () {
|
|
488
|
+
that
|
|
489
|
+
.buildJsonObject(device)
|
|
490
|
+
.then(function () {
|
|
491
|
+
query(index);
|
|
492
|
+
})
|
|
493
|
+
.catch(function (e) {
|
|
494
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
495
|
+
query(index);
|
|
496
|
+
});
|
|
497
|
+
})
|
|
498
|
+
.catch(function (e) {
|
|
499
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
500
|
+
that
|
|
501
|
+
.getDevicePointListWithoutObjectList(device)
|
|
502
|
+
.then(function () {
|
|
503
|
+
that
|
|
504
|
+
.buildJsonObject(device)
|
|
505
|
+
.then(function () {
|
|
506
|
+
query(index);
|
|
507
|
+
})
|
|
508
|
+
.catch(function (e) {
|
|
509
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
510
|
+
query(index);
|
|
511
|
+
});
|
|
512
|
+
})
|
|
513
|
+
.catch(function (e) {
|
|
514
|
+
query(index);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
} else if (device.getSegmentation() == 3) {
|
|
519
|
+
|
|
520
|
+
that.updateDeviceName(device);
|
|
521
|
+
that
|
|
522
|
+
.getDevicePointListWithoutObjectList(device)
|
|
523
|
+
.then(function () {
|
|
524
|
+
that
|
|
525
|
+
.buildJsonObject(device)
|
|
526
|
+
.then(function () {
|
|
527
|
+
query(index);
|
|
528
|
+
})
|
|
529
|
+
.catch(function (e) {
|
|
530
|
+
that.logOut(`getDevicePointList error: ${device.getAddress()}`, e);
|
|
531
|
+
query(index);
|
|
532
|
+
});
|
|
533
|
+
})
|
|
534
|
+
.catch(function (e) {
|
|
535
|
+
query(index);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
} catch (e) {
|
|
539
|
+
that.logOut("Error while querying devices: ", e);
|
|
540
|
+
query(index);
|
|
541
|
+
}
|
|
542
|
+
} else {
|
|
543
|
+
that.logOut("queryDevices: invalid device found: ", device);
|
|
544
|
+
query(index);
|
|
545
|
+
}
|
|
546
|
+
} else if (index == that.deviceList.length) {
|
|
547
|
+
that.pollInProgress = false;
|
|
454
548
|
}
|
|
455
|
-
}
|
|
549
|
+
}
|
|
456
550
|
}
|
|
457
551
|
|
|
458
552
|
updateDeviceName(device) {
|
|
459
553
|
let that = this;
|
|
460
554
|
that._getDeviceName(device.getAddress(), device.getDeviceId()).then(function (deviceObject) {
|
|
461
555
|
if (typeof deviceObject.name == "string") {
|
|
462
|
-
device.setDeviceName(deviceObject.name);
|
|
556
|
+
device.setDeviceName(deviceObject.name + " " + device.getDeviceId());
|
|
463
557
|
device.setPointsList(deviceObject.devicePointEntry);
|
|
464
558
|
}
|
|
465
559
|
});
|
|
@@ -475,9 +569,6 @@ class BacnetClient extends EventEmitter {
|
|
|
475
569
|
that.discover_polling_schedule = config.discover_polling_schedule;
|
|
476
570
|
that.deviceId = config.deviceId;
|
|
477
571
|
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
572
|
that.device_read_schedule = config.device_read_schedule;
|
|
482
573
|
|
|
483
574
|
if (that.scheduler !== null) {
|
|
@@ -505,7 +596,6 @@ class BacnetClient extends EventEmitter {
|
|
|
505
596
|
// //query device task
|
|
506
597
|
const queryDevices = new Task("simple task", () => {
|
|
507
598
|
if (!that.pollInProgress) that.queryDevices();
|
|
508
|
-
that.sanitizeDeviceList();
|
|
509
599
|
});
|
|
510
600
|
|
|
511
601
|
const queryJob = new SimpleIntervalJob({ seconds: parseInt(config.device_read_schedule) }, queryDevices);
|
|
@@ -514,7 +604,7 @@ class BacnetClient extends EventEmitter {
|
|
|
514
604
|
|
|
515
605
|
//buildNetworkTreeData task
|
|
516
606
|
const buildNetworkTree = new Task("simple task", () => {
|
|
517
|
-
that.
|
|
607
|
+
that.doTreeBuilder();
|
|
518
608
|
that.countDevices();
|
|
519
609
|
});
|
|
520
610
|
|
|
@@ -545,54 +635,182 @@ class BacnetClient extends EventEmitter {
|
|
|
545
635
|
return newProps;
|
|
546
636
|
}
|
|
547
637
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
638
|
+
findDeviceByKey(key, deviceList, that) {
|
|
639
|
+
return deviceList.find(ele => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` === key);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
getObjectId(pointName, pointConfig, that) {
|
|
643
|
+
// Retrieve the object type based on the point configuration
|
|
644
|
+
const bacObjType = that.getObjectType(pointConfig.meta.objectId.type);
|
|
645
|
+
// Construct the object ID string
|
|
646
|
+
return `${pointName}_${bacObjType}_${pointConfig.meta.objectId.instance}`;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
createDeviceKey(device) {
|
|
650
|
+
// Create a device key by combining the address and device ID
|
|
651
|
+
const address = device.getAddress();
|
|
652
|
+
const deviceId = device.getDeviceId();
|
|
653
|
+
if (typeof address === "object") {
|
|
654
|
+
return `${address.address}-${deviceId}`;
|
|
655
|
+
} else {
|
|
656
|
+
return `${address}-${deviceId}`;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
async doRead(readConfig, outputType, objectPropertyType, readNodeName) {
|
|
662
|
+
const that = this;
|
|
663
|
+
const roundDecimal = readConfig.precision;
|
|
664
|
+
const devicesToRead = Object.keys(readConfig.pointsToRead);
|
|
665
|
+
const bacnetResults = {};
|
|
666
|
+
let pendingRequests = 0;
|
|
667
|
+
|
|
552
668
|
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
669
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
670
|
+
// Process all devices in sequence
|
|
671
|
+
for (let deviceIndex = 0; deviceIndex < devicesToRead.length; deviceIndex++) {
|
|
672
|
+
const key = devicesToRead[deviceIndex];
|
|
673
|
+
const device = that.findDeviceByKey(key, that.deviceList, that);
|
|
674
|
+
if (!device) continue;
|
|
675
|
+
|
|
676
|
+
const deviceName = that.computeDeviceName(device);
|
|
677
|
+
const deviceKey = that.createDeviceKey(device);
|
|
678
|
+
const deviceObject = that.networkTree[deviceKey];
|
|
679
|
+
const maxObjectCount = that.estimateMaxObjectSize(device.getMaxApdu());
|
|
680
|
+
|
|
681
|
+
if (!bacnetResults[deviceName]) {
|
|
682
|
+
bacnetResults[deviceName] = {};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Process points for the current device
|
|
686
|
+
const pointsToRead = readConfig.pointsToRead[key];
|
|
687
|
+
const pointNames = Object.keys(pointsToRead);
|
|
688
|
+
const totalPoints = pointNames.length;
|
|
689
|
+
let requestArray = [];
|
|
690
|
+
let processedPoints = 0; // Counter for processed points
|
|
691
|
+
|
|
692
|
+
// Process each point for the device in batches
|
|
693
|
+
for (let i = 0; i < pointNames.length; i++) {
|
|
694
|
+
const pointName = pointNames[i];
|
|
695
|
+
if (pointName === "deviceName") continue;
|
|
696
|
+
|
|
697
|
+
const pointConfig = pointsToRead[pointName];
|
|
698
|
+
const objectId = that.getObjectId(pointName, pointConfig, that);
|
|
699
|
+
const point = deviceObject[objectId];
|
|
700
|
+
|
|
701
|
+
if (point) {
|
|
702
|
+
point.displayName = pointConfig.displayName;
|
|
703
|
+
|
|
704
|
+
// Prepare request array for batch processing
|
|
705
|
+
requestArray.push({
|
|
706
|
+
objectId: { type: point.meta.objectId.type, instance: point.meta.objectId.instance },
|
|
707
|
+
properties: [{ id: baEnum.PropertyIdentifier.PRESENT_VALUE }],
|
|
708
|
+
pointRef: point,
|
|
709
|
+
pointName: pointName
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Process the batch when the request array is full or the last point is reached
|
|
714
|
+
if (requestArray.length === maxObjectCount || i === pointNames.length - 1) {
|
|
715
|
+
if (device.getProtocolServiceSupport("ReadPropertyMultiple") == true) {
|
|
716
|
+
await that.processBatch(device, requestArray, deviceName, bacnetResults, that, roundDecimal);
|
|
717
|
+
} else {
|
|
718
|
+
await that.processIndividualPoints(device, requestArray, deviceName, bacnetResults, that, roundDecimal);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
requestArray = [];
|
|
722
|
+
// Increment the processed points counter
|
|
723
|
+
processedPoints += maxObjectCount;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Check if all points for the device have been processed
|
|
727
|
+
if (processedPoints >= totalPoints) {
|
|
728
|
+
pendingRequests++;
|
|
729
|
+
// Emit the `values` event for the current device
|
|
730
|
+
that.emit("values", bacnetResults, outputType, objectPropertyType, readNodeName, pendingRequests, devicesToRead.length);
|
|
731
|
+
delete bacnetResults[deviceName];
|
|
732
|
+
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
} catch (error) {
|
|
737
|
+
that.logOut("doRead error: ", error);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
async processBatch(device, requestArray, deviceName, bacnetResults, that, roundDecimal) {
|
|
742
|
+
try {
|
|
743
|
+
const results = await that.updateManyPoints(device, requestArray);
|
|
744
|
+
if (results.error) {
|
|
745
|
+
throw results.error;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Process the results of the batch
|
|
749
|
+
results.value.values.forEach(pointResult => {
|
|
750
|
+
const cacheRef = requestArray.find(ele =>
|
|
751
|
+
ele.pointRef.meta.objectId.type === pointResult.objectId.type &&
|
|
752
|
+
ele.pointRef.meta.objectId.instance === pointResult.objectId.instance
|
|
753
|
+
);
|
|
754
|
+
|
|
755
|
+
if (cacheRef) {
|
|
756
|
+
const pointRef = cacheRef.pointRef;
|
|
757
|
+
const pointNameRef = cacheRef.pointName;
|
|
758
|
+
const val = pointResult.values[0].value[0].value;
|
|
759
|
+
|
|
760
|
+
if (isNumber(val)) {
|
|
761
|
+
pointRef.presentValue = roundDecimalPlaces(val, roundDecimal);
|
|
762
|
+
if (pointRef.meta.objectId.type == 19 || pointRef.meta.objectId.type == 13 || pointRef.meta.objectId.type == 14) {
|
|
763
|
+
if (val != 0) {
|
|
764
|
+
pointRef.presentValue = pointRef.stateTextArray[val - 1].value;
|
|
765
|
+
} else {
|
|
766
|
+
pointRef.presentValue = pointRef.stateTextArray[val].value;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
} else {
|
|
770
|
+
if (typeof val !== "object") {
|
|
771
|
+
pointRef.presentValue = val;
|
|
584
772
|
}
|
|
585
773
|
}
|
|
774
|
+
|
|
775
|
+
// Store the point data in results
|
|
776
|
+
bacnetResults[deviceName][pointNameRef] = pointRef;
|
|
586
777
|
}
|
|
778
|
+
});
|
|
779
|
+
} catch (err) {
|
|
780
|
+
that.logOut("Error processing batch:", err);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
587
783
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
784
|
+
async processIndividualPoints(device, requestArray, deviceName, bacnetResults, that, roundDecimal) {
|
|
785
|
+
for (const request of requestArray) {
|
|
786
|
+
const { objectId, pointRef, pointName } = request;
|
|
787
|
+
try {
|
|
788
|
+
const result = await that.updatePoint(device, pointRef);
|
|
789
|
+
const val = result.values[0].value;
|
|
790
|
+
|
|
791
|
+
if (isNumber(val)) {
|
|
792
|
+
pointRef.presentValue = roundDecimalPlaces(val, roundDecimal);
|
|
793
|
+
} else {
|
|
794
|
+
pointRef.presentValue = val;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Store the point data in results
|
|
798
|
+
bacnetResults[deviceName][pointName] = pointRef;
|
|
799
|
+
} catch (err) {
|
|
800
|
+
that.logOut(`Error updating point ${pointName}:`, err);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
updateManyPoints(device, points) {
|
|
806
|
+
let that = this;
|
|
807
|
+
return new Promise((resolve, reject) => {
|
|
808
|
+
that._readObjectWithRequestArray(device.getAddress(), points, that.readPropertyMultipleOptions).then(function (results) {
|
|
809
|
+
resolve(results);
|
|
810
|
+
}).catch(function (err) {
|
|
811
|
+
reject(err);
|
|
592
812
|
});
|
|
593
|
-
}
|
|
594
|
-
that.logOut("Issue doing read, see error: ", e);
|
|
595
|
-
}
|
|
813
|
+
});
|
|
596
814
|
}
|
|
597
815
|
|
|
598
816
|
updatePoint(device, point) {
|
|
@@ -600,15 +818,13 @@ class BacnetClient extends EventEmitter {
|
|
|
600
818
|
return new Promise((resolve, reject) => {
|
|
601
819
|
that.client.readProperty(
|
|
602
820
|
device.getAddress(),
|
|
603
|
-
{ type: point.
|
|
821
|
+
{ type: point.meta.objectId.type, instance: point.meta.objectId.instance },
|
|
604
822
|
baEnum.PropertyIdentifier.PRESENT_VALUE,
|
|
605
|
-
|
|
823
|
+
that.readPropertyMultipleOptions,
|
|
606
824
|
(err, value) => {
|
|
607
825
|
if (err) {
|
|
608
|
-
//console.log("err ", err);
|
|
609
826
|
reject(err);
|
|
610
827
|
}
|
|
611
|
-
|
|
612
828
|
if (value) {
|
|
613
829
|
resolve(value);
|
|
614
830
|
}
|
|
@@ -617,6 +833,18 @@ class BacnetClient extends EventEmitter {
|
|
|
617
833
|
});
|
|
618
834
|
}
|
|
619
835
|
|
|
836
|
+
estimateMaxObjectSize(apduSize) {
|
|
837
|
+
if (apduSize < 500) {
|
|
838
|
+
return 20;
|
|
839
|
+
} else if (apduSize > 500 && apduSize < 1000) {
|
|
840
|
+
//return Math.round(((apduSize - 30) / 7));
|
|
841
|
+
return 50;
|
|
842
|
+
} else if (apduSize > 1000) {
|
|
843
|
+
//return Math.round(((apduSize - 30) / 7));
|
|
844
|
+
return 100;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
620
848
|
getDeviceAddress(device) {
|
|
621
849
|
switch (typeof device.getAddress()) {
|
|
622
850
|
case "object":
|
|
@@ -825,12 +1053,13 @@ class BacnetClient extends EventEmitter {
|
|
|
825
1053
|
}
|
|
826
1054
|
|
|
827
1055
|
_readObjectFull(device, deviceAddress, type, instance) {
|
|
828
|
-
|
|
1056
|
+
const that = this;
|
|
829
1057
|
const readOptions = {
|
|
830
1058
|
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
831
1059
|
maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
832
1060
|
};
|
|
833
1061
|
|
|
1062
|
+
// Define all properties to be read
|
|
834
1063
|
const allProperties = [
|
|
835
1064
|
{ id: baEnum.PropertyIdentifier.PRESENT_VALUE },
|
|
836
1065
|
{ id: baEnum.PropertyIdentifier.DESCRIPTION },
|
|
@@ -840,77 +1069,151 @@ class BacnetClient extends EventEmitter {
|
|
|
840
1069
|
{ id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER },
|
|
841
1070
|
{ id: baEnum.PropertyIdentifier.SYSTEM_STATUS },
|
|
842
1071
|
{ id: baEnum.PropertyIdentifier.MODIFICATION_DATE },
|
|
843
|
-
{ id: baEnum.PropertyIdentifier.
|
|
1072
|
+
{ id: baEnum.PropertyIdentifier.STATE_TEXT },
|
|
844
1073
|
{ id: baEnum.PropertyIdentifier.RECORD_COUNT },
|
|
845
1074
|
{ id: baEnum.PropertyIdentifier.PRIORITY_ARRAY },
|
|
1075
|
+
{ id: baEnum.PropertyIdentifier.VENDOR_NAME },
|
|
846
1076
|
];
|
|
847
1077
|
|
|
848
1078
|
return new Promise((resolve, reject) => {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
.then(
|
|
1079
|
+
// Try to read all properties at once
|
|
1080
|
+
that._readObject(deviceAddress, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }], readOptions)
|
|
1081
|
+
.then(result => {
|
|
852
1082
|
if (result.value) {
|
|
1083
|
+
// If the result has value, resolve the promise
|
|
853
1084
|
resolve(result);
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
let i = 0;
|
|
858
|
-
readIndividualProperties(i);
|
|
1085
|
+
} else {
|
|
1086
|
+
// If not, proceed to read individual properties
|
|
1087
|
+
readPropertiesIndividually();
|
|
859
1088
|
}
|
|
860
1089
|
})
|
|
861
|
-
.catch(
|
|
862
|
-
|
|
863
|
-
|
|
1090
|
+
.catch(() => {
|
|
1091
|
+
// On error, proceed to read individual properties
|
|
1092
|
+
readPropertiesIndividually();
|
|
864
1093
|
});
|
|
865
1094
|
|
|
866
|
-
|
|
867
|
-
|
|
1095
|
+
// Function to read properties individually
|
|
1096
|
+
const readPropertiesIndividually = () => {
|
|
1097
|
+
const promises = allProperties.map((property, index) => new Promise((propertyResolve) => {
|
|
1098
|
+
that.client.readProperty(
|
|
1099
|
+
deviceAddress,
|
|
1100
|
+
{ type: type, instance: instance },
|
|
1101
|
+
property.id,
|
|
1102
|
+
readOptions,
|
|
1103
|
+
(err, value) => {
|
|
1104
|
+
if (err) {
|
|
1105
|
+
propertyResolve(null);
|
|
1106
|
+
} else {
|
|
1107
|
+
propertyResolve({
|
|
1108
|
+
id: property.id,
|
|
1109
|
+
index: value.property.index,
|
|
1110
|
+
value: value.values,
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
);
|
|
1115
|
+
}));
|
|
1116
|
+
|
|
1117
|
+
Promise.all(promises)
|
|
1118
|
+
.then(resultArray => {
|
|
1119
|
+
// Filter out null results
|
|
1120
|
+
const validResults = resultArray.filter(result => result !== null);
|
|
1121
|
+
|
|
1122
|
+
resolve({
|
|
1123
|
+
error: null,
|
|
1124
|
+
value: {
|
|
1125
|
+
values: [
|
|
1126
|
+
{
|
|
1127
|
+
objectId: {
|
|
1128
|
+
type: type,
|
|
1129
|
+
instance: instance,
|
|
1130
|
+
},
|
|
1131
|
+
values: validResults,
|
|
1132
|
+
},
|
|
1133
|
+
],
|
|
1134
|
+
},
|
|
1135
|
+
});
|
|
1136
|
+
})
|
|
1137
|
+
.catch(reject);
|
|
1138
|
+
};
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
868
1141
|
|
|
869
|
-
function readIndividualProperties(index) {
|
|
870
|
-
const property = allProperties[index];
|
|
871
1142
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
if (err) {
|
|
879
|
-
errorArray.push(err);
|
|
880
|
-
}
|
|
1143
|
+
_readObjectLite(device, deviceAddress, type, instance) {
|
|
1144
|
+
const that = this;
|
|
1145
|
+
const readOptions = {
|
|
1146
|
+
maxSegments: that.readPropertyMultipleOptions.maxSegments,
|
|
1147
|
+
maxApdu: that.readPropertyMultipleOptions.maxApdu,
|
|
1148
|
+
};
|
|
881
1149
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
};
|
|
1150
|
+
// Define all properties to be read
|
|
1151
|
+
const allProperties = [
|
|
1152
|
+
{ id: baEnum.PropertyIdentifier.PRESENT_VALUE },
|
|
1153
|
+
{ id: baEnum.PropertyIdentifier.OBJECT_NAME },
|
|
1154
|
+
];
|
|
888
1155
|
|
|
889
|
-
|
|
890
|
-
|
|
1156
|
+
return new Promise((resolve, reject) => {
|
|
1157
|
+
// Try to read all properties at once
|
|
1158
|
+
that._readObject(deviceAddress, type, instance, allProperties, readOptions)
|
|
1159
|
+
.then(result => {
|
|
1160
|
+
if (result.value) {
|
|
1161
|
+
// If the result has value, resolve the promise
|
|
1162
|
+
resolve(result);
|
|
1163
|
+
} else {
|
|
1164
|
+
// If not, proceed to read individual properties
|
|
1165
|
+
readPropertiesIndividually();
|
|
1166
|
+
}
|
|
1167
|
+
})
|
|
1168
|
+
.catch(() => {
|
|
1169
|
+
// On error, proceed to read individual properties
|
|
1170
|
+
readPropertiesIndividually();
|
|
1171
|
+
});
|
|
891
1172
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1173
|
+
// Function to read properties individually
|
|
1174
|
+
const readPropertiesIndividually = () => {
|
|
1175
|
+
const promises = allProperties.map((property, index) => new Promise((propertyResolve) => {
|
|
1176
|
+
that.client.readProperty(
|
|
1177
|
+
deviceAddress,
|
|
1178
|
+
{ type: type, instance: instance },
|
|
1179
|
+
property.id,
|
|
1180
|
+
readOptions,
|
|
1181
|
+
(err, value) => {
|
|
1182
|
+
if (err) {
|
|
1183
|
+
propertyResolve(null);
|
|
1184
|
+
} else {
|
|
1185
|
+
propertyResolve({
|
|
1186
|
+
id: property.id,
|
|
1187
|
+
index: value.property.index,
|
|
1188
|
+
value: value.values,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
910
1191
|
}
|
|
911
|
-
|
|
912
|
-
);
|
|
913
|
-
|
|
1192
|
+
);
|
|
1193
|
+
}));
|
|
1194
|
+
|
|
1195
|
+
Promise.all(promises)
|
|
1196
|
+
.then(resultArray => {
|
|
1197
|
+
// Filter out null results
|
|
1198
|
+
const validResults = resultArray.filter(result => result !== null);
|
|
1199
|
+
|
|
1200
|
+
resolve({
|
|
1201
|
+
error: null,
|
|
1202
|
+
value: {
|
|
1203
|
+
values: [
|
|
1204
|
+
{
|
|
1205
|
+
objectId: {
|
|
1206
|
+
type: type,
|
|
1207
|
+
instance: instance,
|
|
1208
|
+
},
|
|
1209
|
+
values: validResults,
|
|
1210
|
+
},
|
|
1211
|
+
],
|
|
1212
|
+
},
|
|
1213
|
+
});
|
|
1214
|
+
})
|
|
1215
|
+
.catch(reject);
|
|
1216
|
+
};
|
|
914
1217
|
});
|
|
915
1218
|
}
|
|
916
1219
|
|
|
@@ -1048,6 +1351,7 @@ class BacnetClient extends EventEmitter {
|
|
|
1048
1351
|
reducedDeviceList.forEach((device) => {
|
|
1049
1352
|
delete device["pointsList"];
|
|
1050
1353
|
});
|
|
1354
|
+
|
|
1051
1355
|
resolve({
|
|
1052
1356
|
renderList: that.renderList,
|
|
1053
1357
|
deviceList: reducedDeviceList,
|
|
@@ -1096,42 +1400,6 @@ class BacnetClient extends EventEmitter {
|
|
|
1096
1400
|
});
|
|
1097
1401
|
}
|
|
1098
1402
|
|
|
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
1403
|
sortDevices(a, b) {
|
|
1136
1404
|
if (a.deviceId < b.deviceId) {
|
|
1137
1405
|
return -1;
|
|
@@ -1153,443 +1421,128 @@ class BacnetClient extends EventEmitter {
|
|
|
1153
1421
|
return a.label.localeCompare(b.label);
|
|
1154
1422
|
}
|
|
1155
1423
|
|
|
1156
|
-
|
|
1424
|
+
computeDeviceName(device) {
|
|
1425
|
+
if (device.getDisplayName() !== null && device.getDisplayName() !== "" && device.getDisplayName() !== undefined) {
|
|
1426
|
+
return device.getDisplayName();
|
|
1427
|
+
}
|
|
1428
|
+
return device.getDeviceName();
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
checkInterruptFlag() {
|
|
1157
1432
|
let that = this;
|
|
1158
|
-
|
|
1159
|
-
let displayNameCharThreshold = 40;
|
|
1433
|
+
let BreakException = {};
|
|
1160
1434
|
|
|
1161
|
-
if (that.
|
|
1162
|
-
|
|
1163
|
-
JSON.stringify({
|
|
1164
|
-
renderList: that.renderList,
|
|
1165
|
-
deviceList: that.deviceList,
|
|
1166
|
-
pointList: that.networkTree,
|
|
1167
|
-
renderListCount: that.renderListCount,
|
|
1168
|
-
})
|
|
1169
|
-
);
|
|
1435
|
+
if (that.buildTreeException) {
|
|
1436
|
+
throw BreakException;
|
|
1170
1437
|
}
|
|
1438
|
+
}
|
|
1171
1439
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
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];
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
displayName += "...";
|
|
1204
|
-
}
|
|
1440
|
+
getPointName(object, pointName) {
|
|
1441
|
+
if (object.displayName) {
|
|
1442
|
+
return object.displayName;
|
|
1443
|
+
}
|
|
1444
|
+
return pointName;
|
|
1445
|
+
}
|
|
1205
1446
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
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
|
-
}
|
|
1447
|
+
addUniqueToArray(device, array) {
|
|
1448
|
+
const foundIndex = array.findIndex(ele => ele.getDeviceId() === device.getDeviceId());
|
|
1449
|
+
if (foundIndex === -1) {
|
|
1450
|
+
array.push(device);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1330
1453
|
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1454
|
+
async getDevicesNotRenderedYet() {
|
|
1455
|
+
let that = this;
|
|
1456
|
+
let missingDevices = [];
|
|
1457
|
+
for (let i = 0; i < that.deviceList.length; i++) {
|
|
1458
|
+
const device = that.deviceList[i];
|
|
1459
|
+
if (!device.getIsMstpDevice()) {
|
|
1460
|
+
//ip device
|
|
1461
|
+
const foundIndex = that.renderList.findIndex(ele => ele.deviceId == device.getDeviceId());
|
|
1462
|
+
if (foundIndex == -1) {
|
|
1463
|
+
that.addUniqueToArray(device, missingDevices);
|
|
1464
|
+
}
|
|
1465
|
+
} else {
|
|
1466
|
+
//mstp device
|
|
1467
|
+
const foundParentIndex = that.renderList.findIndex(ele => ele.deviceId == device.getParentDeviceId());
|
|
1468
|
+
if (foundParentIndex == -1) {
|
|
1469
|
+
//parent not existent in tree
|
|
1470
|
+
const parentDeviceIndex = that.deviceList.findIndex(ele => ele.getDeviceId() === device.getParentDeviceId());
|
|
1471
|
+
if (parentDeviceIndex !== -1) {
|
|
1472
|
+
that.addUniqueToArray(that.deviceList[parentDeviceIndex], missingDevices);
|
|
1473
|
+
}
|
|
1474
|
+
that.addUniqueToArray(device, missingDevices);
|
|
1475
|
+
} else {
|
|
1476
|
+
const parentTreeDevice = that.renderList[foundParentIndex];
|
|
1477
|
+
let mstpIndex = -1;
|
|
1478
|
+
parentTreeDevice.children.forEach(child => {
|
|
1479
|
+
if (child.label.includes("MSTP")) {
|
|
1480
|
+
const tempIndex = child.children.findIndex(ele => ele.deviceId == device.getDeviceId());
|
|
1481
|
+
if (tempIndex !== -1) {
|
|
1482
|
+
mstpIndex = tempIndex;
|
|
1344
1483
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
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
|
-
}
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
if (mstpIndex == -1) {
|
|
1487
|
+
that.addUniqueToArray(device, missingDevices);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return missingDevices;
|
|
1493
|
+
}
|
|
1379
1494
|
|
|
1380
|
-
|
|
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
|
-
};
|
|
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
|
-
];
|
|
1457
|
-
} else {
|
|
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
|
-
];
|
|
1468
|
-
}
|
|
1495
|
+
initialTreeBuild = true;
|
|
1469
1496
|
|
|
1470
|
-
|
|
1471
|
-
|
|
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
|
-
);
|
|
1497
|
+
async doTreeBuilder() {
|
|
1498
|
+
let that = this;
|
|
1490
1499
|
|
|
1491
|
-
|
|
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
|
-
}
|
|
1500
|
+
const treeWorker = new treeBuilder(that.deviceList, that.networkTree, that.renderList, that.renderListCount, that.initialTreeBuild);
|
|
1533
1501
|
|
|
1534
|
-
|
|
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,
|
|
1541
|
-
});
|
|
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,
|
|
1551
|
-
});
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1502
|
+
treeWorker.cacheData();
|
|
1554
1503
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1504
|
+
//const missingDevices = await that.getDevicesNotRenderedYet();
|
|
1505
|
+
|
|
1506
|
+
for (let i = 0; i < that.deviceList.length; i++) {
|
|
1507
|
+
let device = that.deviceList[i];
|
|
1508
|
+
await treeWorker.processDevice(device, i);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
that.deviceList = treeWorker.deviceList;
|
|
1512
|
+
that.networkTree = treeWorker.networkTree;
|
|
1513
|
+
that.renderList = treeWorker.renderList;
|
|
1514
|
+
|
|
1515
|
+
that.initialTreeBuild = false;
|
|
1560
1516
|
}
|
|
1561
1517
|
|
|
1562
1518
|
countDevices() {
|
|
1563
1519
|
let that = this;
|
|
1564
|
-
|
|
1565
1520
|
let deviceCount = 0;
|
|
1566
1521
|
|
|
1567
|
-
that.renderList.
|
|
1568
|
-
|
|
1569
|
-
if (
|
|
1570
|
-
device.children
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
} else {
|
|
1580
|
-
deviceCount++;
|
|
1522
|
+
if (that.renderList && that.renderList.length > 0) {
|
|
1523
|
+
that.renderList.forEach(function (device, index) {
|
|
1524
|
+
if (device && device.children.length > 0) {
|
|
1525
|
+
device.children.forEach(function (folder) {
|
|
1526
|
+
if (folder.label == "Points") {
|
|
1527
|
+
//increment for parent device / mstp router
|
|
1528
|
+
deviceCount++;
|
|
1529
|
+
} else if (folder.label.includes("MSTP")) {
|
|
1530
|
+
//increment for mstp device list
|
|
1531
|
+
deviceCount += folder.children.length;
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1581
1534
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1535
|
+
if (index == that.renderList.length - 1) {
|
|
1536
|
+
that.renderListCount = deviceCount;
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1587
1540
|
}
|
|
1588
1541
|
|
|
1589
|
-
buildJsonObject(device
|
|
1542
|
+
buildJsonObject(device) {
|
|
1590
1543
|
let that = this;
|
|
1591
1544
|
let address = device.address;
|
|
1592
|
-
let pointList =
|
|
1545
|
+
let pointList = device.getPointsList();
|
|
1593
1546
|
let requestMutex = new Mutex();
|
|
1594
1547
|
|
|
1595
1548
|
return new Promise(function (resolve, reject) {
|
|
@@ -1597,49 +1550,100 @@ class BacnetClient extends EventEmitter {
|
|
|
1597
1550
|
if (typeof pointList !== "undefined" && pointList.length > 0) {
|
|
1598
1551
|
pointList.forEach(function (point, pointListIndex) {
|
|
1599
1552
|
requestMutex.acquire().then(function (release) {
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
if (result.
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1553
|
+
if (device.getIsInitialQuery()) {
|
|
1554
|
+
that
|
|
1555
|
+
._readObjectLite(device, address, point.value.type, point.value.instance)
|
|
1556
|
+
.then(function (result) {
|
|
1557
|
+
if (!result.error) {
|
|
1558
|
+
if (result.length > 0 && Array.isArray(result)) {
|
|
1559
|
+
promiseArray = result;
|
|
1560
|
+
} else {
|
|
1561
|
+
promiseArray.push(result);
|
|
1562
|
+
}
|
|
1608
1563
|
}
|
|
1609
|
-
}
|
|
1610
1564
|
|
|
1611
|
-
|
|
1565
|
+
release();
|
|
1612
1566
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1567
|
+
if (pointListIndex == pointList.length - 1) {
|
|
1568
|
+
device.setIsInitialQuery(false);
|
|
1569
|
+
that
|
|
1570
|
+
.buildResponse(promiseArray, device)
|
|
1571
|
+
.then(function () {
|
|
1572
|
+
that.lastNetworkPoll = Date.now();
|
|
1573
|
+
resolve({ deviceList: that.deviceList, pointList: that.networkTree });
|
|
1574
|
+
})
|
|
1575
|
+
.catch(function (e) {
|
|
1576
|
+
that.logOut("Error while building json object: ", e);
|
|
1577
|
+
reject(e);
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
})
|
|
1581
|
+
.catch(function (e) {
|
|
1582
|
+
release();
|
|
1583
|
+
that.logOut("_readObjectLite error: ", e);
|
|
1629
1584
|
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1585
|
+
if (pointListIndex == pointList.length - 1) {
|
|
1586
|
+
device.setIsInitialQuery(false);
|
|
1587
|
+
that
|
|
1588
|
+
.buildResponse(promiseArray, device)
|
|
1589
|
+
.then(function () {
|
|
1590
|
+
that.lastNetworkPoll = Date.now();
|
|
1591
|
+
resolve({ deviceList: that.deviceList, pointList: that.networkTree });
|
|
1592
|
+
})
|
|
1593
|
+
.catch(function (e) {
|
|
1594
|
+
that.logOut("Error while building json object: ", e);
|
|
1595
|
+
reject(e);
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
} else {
|
|
1603
|
+
that
|
|
1604
|
+
._readObjectFull(device, address, point.value.type, point.value.instance)
|
|
1605
|
+
.then(function (result) {
|
|
1606
|
+
if (!result.error) {
|
|
1607
|
+
if (result.length > 0 && Array.isArray(result)) {
|
|
1608
|
+
promiseArray = result;
|
|
1609
|
+
} else {
|
|
1610
|
+
promiseArray.push(result);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
release();
|
|
1615
|
+
|
|
1616
|
+
if (pointListIndex == pointList.length - 1) {
|
|
1617
|
+
that
|
|
1618
|
+
.buildResponse(promiseArray, device)
|
|
1619
|
+
.then(function () {
|
|
1620
|
+
that.lastNetworkPoll = Date.now();
|
|
1621
|
+
resolve({ deviceList: that.deviceList, pointList: that.networkTree });
|
|
1622
|
+
})
|
|
1623
|
+
.catch(function (e) {
|
|
1624
|
+
that.logOut("Error while building json object: ", e);
|
|
1625
|
+
reject(e);
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
})
|
|
1629
|
+
.catch(function (e) {
|
|
1630
|
+
release();
|
|
1631
|
+
that.logOut("_readObjectFull error: ", e);
|
|
1632
|
+
|
|
1633
|
+
if (pointListIndex == pointList.length - 1) {
|
|
1634
|
+
that
|
|
1635
|
+
.buildResponse(promiseArray, device)
|
|
1636
|
+
.then(function () {
|
|
1637
|
+
that.lastNetworkPoll = Date.now();
|
|
1638
|
+
resolve({ deviceList: that.deviceList, pointList: that.networkTree });
|
|
1639
|
+
})
|
|
1640
|
+
.catch(function (e) {
|
|
1641
|
+
that.logOut("Error while building json object: ", e);
|
|
1642
|
+
reject(e);
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1643
1647
|
});
|
|
1644
1648
|
});
|
|
1645
1649
|
} else {
|
|
@@ -1651,7 +1655,7 @@ class BacnetClient extends EventEmitter {
|
|
|
1651
1655
|
// Builds response object for a fully qualified
|
|
1652
1656
|
buildResponse(fullObjects, device) {
|
|
1653
1657
|
let that = this;
|
|
1654
|
-
|
|
1658
|
+
const reg = /[$#\/\\+]/gi;
|
|
1655
1659
|
return new Promise(function (resolve, reject) {
|
|
1656
1660
|
let deviceKey =
|
|
1657
1661
|
typeof device.getAddress() == "object"
|
|
@@ -1670,9 +1674,11 @@ class BacnetClient extends EventEmitter {
|
|
|
1670
1674
|
let currobjectId = pointProperty.objectId.type;
|
|
1671
1675
|
let bac_obj = that.getObjectType(currobjectId);
|
|
1672
1676
|
let objectName = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_NAME);
|
|
1673
|
-
let objectType =
|
|
1677
|
+
let objectType = pointProperty.objectId.type;
|
|
1678
|
+
|
|
1674
1679
|
let objectId;
|
|
1675
1680
|
if (objectName !== null && typeof objectName == "string") {
|
|
1681
|
+
objectName = objectName.replace(reg, '');
|
|
1676
1682
|
objectId = objectName + "_" + bac_obj + "_" + pointProperty.objectId.instance;
|
|
1677
1683
|
|
|
1678
1684
|
try {
|
|
@@ -1697,7 +1703,16 @@ class BacnetClient extends EventEmitter {
|
|
|
1697
1703
|
} else if (objectType == 40) {
|
|
1698
1704
|
//character string
|
|
1699
1705
|
values[objectId].presentValue = object.value[0].value;
|
|
1700
|
-
} else {
|
|
1706
|
+
} else if (objectType == 13 || objectType == 14 || objectType == 19) {
|
|
1707
|
+
//check for MSV MSI MSO - for enum state text
|
|
1708
|
+
if (values[objectId].stateTextArray && values[objectId].stateTextArray.length > 0) {
|
|
1709
|
+
if (object.value[0].value == 0) {
|
|
1710
|
+
values[objectId].presentValue = values[objectId].stateTextArray[object.value[0].value].value;
|
|
1711
|
+
} else if (object.value[0].value !== 0) {
|
|
1712
|
+
values[objectId].presentValue = values[objectId].stateTextArray[object.value[0].value - 1].value;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
} else if (objectType !== 8) {
|
|
1701
1716
|
values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, 2);
|
|
1702
1717
|
}
|
|
1703
1718
|
}
|
|
@@ -1711,7 +1726,12 @@ class BacnetClient extends EventEmitter {
|
|
|
1711
1726
|
values[objectId].units = getUnit(object.value[0].value);
|
|
1712
1727
|
break;
|
|
1713
1728
|
case baEnum.PropertyIdentifier.OBJECT_NAME:
|
|
1714
|
-
if (object.value[0] && object.value[0].value)
|
|
1729
|
+
if (object.value[0] && object.value[0].value) {
|
|
1730
|
+
values[objectId].objectName = object.value[0].value.replace(reg, '');
|
|
1731
|
+
if (!values[objectId].displayName) {
|
|
1732
|
+
values[objectId].displayName = object.value[0].value.replace(reg, '');
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1715
1735
|
break;
|
|
1716
1736
|
case baEnum.PropertyIdentifier.OBJECT_TYPE:
|
|
1717
1737
|
if (object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
|
|
@@ -1722,13 +1742,11 @@ class BacnetClient extends EventEmitter {
|
|
|
1722
1742
|
case baEnum.PropertyIdentifier.PROPERTY_LIST:
|
|
1723
1743
|
if (object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
|
|
1724
1744
|
break;
|
|
1725
|
-
|
|
1726
1745
|
case baEnum.PropertyIdentifier.SYSTEM_STATUS:
|
|
1727
1746
|
if (object.value[0]) {
|
|
1728
1747
|
values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
|
|
1729
1748
|
}
|
|
1730
1749
|
break;
|
|
1731
|
-
|
|
1732
1750
|
case baEnum.PropertyIdentifier.MODIFICATION_DATE:
|
|
1733
1751
|
if (object.value[0]) {
|
|
1734
1752
|
values[objectId].modificationDate = object.value[0].value;
|
|
@@ -1751,6 +1769,28 @@ class BacnetClient extends EventEmitter {
|
|
|
1751
1769
|
values[objectId].hasPriorityArray = true;
|
|
1752
1770
|
}
|
|
1753
1771
|
break;
|
|
1772
|
+
case baEnum.PropertyIdentifier.STATE_TEXT:
|
|
1773
|
+
if (object.value) {
|
|
1774
|
+
values[objectId].stateTextArray = object.value;
|
|
1775
|
+
if (typeof values[objectId].presentValue == "number" &&
|
|
1776
|
+
values[objectId].presentValue !== null &&
|
|
1777
|
+
values[objectId].presentValue !== undefined) {
|
|
1778
|
+
const tempIndex = values[objectId].presentValue;
|
|
1779
|
+
if (tempIndex == 0) {
|
|
1780
|
+
values[objectId].presentValue = values[objectId].stateTextArray[tempIndex].value;
|
|
1781
|
+
} else if (tempIndex !== 0) {
|
|
1782
|
+
values[objectId].presentValue = values[objectId].stateTextArray[tempIndex - 1].value;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
break;
|
|
1787
|
+
case baEnum.PropertyIdentifier.VENDOR_NAME:
|
|
1788
|
+
if (object.value) {
|
|
1789
|
+
if (object.value[0].value && typeof object.value[0].value == "string") {
|
|
1790
|
+
values[objectId].vendorName = object.value[0].value;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
break;
|
|
1754
1794
|
}
|
|
1755
1795
|
}
|
|
1756
1796
|
if (
|