@halsystems/red-bacnet 1.1.0 → 1.1.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 +8 -0
- package/common/bacnet.js +17 -9
- package/common/core/concurrent.js +6 -2
- package/common/job/discover_point.js +10 -7
- package/common/job/read_point.js +4 -2
- package/common/job/write_point.js +3 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.1]
|
|
4
|
+
### Added
|
|
5
|
+
- Unit test for BACnet string points
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Reading offline device points run infinitely
|
|
9
|
+
- Unit test failure
|
|
10
|
+
|
|
3
11
|
## [1.1.0]
|
|
4
12
|
### Changed
|
|
5
13
|
- Implemented auto resize batch size when querying using readPropertyMultiple to improve performance
|
package/common/bacnet.js
CHANGED
|
@@ -115,7 +115,6 @@ module.exports = {
|
|
|
115
115
|
if (item?.type === 105) break
|
|
116
116
|
|
|
117
117
|
result.push(item);
|
|
118
|
-
console.log(item)
|
|
119
118
|
} catch (err) {
|
|
120
119
|
void err
|
|
121
120
|
break;
|
|
@@ -155,13 +154,15 @@ module.exports = {
|
|
|
155
154
|
* maximum concurrent point to read in single read mode
|
|
156
155
|
* @param {number} singleReadFailedRetry
|
|
157
156
|
* retry times for single read failed
|
|
157
|
+
* @param {number} concurrentTaskDelay
|
|
158
|
+
* delay between concurrent tasks
|
|
158
159
|
* @returns array of objects
|
|
159
160
|
* eg: [{type: 12, value: {type: 8, instance: 123}, ...],
|
|
160
161
|
* @async
|
|
161
162
|
*/
|
|
162
163
|
smartReadProperty: async function (
|
|
163
164
|
client, device, reqArr, readMethod = 1, maxConcurrentSinglePointRead = 5,
|
|
164
|
-
singleReadFailedRetry = 5
|
|
165
|
+
singleReadFailedRetry = 5, concurrentTaskDelay = 50
|
|
165
166
|
) {
|
|
166
167
|
/* reqArr example
|
|
167
168
|
[{
|
|
@@ -182,8 +183,11 @@ module.exports = {
|
|
|
182
183
|
batchSizes.add(20);
|
|
183
184
|
else {
|
|
184
185
|
const perValueBytes = [30] // typical numeric point is 17 byte
|
|
185
|
-
for (let x = 0; x < perValueBytes.length; x++)
|
|
186
|
-
|
|
186
|
+
for (let x = 0; x < perValueBytes.length; x++) {
|
|
187
|
+
let batchSize = Math.trunc(device.maxApdu / perValueBytes[x])
|
|
188
|
+
if (batchSize > 0)
|
|
189
|
+
batchSizes.add(batchSize)
|
|
190
|
+
}
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
193
|
|
|
@@ -261,7 +265,6 @@ module.exports = {
|
|
|
261
265
|
if (!success) {
|
|
262
266
|
let failedCount = 0
|
|
263
267
|
let result_single = []
|
|
264
|
-
|
|
265
268
|
const dummyEventEmitter = new EventEmitter();
|
|
266
269
|
const tasks = reqArr.slice(reqArrIndexNext).flatMap((req, x) =>
|
|
267
270
|
req.properties.map((prop, y) => ({
|
|
@@ -285,7 +288,7 @@ module.exports = {
|
|
|
285
288
|
return value;
|
|
286
289
|
} catch (err) {
|
|
287
290
|
failedCount++;
|
|
288
|
-
if (
|
|
291
|
+
if (failedCount >= singleReadFailedRetry)
|
|
289
292
|
throw err
|
|
290
293
|
}
|
|
291
294
|
}
|
|
@@ -293,7 +296,7 @@ module.exports = {
|
|
|
293
296
|
);
|
|
294
297
|
|
|
295
298
|
try {
|
|
296
|
-
await concurrentTasks(dummyEventEmitter, tasks, maxConcurrentSinglePointRead);
|
|
299
|
+
await concurrentTasks(dummyEventEmitter, tasks, maxConcurrentSinglePointRead, concurrentTaskDelay);
|
|
297
300
|
} catch (err) {
|
|
298
301
|
void err
|
|
299
302
|
}
|
|
@@ -342,9 +345,14 @@ module.exports = {
|
|
|
342
345
|
* @param {EventEmitter} eventEmitter
|
|
343
346
|
* @param {number} maxConcurrentWrite
|
|
344
347
|
* maximum concurrent point to write
|
|
348
|
+
* @param {number} concurrentTaskDelay
|
|
349
|
+
* delay between concurrent tasks
|
|
345
350
|
* @async
|
|
346
351
|
*/
|
|
347
|
-
smartWriteProperty: async function (
|
|
352
|
+
smartWriteProperty: async function (
|
|
353
|
+
client, device, writePoints, eventEmitter, maxConcurrentWrite,
|
|
354
|
+
concurrentTaskDelay = 50
|
|
355
|
+
) {
|
|
348
356
|
const entries = Object.entries(writePoints);
|
|
349
357
|
|
|
350
358
|
// current writePropertyMultiple will throw ERR_TIMEOUT if any of the write fails
|
|
@@ -370,7 +378,7 @@ module.exports = {
|
|
|
370
378
|
}
|
|
371
379
|
}));
|
|
372
380
|
|
|
373
|
-
await concurrentTasks(eventEmitter, tasks, maxConcurrentWrite);
|
|
381
|
+
await concurrentTasks(eventEmitter, tasks, maxConcurrentWrite, concurrentTaskDelay);
|
|
374
382
|
|
|
375
383
|
// write properties multiples example
|
|
376
384
|
// const values = [
|
|
@@ -17,10 +17,13 @@ module.exports = {
|
|
|
17
17
|
* @param {EventEmitter} eventEmitter - The event emitter to emit events to.
|
|
18
18
|
* @param {Array} tasks - The list of tasks to execute.
|
|
19
19
|
* @param {number} maxConcurrent - The maximum number of concurrent tasks.
|
|
20
|
+
* @param {number} concurrentTaskDelay - The delay between concurrent tasks.
|
|
20
21
|
* @returns {Promise<Array>} - A promise that resolves with an array of results.
|
|
21
22
|
* @async
|
|
22
23
|
*/
|
|
23
|
-
concurrentTasks: async function (
|
|
24
|
+
concurrentTasks: async function (
|
|
25
|
+
eventEmitter, tasks, maxConcurrent, concurrentTaskDelay = 50
|
|
26
|
+
) {
|
|
24
27
|
const executing = new Set();
|
|
25
28
|
const results = [];
|
|
26
29
|
|
|
@@ -44,7 +47,8 @@ module.exports = {
|
|
|
44
47
|
await Promise.race(executing);
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
if (concurrentTaskDelay > 0)
|
|
51
|
+
await delay(concurrentTaskDelay)
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
await Promise.allSettled(executing);
|
|
@@ -53,7 +53,8 @@ module.exports = {
|
|
|
53
53
|
|
|
54
54
|
constructor(
|
|
55
55
|
client, eventEmitter, inputDevices, discoverMode, readMethod, groupExportDeviceCount,
|
|
56
|
-
maxConcurrentDeviceRead, maxConcurrentSinglePointRead,
|
|
56
|
+
maxConcurrentDeviceRead, maxConcurrentSinglePointRead, concurrentTaskDelay = 50,
|
|
57
|
+
name = 'discover point'
|
|
57
58
|
) {
|
|
58
59
|
super();
|
|
59
60
|
this.client = client
|
|
@@ -64,6 +65,7 @@ module.exports = {
|
|
|
64
65
|
this.groupExportDeviceCount = groupExportDeviceCount
|
|
65
66
|
this.maxConcurrentDeviceRead = maxConcurrentDeviceRead
|
|
66
67
|
this.maxConcurrentSinglePointRead = maxConcurrentSinglePointRead
|
|
68
|
+
this.concurrentTaskDelay = concurrentTaskDelay
|
|
67
69
|
this.name = name
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -194,7 +196,7 @@ module.exports = {
|
|
|
194
196
|
|
|
195
197
|
return await readPoints(
|
|
196
198
|
d, objectListFinal, discoverPointEvent, this.name, this.client, this.readMethod,
|
|
197
|
-
this.maxConcurrentSinglePointRead
|
|
199
|
+
this.maxConcurrentSinglePointRead, this.concurrentTaskDelay
|
|
198
200
|
);
|
|
199
201
|
} catch (error) {
|
|
200
202
|
this.eventEmitter.emit(EVENT_ERROR, errMsg(this.name, `Error reading ${d.deviceName} points`, error));
|
|
@@ -237,7 +239,8 @@ module.exports = {
|
|
|
237
239
|
|
|
238
240
|
// ---------------------------------- functions ----------------------------------
|
|
239
241
|
const readPoints = async (
|
|
240
|
-
device, objects, eventEmitter, name, client, readMethod, maxConcurrentSinglePointRead
|
|
242
|
+
device, objects, eventEmitter, name, client, readMethod, maxConcurrentSinglePointRead,
|
|
243
|
+
concurrentTaskDelay
|
|
241
244
|
) => {
|
|
242
245
|
const points = [];
|
|
243
246
|
|
|
@@ -258,7 +261,7 @@ const readPoints = async (
|
|
|
258
261
|
try {
|
|
259
262
|
// First request - get basic properties
|
|
260
263
|
const result = await smartReadProperty(
|
|
261
|
-
client, device, reqArr, readMethod, maxConcurrentSinglePointRead, 50
|
|
264
|
+
client, device, reqArr, readMethod, maxConcurrentSinglePointRead, 50, concurrentTaskDelay
|
|
262
265
|
);
|
|
263
266
|
|
|
264
267
|
// Process basic properties first
|
|
@@ -279,7 +282,7 @@ const readPoints = async (
|
|
|
279
282
|
try {
|
|
280
283
|
// Force use single read on state text to reduce loss especially long text
|
|
281
284
|
const stateTextResult = await smartReadProperty(
|
|
282
|
-
client, device, stateTextReqArr, 0, 1, 50
|
|
285
|
+
client, device, stateTextReqArr, 0, 1, 50, concurrentTaskDelay
|
|
283
286
|
);
|
|
284
287
|
|
|
285
288
|
// Update points with STATE_TEXT
|
|
@@ -374,7 +377,7 @@ const setPointValues = (point, i) => {
|
|
|
374
377
|
|
|
375
378
|
const processValue = (value, facets) => {
|
|
376
379
|
if (value?.errorClass != null && value?.errorCode != null) return null;
|
|
377
|
-
const match = facets
|
|
380
|
+
const match = facets?.match(/precision:(\d+)/);
|
|
378
381
|
const precision = match ? +match[1] : null;
|
|
379
382
|
|
|
380
383
|
if (typeof value === 'number')
|
|
@@ -382,4 +385,4 @@ const processValue = (value, facets) => {
|
|
|
382
385
|
else
|
|
383
386
|
return value
|
|
384
387
|
|
|
385
|
-
};
|
|
388
|
+
};
|
package/common/job/read_point.js
CHANGED
|
@@ -23,7 +23,7 @@ module.exports = {
|
|
|
23
23
|
|
|
24
24
|
constructor(
|
|
25
25
|
client, eventEmitter, devices, points, readMethod, maxConcurrentDeviceRead = 2,
|
|
26
|
-
maxConcurrentSinglePointRead = 5, name = 'read point'
|
|
26
|
+
maxConcurrentSinglePointRead = 5, concurrentTaskDelay = 50, name = 'read point'
|
|
27
27
|
) {
|
|
28
28
|
super();
|
|
29
29
|
this.client = client
|
|
@@ -33,6 +33,7 @@ module.exports = {
|
|
|
33
33
|
this.readMethod = readMethod
|
|
34
34
|
this.maxConcurrentDeviceRead = maxConcurrentDeviceRead
|
|
35
35
|
this.maxConcurrentSinglePointRead = maxConcurrentSinglePointRead
|
|
36
|
+
this.concurrentTaskDelay = concurrentTaskDelay
|
|
36
37
|
this.name = name
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -219,7 +220,8 @@ module.exports = {
|
|
|
219
220
|
id: k,
|
|
220
221
|
task: async () => {
|
|
221
222
|
return await smartReadProperty(
|
|
222
|
-
this.client, v.device, v.points, this.readMethod,
|
|
223
|
+
this.client, v.device, v.points, this.readMethod,
|
|
224
|
+
this.maxConcurrentSinglePointRead, 5, this.concurrentTaskDelay
|
|
223
225
|
);
|
|
224
226
|
}
|
|
225
227
|
}));
|
|
@@ -25,6 +25,7 @@ module.exports = {
|
|
|
25
25
|
constructor(
|
|
26
26
|
client, eventEmitter, devices, points, writePoints,
|
|
27
27
|
maxConcurrentDeviceWrite = 2, maxConcurrentPointWrite = 1,
|
|
28
|
+
concurrentTaskDelay = 50,
|
|
28
29
|
name = 'write point'
|
|
29
30
|
) {
|
|
30
31
|
super();
|
|
@@ -35,6 +36,7 @@ module.exports = {
|
|
|
35
36
|
this.writePoints = writePoints
|
|
36
37
|
this.maxConcurrentDeviceWrite = maxConcurrentDeviceWrite
|
|
37
38
|
this.maxConcurrentPointWrite = maxConcurrentPointWrite
|
|
39
|
+
this.concurrentTaskDelay = concurrentTaskDelay
|
|
38
40
|
this.name = name
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -277,7 +279,7 @@ module.exports = {
|
|
|
277
279
|
task: async () => {
|
|
278
280
|
return await smartWriteProperty(
|
|
279
281
|
this.client, v.device, v.writePoints, smartWriteEvent,
|
|
280
|
-
this.maxConcurrentPointWrite
|
|
282
|
+
this.maxConcurrentPointWrite, this.concurrentTaskDelay
|
|
281
283
|
);
|
|
282
284
|
}
|
|
283
285
|
}));
|