node-opcua-aggregates 2.54.0 → 2.57.0
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/.mocharc.yml +7 -7
- package/LICENSE +20 -20
- package/bin/sample_aggregate_server.js +14 -14
- package/dist/aggregates.js +2 -2
- package/dist/aggregates.js.map +1 -1
- package/dist/average.js +6 -5
- package/dist/average.js.map +1 -1
- package/dist/common.js +12 -2
- package/dist/common.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interpolate.d.ts +1 -1
- package/dist/interpolate.js +8 -12
- package/dist/interpolate.js.map +1 -1
- package/dist/minmax.js +3 -2
- package/dist/minmax.js.map +1 -1
- package/dist/read_processed_details.d.ts +2 -2
- package/dist/read_processed_details.js +41 -38
- package/dist/read_processed_details.js.map +1 -1
- package/nyc.config.js +16 -16
- package/package.json +17 -15
- package/source/aggregates.ts +284 -277
- package/source/average.ts +71 -74
- package/source/common.ts +23 -10
- package/source/index.ts +11 -17
- package/source/interpolate.ts +14 -20
- package/source/interval.ts +3 -3
- package/source/minmax.ts +231 -231
- package/source/read_processed_details.ts +149 -139
- package/dist2/aggregates.d.ts +0 -7
- package/dist2/aggregates.js +0 -201
- package/dist2/aggregates.js.map +0 -1
- package/dist2/average.d.ts +0 -3
- package/dist2/average.js +0 -61
- package/dist2/average.js.map +0 -1
- package/dist2/common.d.ts +0 -8
- package/dist2/common.js +0 -89
- package/dist2/common.js.map +0 -1
- package/dist2/index.d.ts +0 -11
- package/dist2/index.js +0 -29
- package/dist2/index.js.map +0 -1
- package/dist2/interpolate.d.ts +0 -16
- package/dist2/interpolate.js +0 -135
- package/dist2/interpolate.js.map +0 -1
- package/dist2/interval.d.ts +0 -49
- package/dist2/interval.js +0 -165
- package/dist2/interval.js.map +0 -1
- package/dist2/minmax.d.ts +0 -18
- package/dist2/minmax.js +0 -149
- package/dist2/minmax.js.map +0 -1
- package/dist2/read_processed_details.d.ts +0 -6
- package/dist2/read_processed_details.js +0 -116
- package/dist2/read_processed_details.js.map +0 -1
package/source/average.ts
CHANGED
|
@@ -1,74 +1,71 @@
|
|
|
1
|
-
import { UAVariable } from "node-opcua-address-space";
|
|
2
|
-
import { DataValue } from "node-opcua-data-value";
|
|
3
|
-
import { Variant, DataType } from "node-opcua-variant";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
endDate
|
|
71
|
-
|
|
72
|
-
) {
|
|
73
|
-
return getAggregateData(node, processingInterval, startDate, endDate, calculateIntervalAverageValue, callback);
|
|
74
|
-
}
|
|
1
|
+
import { UAVariable } from "node-opcua-address-space";
|
|
2
|
+
import { DataValue } from "node-opcua-data-value";
|
|
3
|
+
import { Variant, DataType } from "node-opcua-variant";
|
|
4
|
+
import { StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
5
|
+
|
|
6
|
+
import { getAggregateData } from "./common";
|
|
7
|
+
import { Interval, AggregateConfigurationOptions, isGood } from "./interval";
|
|
8
|
+
|
|
9
|
+
function calculateIntervalAverageValue(interval: Interval, options: AggregateConfigurationOptions): DataValue {
|
|
10
|
+
const indexStart = interval.index;
|
|
11
|
+
let statusCode: StatusCode;
|
|
12
|
+
let isPartial = interval.isPartial;
|
|
13
|
+
|
|
14
|
+
const isRaw = false;
|
|
15
|
+
let hasBad = false;
|
|
16
|
+
|
|
17
|
+
const values: number[] = [];
|
|
18
|
+
|
|
19
|
+
for (let i = indexStart; i < indexStart + interval.count; i++) {
|
|
20
|
+
const dataValue = interval.dataValues[i];
|
|
21
|
+
|
|
22
|
+
if (dataValue.statusCode === StatusCodes.BadNoData) {
|
|
23
|
+
isPartial = true;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!isGood(dataValue.statusCode)) {
|
|
28
|
+
hasBad = true;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
values.push(dataValue.value.value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isRaw) {
|
|
35
|
+
if (hasBad) {
|
|
36
|
+
statusCode = StatusCodes.UncertainDataSubNormal;
|
|
37
|
+
} else {
|
|
38
|
+
statusCode = StatusCodes.Good;
|
|
39
|
+
}
|
|
40
|
+
} else if (hasBad) {
|
|
41
|
+
statusCode = StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, "HistorianCalculated");
|
|
42
|
+
} else {
|
|
43
|
+
statusCode = StatusCode.makeStatusCode(StatusCodes.Good, "HistorianCalculated");
|
|
44
|
+
}
|
|
45
|
+
if (values.length === 0) {
|
|
46
|
+
return new DataValue({
|
|
47
|
+
sourceTimestamp: interval.startTime,
|
|
48
|
+
statusCode: StatusCodes.BadNoData
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const mean = values.reduce((p, c) => p + c, 0) / values.length;
|
|
52
|
+
|
|
53
|
+
return new DataValue({
|
|
54
|
+
sourceTimestamp: interval.startTime,
|
|
55
|
+
statusCode: statusCode as StatusCode,
|
|
56
|
+
value: {
|
|
57
|
+
dataType: DataType.Double,
|
|
58
|
+
value: mean
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getAverageData(
|
|
64
|
+
node: UAVariable,
|
|
65
|
+
processingInterval: number,
|
|
66
|
+
startDate: Date,
|
|
67
|
+
endDate: Date,
|
|
68
|
+
callback: (err: Error | null, dataValues?: DataValue[]) => void
|
|
69
|
+
): void {
|
|
70
|
+
getAggregateData(node, processingInterval, startDate, endDate, calculateIntervalAverageValue, callback);
|
|
71
|
+
}
|
package/source/common.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opca-aggregates
|
|
3
3
|
*/
|
|
4
|
-
import { SessionContext, UAVariable } from "node-opcua-address-space";
|
|
4
|
+
import { SessionContext, UAVariable, ContinuationPointManager, ContinuationPoint } from "node-opcua-address-space";
|
|
5
5
|
import { NodeClass } from "node-opcua-data-model";
|
|
6
6
|
import { DataValue } from "node-opcua-data-value";
|
|
7
7
|
import { HistoryData, HistoryReadResult, ReadRawModifiedDetails } from "node-opcua-service-history";
|
|
8
8
|
import { StatusCode } from "node-opcua-status-code";
|
|
9
|
+
import { coerceNodeId } from "node-opcua-nodeid";
|
|
9
10
|
|
|
10
11
|
import { getAggregateConfiguration } from "./aggregates";
|
|
11
12
|
import { getInterval, Interval, AggregateConfigurationOptionsEx } from "./interval";
|
|
@@ -56,7 +57,6 @@ function processAggregateData(
|
|
|
56
57
|
setImmediate(() => {
|
|
57
58
|
callback(null, results);
|
|
58
59
|
});
|
|
59
|
-
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export function getAggregateData(
|
|
@@ -66,8 +66,7 @@ export function getAggregateData(
|
|
|
66
66
|
endDate: Date,
|
|
67
67
|
lambda: (interval: Interval, aggregateConfiguration: AggregateConfigurationOptionsEx) => DataValue,
|
|
68
68
|
callback: (err: Error | null, dataValues?: DataValue[]) => void
|
|
69
|
-
) {
|
|
70
|
-
|
|
69
|
+
): void {
|
|
71
70
|
/* istanbul ignore next */
|
|
72
71
|
if (node.nodeClass !== NodeClass.Variable) {
|
|
73
72
|
throw new Error("node must be UAVariable");
|
|
@@ -78,17 +77,30 @@ export function getAggregateData(
|
|
|
78
77
|
throw new Error("Invalid processing interval, shall be greater than 0");
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
const
|
|
80
|
+
const continuationPointManager = new ContinuationPointManager();
|
|
81
|
+
const context = new SessionContext({
|
|
82
|
+
session: {
|
|
83
|
+
continuationPointManager,
|
|
84
|
+
getSessionId: () => coerceNodeId("i=0")
|
|
85
|
+
}
|
|
86
|
+
});
|
|
82
87
|
const historyReadDetails = new ReadRawModifiedDetails({
|
|
83
88
|
endTime: endDate,
|
|
84
89
|
startTime: startDate,
|
|
90
|
+
isReadModified: false,
|
|
91
|
+
numValuesPerNode: 0
|
|
92
|
+
// returnBounds: true,
|
|
85
93
|
});
|
|
86
94
|
const indexRange = null;
|
|
87
95
|
const dataEncoding = null;
|
|
88
|
-
const continuationPoint = null;
|
|
89
|
-
node.historyRead(
|
|
96
|
+
const continuationPoint: ContinuationPoint | null = null;
|
|
97
|
+
node.historyRead(
|
|
98
|
+
context,
|
|
99
|
+
historyReadDetails,
|
|
100
|
+
indexRange,
|
|
101
|
+
dataEncoding,
|
|
102
|
+
{ continuationPoint },
|
|
90
103
|
(err: Error | null, result?: HistoryReadResult) => {
|
|
91
|
-
|
|
92
104
|
/* istanbul ignore next */
|
|
93
105
|
if (err) {
|
|
94
106
|
return callback(err);
|
|
@@ -98,10 +110,11 @@ export function getAggregateData(
|
|
|
98
110
|
const dataValues = historyData.dataValues || [];
|
|
99
111
|
|
|
100
112
|
processAggregateData(node, processingInterval, startDate, endDate, dataValues, lambda, callback);
|
|
101
|
-
}
|
|
113
|
+
}
|
|
114
|
+
);
|
|
102
115
|
}
|
|
103
116
|
|
|
104
|
-
export function interpolateValue(dataValue1: DataValue, dataValue2: DataValue, date: Date) {
|
|
117
|
+
export function interpolateValue(dataValue1: DataValue, dataValue2: DataValue, date: Date): DataValue {
|
|
105
118
|
const t0 = dataValue1.sourceTimestamp!.getTime();
|
|
106
119
|
const t = date.getTime();
|
|
107
120
|
const t1 = dataValue2.sourceTimestamp!.getTime();
|
package/source/index.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module node-opca-aggregates
|
|
3
|
-
*/
|
|
4
|
-
export {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export * from "./
|
|
10
|
-
export * from "./
|
|
11
|
-
export
|
|
12
|
-
export * from "./common";
|
|
13
|
-
export * from "./average";
|
|
14
|
-
export * from "./read_processed_details";
|
|
15
|
-
export {
|
|
16
|
-
AggregateFunction
|
|
17
|
-
} from "node-opcua-constants";
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opca-aggregates
|
|
3
|
+
*/
|
|
4
|
+
export { addAggregateSupport, installAggregateConfigurationOptions, getAggregateConfiguration } from "./aggregates";
|
|
5
|
+
export * from "./interpolate";
|
|
6
|
+
export * from "./minmax";
|
|
7
|
+
export * from "./interval";
|
|
8
|
+
export * from "./common";
|
|
9
|
+
export * from "./average";
|
|
10
|
+
export * from "./read_processed_details";
|
|
11
|
+
export { AggregateFunction } from "node-opcua-constants";
|
package/source/interpolate.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module node-
|
|
2
|
+
* @module node-opcua-aggregates
|
|
3
3
|
*/
|
|
4
4
|
// excerpt from OPC Unified Architecture, Part 13 21 Release 1.04
|
|
5
5
|
//
|
|
@@ -47,7 +47,8 @@ import {
|
|
|
47
47
|
_findGoodDataValueBefore,
|
|
48
48
|
adjustProcessingOptions,
|
|
49
49
|
AggregateConfigurationOptionsEx,
|
|
50
|
-
Interval,
|
|
50
|
+
Interval,
|
|
51
|
+
isBad,
|
|
51
52
|
isGood
|
|
52
53
|
} from "./interval";
|
|
53
54
|
|
|
@@ -62,11 +63,10 @@ import {
|
|
|
62
63
|
If for an interval neither ratio applies then that interval is Uncertain_DataSubNormal.
|
|
63
64
|
*/
|
|
64
65
|
export function interpolatedValue(interval: Interval, options: AggregateConfigurationOptionsEx): DataValue {
|
|
65
|
-
|
|
66
66
|
options = adjustProcessingOptions(options);
|
|
67
67
|
|
|
68
|
-
assert(Object.prototype.hasOwnProperty.call(options,"useSlopedExtrapolation"));
|
|
69
|
-
assert(Object.prototype.hasOwnProperty.call(options,"treatUncertainAsBad"));
|
|
68
|
+
assert(Object.prototype.hasOwnProperty.call(options, "useSlopedExtrapolation"));
|
|
69
|
+
assert(Object.prototype.hasOwnProperty.call(options, "treatUncertainAsBad"));
|
|
70
70
|
|
|
71
71
|
const bTreatUncertainAsBad = options.treatUncertainAsBad!;
|
|
72
72
|
|
|
@@ -77,10 +77,9 @@ export function interpolatedValue(interval: Interval, options: AggregateConfigur
|
|
|
77
77
|
const interpValue = new DataValue({
|
|
78
78
|
sourceTimestamp: interval.startTime,
|
|
79
79
|
statusCode: StatusCodes.Bad,
|
|
80
|
-
value: previousDataValue.value
|
|
80
|
+
value: previousDataValue.value
|
|
81
81
|
});
|
|
82
|
-
interpValue.statusCode =
|
|
83
|
-
StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, "HistorianInterpolated");
|
|
82
|
+
interpValue.statusCode = StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, "HistorianInterpolated");
|
|
84
83
|
return interpValue;
|
|
85
84
|
};
|
|
86
85
|
|
|
@@ -93,7 +92,7 @@ export function interpolatedValue(interval: Interval, options: AggregateConfigur
|
|
|
93
92
|
return new DataValue({
|
|
94
93
|
sourceTimestamp: interval.startTime,
|
|
95
94
|
statusCode: StatusCodes.BadNoData,
|
|
96
|
-
value: undefined
|
|
95
|
+
value: undefined
|
|
97
96
|
});
|
|
98
97
|
}
|
|
99
98
|
if (!options.useSlopedExtrapolation) {
|
|
@@ -111,13 +110,12 @@ export function interpolatedValue(interval: Interval, options: AggregateConfigur
|
|
|
111
110
|
// tslint:disable:no-bitwise
|
|
112
111
|
if (prev2.index + 1 < prev1.index || prev1.index < interval.dataValues.length - 1) {
|
|
113
112
|
// some bad data exist in between = change status code
|
|
114
|
-
const mask =
|
|
113
|
+
const mask = 0x0000ffffff;
|
|
115
114
|
const extraBits = interpVal.statusCode.value & mask;
|
|
116
115
|
interpVal.statusCode = StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, extraBits);
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
return interpVal;
|
|
120
|
-
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
/* istanbul ignore next */
|
|
@@ -166,16 +164,12 @@ export function interpolatedValue(interval: Interval, options: AggregateConfigur
|
|
|
166
164
|
// x is a value at ‘x’ and Tx is the timestamp associated with Vx.
|
|
167
165
|
const interpolatedDataValue = interpolateValue(before.dataValue, next.dataValue, interval.startTime);
|
|
168
166
|
|
|
169
|
-
if (before.index + 1 < next.index
|
|
170
|
-
|| !isGood(next.dataValue.statusCode)
|
|
171
|
-
|| !isGood(before.dataValue.statusCode)
|
|
172
|
-
) {
|
|
167
|
+
if (before.index + 1 < next.index || !isGood(next.dataValue.statusCode) || !isGood(before.dataValue.statusCode)) {
|
|
173
168
|
// tslint:disable:no-bitwise
|
|
174
169
|
// some bad data exist in between = change status code
|
|
175
|
-
const mask =
|
|
170
|
+
const mask = 0x0000ffffff;
|
|
176
171
|
const extraBits = interpolatedDataValue.statusCode.value & mask;
|
|
177
|
-
interpolatedDataValue.statusCode =
|
|
178
|
-
StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, extraBits);
|
|
172
|
+
interpolatedDataValue.statusCode = StatusCode.makeStatusCode(StatusCodes.UncertainDataSubNormal, extraBits);
|
|
179
173
|
}
|
|
180
174
|
// check if uncertain or bad value exist between before/next
|
|
181
175
|
// todo
|
|
@@ -196,6 +190,6 @@ export function getInterpolatedData(
|
|
|
196
190
|
startDate: Date,
|
|
197
191
|
endDate: Date,
|
|
198
192
|
callback: (err: Error | null, dataValues?: DataValue[]) => void
|
|
199
|
-
) {
|
|
200
|
-
|
|
193
|
+
): void {
|
|
194
|
+
getAggregateData(node, processingInterval, startDate, endDate, interpolatedValue, callback);
|
|
201
195
|
}
|
package/source/interval.ts
CHANGED
|
@@ -117,7 +117,7 @@ export class Interval {
|
|
|
117
117
|
/**
|
|
118
118
|
* returns true if a raw data exists at start
|
|
119
119
|
*/
|
|
120
|
-
public hasRawDataAsStart() {
|
|
120
|
+
public hasRawDataAsStart(): boolean {
|
|
121
121
|
const index = this.index;
|
|
122
122
|
if (index < 0) {
|
|
123
123
|
return false;
|
|
@@ -131,11 +131,11 @@ export class Interval {
|
|
|
131
131
|
* just preceding this interval
|
|
132
132
|
* @returns {*}
|
|
133
133
|
*/
|
|
134
|
-
public beforeStartDataValue(bTreatUncertainAsBad: boolean) {
|
|
134
|
+
public beforeStartDataValue(bTreatUncertainAsBad: boolean): DataValueWithIndex {
|
|
135
135
|
return _findGoodDataValueBefore(this.dataValues, this.index, bTreatUncertainAsBad);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
public nextStartDataValue(bTreatUncertainAsBad: boolean) {
|
|
138
|
+
public nextStartDataValue(bTreatUncertainAsBad: boolean): DataValueWithIndex {
|
|
139
139
|
return _findGoodDataValueAfter(this.dataValues, this.index, bTreatUncertainAsBad);
|
|
140
140
|
}
|
|
141
141
|
|