node-opcua-aggregates 2.98.0 → 2.98.2
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/dist/aggregates.d.ts +22 -0
- package/dist/aggregates.js +276 -0
- package/dist/aggregates.js.map +1 -0
- package/dist/average.d.ts +3 -0
- package/dist/average.js +61 -0
- package/dist/average.js.map +1 -0
- package/dist/calculate_bad_good.d.ts +10 -0
- package/dist/calculate_bad_good.js +118 -0
- package/dist/calculate_bad_good.js.map +1 -0
- package/dist/common.d.ts +8 -0
- package/dist/common.js +94 -0
- package/dist/common.js.map +1 -0
- package/dist/count.d.ts +3 -0
- package/dist/count.js +87 -0
- package/dist/count.js.map +1 -0
- package/dist/duration_bad.d.ts +4 -0
- package/dist/duration_bad.js +32 -0
- package/dist/duration_bad.js.map +1 -0
- package/dist/duration_good.d.ts +4 -0
- package/dist/duration_good.js +32 -0
- package/dist/duration_good.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +16 -0
- package/dist/interpolate.js +131 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/interval.d.ts +62 -0
- package/dist/interval.js +200 -0
- package/dist/interval.js.map +1 -0
- package/dist/minmax.d.ts +18 -0
- package/dist/minmax.js +149 -0
- package/dist/minmax.js.map +1 -0
- package/dist/percent_bad.d.ts +4 -0
- package/dist/percent_bad.js +25 -0
- package/dist/percent_bad.js.map +1 -0
- package/dist/percent_good.d.ts +7 -0
- package/dist/percent_good.js +49 -0
- package/dist/percent_good.js.map +1 -0
- package/dist/read_processed_details.d.ts +6 -0
- package/dist/read_processed_details.js +144 -0
- package/dist/read_processed_details.js.map +1 -0
- package/package.json +22 -18
- package/.mocharc.yml +0 -7
- package/bin/sample_aggregate_server.js +0 -15
- package/nyc.config.js +0 -16
package/dist/count.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCountData = void 0;
|
|
4
|
+
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
5
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
6
|
+
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
7
|
+
const common_1 = require("./common");
|
|
8
|
+
const interval_1 = require("./interval");
|
|
9
|
+
/**
|
|
10
|
+
* The Count Aggregate retrieves a count of all the raw values within an interval.
|
|
11
|
+
* If one or more raw values are non-Good, they are not included in the count, and the Aggregate
|
|
12
|
+
* StatusCode is determined using the StatusCode Calculation for non-time based Aggregates.
|
|
13
|
+
* If no Good data exists for an interval, the count is zero.
|
|
14
|
+
*/
|
|
15
|
+
function calculateCountValue(interval, options) {
|
|
16
|
+
const indexStart = interval.index;
|
|
17
|
+
let statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
18
|
+
let isPartial = interval.isPartial;
|
|
19
|
+
let nbBad = 0;
|
|
20
|
+
let nbGood = 0;
|
|
21
|
+
let nbUncertain = 0;
|
|
22
|
+
let badDuration = 0;
|
|
23
|
+
let uncertainDuration = 0;
|
|
24
|
+
let goodDuration = 0;
|
|
25
|
+
for (let i = indexStart; i < indexStart + interval.count; i++) {
|
|
26
|
+
const dataValue = interval.dataValues[i];
|
|
27
|
+
if (dataValue.statusCode.equals(node_opcua_status_code_1.StatusCodes.BadNoData)) {
|
|
28
|
+
isPartial = true;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const regionDuration = interval.regionDuration(i);
|
|
32
|
+
if (dataValue.statusCode.isBad()) {
|
|
33
|
+
nbBad++;
|
|
34
|
+
badDuration += regionDuration;
|
|
35
|
+
}
|
|
36
|
+
else if ((0, interval_1.isUncertain)(dataValue.statusCode)) {
|
|
37
|
+
nbUncertain++;
|
|
38
|
+
uncertainDuration += regionDuration;
|
|
39
|
+
}
|
|
40
|
+
else if (dataValue.statusCode.isGoodish()) {
|
|
41
|
+
nbGood++;
|
|
42
|
+
goodDuration += regionDuration;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const partialFlag = isPartial ? node_opcua_status_code_1.extraStatusCodeBits.HistorianPartial : 0;
|
|
46
|
+
// console.log(" ", goodDuration, uncertainDuration, badDuration);
|
|
47
|
+
if (nbBad > 0) {
|
|
48
|
+
const duration = interval.duration();
|
|
49
|
+
if (options.treatUncertainAsBad) {
|
|
50
|
+
badDuration += uncertainDuration;
|
|
51
|
+
}
|
|
52
|
+
const actualPercentDataBad = (badDuration / duration) * 100.0;
|
|
53
|
+
const percentDataBad = options.percentDataBad === undefined ? 100 : options.percentDataBad;
|
|
54
|
+
if (actualPercentDataBad >= percentDataBad) {
|
|
55
|
+
return new node_opcua_data_value_1.DataValue({
|
|
56
|
+
sourceTimestamp: interval.startTime,
|
|
57
|
+
statusCode: node_opcua_status_code_1.StatusCodes.Bad
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (nbUncertain > 0 || nbBad > 0) {
|
|
62
|
+
statusCode = node_opcua_status_code_1.StatusCode.makeStatusCode(node_opcua_status_code_1.StatusCodes.UncertainDataSubNormal, node_opcua_status_code_1.extraStatusCodeBits.HistorianCalculated | partialFlag);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
statusCode = node_opcua_status_code_1.StatusCode.makeStatusCode(node_opcua_status_code_1.StatusCodes.Good, node_opcua_status_code_1.extraStatusCodeBits.HistorianCalculated | partialFlag);
|
|
66
|
+
}
|
|
67
|
+
if (nbUncertain === 0 && nbGood === 0) {
|
|
68
|
+
statusCode = node_opcua_status_code_1.StatusCodes.BadNoData;
|
|
69
|
+
return new node_opcua_data_value_1.DataValue({
|
|
70
|
+
sourceTimestamp: interval.startTime,
|
|
71
|
+
statusCode: statusCode
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return new node_opcua_data_value_1.DataValue({
|
|
75
|
+
sourceTimestamp: interval.startTime,
|
|
76
|
+
statusCode: statusCode,
|
|
77
|
+
value: {
|
|
78
|
+
dataType: node_opcua_variant_1.DataType.UInt32,
|
|
79
|
+
value: nbGood
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function getCountData(node, processingInterval, startDate, endDate, callback) {
|
|
84
|
+
(0, common_1.getAggregateData)(node, processingInterval, startDate, endDate, calculateCountValue, callback);
|
|
85
|
+
}
|
|
86
|
+
exports.getCountData = getCountData;
|
|
87
|
+
//# sourceMappingURL=count.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"count.js","sourceRoot":"","sources":["../source/count.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { UAVariable } from "node-opcua-address-space";
|
|
2
|
+
import { DataValue } from "node-opcua-data-value";
|
|
3
|
+
/**Retrieve the percentage of data (0 to 100) in the interval which has Bad StatusCode. */
|
|
4
|
+
export declare function getDurationBadData(node: UAVariable, processingInterval: number, startDate: Date, endDate: Date, callback: (err: Error | null, dataValues?: DataValue[]) => void): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDurationBadData = void 0;
|
|
4
|
+
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
5
|
+
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
6
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
7
|
+
const common_1 = require("./common");
|
|
8
|
+
const calculate_bad_good_1 = require("./calculate_bad_good");
|
|
9
|
+
function calculateDurationBad(interval, options) {
|
|
10
|
+
const { durationBad, durationUnknown, statusCode } = (0, calculate_bad_good_1.calculateBadAndGood)(interval, options);
|
|
11
|
+
if (durationUnknown > 0 && durationBad === 0) {
|
|
12
|
+
return new node_opcua_data_value_1.DataValue({
|
|
13
|
+
sourceTimestamp: interval.startTime,
|
|
14
|
+
statusCode: node_opcua_status_code_1.StatusCodes.Bad
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const value = durationBad;
|
|
18
|
+
if (statusCode.isGoodish()) {
|
|
19
|
+
return new node_opcua_data_value_1.DataValue({
|
|
20
|
+
sourceTimestamp: interval.startTime,
|
|
21
|
+
statusCode,
|
|
22
|
+
value: { dataType: node_opcua_variant_1.DataType.Double, value }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return new node_opcua_data_value_1.DataValue({ sourceTimestamp: interval.startTime, statusCode, value: { dataType: node_opcua_variant_1.DataType.Null } });
|
|
26
|
+
}
|
|
27
|
+
/**Retrieve the percentage of data (0 to 100) in the interval which has Bad StatusCode. */
|
|
28
|
+
function getDurationBadData(node, processingInterval, startDate, endDate, callback) {
|
|
29
|
+
(0, common_1.getAggregateData)(node, processingInterval, startDate, endDate, calculateDurationBad, callback);
|
|
30
|
+
}
|
|
31
|
+
exports.getDurationBadData = getDurationBadData;
|
|
32
|
+
//# sourceMappingURL=duration_bad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration_bad.js","sourceRoot":"","sources":["../source/duration_bad.ts"],"names":[],"mappings":";;;AACA,iEAAkD;AAClD,2DAA8C;AAC9C,mEAAqD;AAErD,qCAA4C;AAE5C,6DAA2D;AAE3D,SAAS,oBAAoB,CAAC,QAAkB,EAAE,OAAsC;IACpF,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,IAAA,wCAAmB,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5F,IAAI,eAAe,GAAG,CAAC,IAAI,WAAW,KAAK,CAAC,EAAE;QAC1C,OAAO,IAAI,iCAAS,CAAC;YACjB,eAAe,EAAE,QAAQ,CAAC,SAAS;YACnC,UAAU,EAAE,oCAAW,CAAC,GAAG;SAC9B,CAAC,CAAC;KACN;IACD,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE;QACxB,OAAO,IAAI,iCAAS,CAAC;YACjB,eAAe,EAAE,QAAQ,CAAC,SAAS;YACnC,UAAU;YACV,KAAK,EAAE,EAAE,QAAQ,EAAE,6BAAQ,CAAC,MAAM,EAAE,KAAK,EAAE;SAC9C,CAAC,CAAC;KACN;IACD,OAAO,IAAI,iCAAS,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,6BAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAClH,CAAC;AACD,0FAA0F;AAC1F,SAAgB,kBAAkB,CAC9B,IAAgB,EAChB,kBAA0B,EAC1B,SAAe,EACf,OAAa,EACb,QAA+D;IAE/D,IAAA,yBAAgB,EAAC,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AACnG,CAAC;AARD,gDAQC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { UAVariable } from "node-opcua-address-space";
|
|
2
|
+
import { DataValue } from "node-opcua-data-value";
|
|
3
|
+
/**Retrieve the percentage of data (0 to 100) in the interval which has Bad StatusCode. */
|
|
4
|
+
export declare function getDurationGoodData(node: UAVariable, processingInterval: number, startDate: Date, endDate: Date, callback: (err: Error | null, dataValues?: DataValue[]) => void): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDurationGoodData = void 0;
|
|
4
|
+
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
5
|
+
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
6
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
7
|
+
const common_1 = require("./common");
|
|
8
|
+
const calculate_bad_good_1 = require("./calculate_bad_good");
|
|
9
|
+
function calculateDurationGood(interval, options) {
|
|
10
|
+
const { durationGood, durationUnknown, statusCode } = (0, calculate_bad_good_1.calculateBadAndGood)(interval, options);
|
|
11
|
+
if (durationUnknown > 0 && durationGood === 0) {
|
|
12
|
+
return new node_opcua_data_value_1.DataValue({
|
|
13
|
+
sourceTimestamp: interval.startTime,
|
|
14
|
+
statusCode: node_opcua_status_code_1.StatusCodes.Bad
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const value = durationGood;
|
|
18
|
+
if (statusCode.isGoodish()) {
|
|
19
|
+
return new node_opcua_data_value_1.DataValue({
|
|
20
|
+
sourceTimestamp: interval.startTime,
|
|
21
|
+
statusCode,
|
|
22
|
+
value: { dataType: node_opcua_variant_1.DataType.Double, value }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return new node_opcua_data_value_1.DataValue({ sourceTimestamp: interval.startTime, statusCode, value: { dataType: node_opcua_variant_1.DataType.Null } });
|
|
26
|
+
}
|
|
27
|
+
/**Retrieve the percentage of data (0 to 100) in the interval which has Bad StatusCode. */
|
|
28
|
+
function getDurationGoodData(node, processingInterval, startDate, endDate, callback) {
|
|
29
|
+
(0, common_1.getAggregateData)(node, processingInterval, startDate, endDate, calculateDurationGood, callback);
|
|
30
|
+
}
|
|
31
|
+
exports.getDurationGoodData = getDurationGoodData;
|
|
32
|
+
//# sourceMappingURL=duration_good.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration_good.js","sourceRoot":"","sources":["../source/duration_good.ts"],"names":[],"mappings":";;;AACA,iEAAkD;AAClD,2DAA8C;AAC9C,mEAAqD;AAErD,qCAA4C;AAE5C,6DAA2D;AAE3D,SAAS,qBAAqB,CAAC,QAAkB,EAAE,OAAsC;IACrF,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,IAAA,wCAAmB,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7F,IAAI,eAAe,GAAC,CAAC,IAAK,YAAY,KAAI,CAAC,EAAE;QACzC,OAAO,IAAI,iCAAS,CAAC;YACjB,eAAe,EAAE,QAAQ,CAAC,SAAS;YACnC,UAAU,EAAE,oCAAW,CAAC,GAAG;SAC9B,CAAC,CAAC;KACN;IACD,MAAM,KAAK,GAAG,YAAY,CAAC;IAC3B,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE;QACxB,OAAO,IAAI,iCAAS,CAAC;YACjB,eAAe,EAAE,QAAQ,CAAC,SAAS;YACnC,UAAU;YACV,KAAK,EAAE,EAAE,QAAQ,EAAE,6BAAQ,CAAC,MAAM,EAAE,KAAK,EAAE;SAC9C,CAAC,CAAC;KACN;IACD,OAAO,IAAI,iCAAS,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,6BAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAClH,CAAC;AACD,0FAA0F;AAC1F,SAAgB,mBAAmB,CAC/B,IAAgB,EAChB,kBAA0B,EAC1B,SAAe,EACf,OAAa,EACb,QAA+D;IAE/D,IAAA,yBAAgB,EAAC,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,EAAE,QAAQ,CAAC,CAAC;AACpG,CAAC;AARD,kDAQC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opca-aggregates
|
|
3
|
+
*/
|
|
4
|
+
export { addAggregateSupport, installAggregateConfigurationOptions, getAggregateConfiguration, addAggregateStandardFunctionSupport, addAggregateFunctionSupport } 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/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.AggregateFunction = exports.addAggregateFunctionSupport = exports.addAggregateStandardFunctionSupport = exports.getAggregateConfiguration = exports.installAggregateConfigurationOptions = exports.addAggregateSupport = void 0;
|
|
18
|
+
/**
|
|
19
|
+
* @module node-opca-aggregates
|
|
20
|
+
*/
|
|
21
|
+
var aggregates_1 = require("./aggregates");
|
|
22
|
+
Object.defineProperty(exports, "addAggregateSupport", { enumerable: true, get: function () { return aggregates_1.addAggregateSupport; } });
|
|
23
|
+
Object.defineProperty(exports, "installAggregateConfigurationOptions", { enumerable: true, get: function () { return aggregates_1.installAggregateConfigurationOptions; } });
|
|
24
|
+
Object.defineProperty(exports, "getAggregateConfiguration", { enumerable: true, get: function () { return aggregates_1.getAggregateConfiguration; } });
|
|
25
|
+
Object.defineProperty(exports, "addAggregateStandardFunctionSupport", { enumerable: true, get: function () { return aggregates_1.addAggregateStandardFunctionSupport; } });
|
|
26
|
+
Object.defineProperty(exports, "addAggregateFunctionSupport", { enumerable: true, get: function () { return aggregates_1.addAggregateFunctionSupport; } });
|
|
27
|
+
__exportStar(require("./interpolate"), exports);
|
|
28
|
+
__exportStar(require("./minmax"), exports);
|
|
29
|
+
__exportStar(require("./interval"), exports);
|
|
30
|
+
__exportStar(require("./common"), exports);
|
|
31
|
+
__exportStar(require("./average"), exports);
|
|
32
|
+
__exportStar(require("./read_processed_details"), exports);
|
|
33
|
+
var node_opcua_constants_1 = require("node-opcua-constants");
|
|
34
|
+
Object.defineProperty(exports, "AggregateFunction", { enumerable: true, get: function () { return node_opcua_constants_1.AggregateFunction; } });
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,2CAMsB;AALlB,iHAAA,mBAAmB,OAAA;AACnB,kIAAA,oCAAoC,OAAA;AACpC,uHAAA,yBAAyB,OAAA;AACzB,iIAAA,mCAAmC,OAAA;AACnC,yHAAA,2BAA2B,OAAA;AAE/B,gDAA8B;AAC9B,2CAAyB;AACzB,6CAA2B;AAC3B,2CAAyB;AACzB,4CAA0B;AAC1B,2DAAyC;AACzC,6DAAyD;AAAhD,yHAAA,iBAAiB,OAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-aggregates
|
|
3
|
+
*/
|
|
4
|
+
import { UAVariable } from "node-opcua-address-space";
|
|
5
|
+
import { DataValue } from "node-opcua-data-value";
|
|
6
|
+
import { AggregateConfigurationOptionsEx, Interval } from "./interval";
|
|
7
|
+
export declare function interpolatedValue(interval: Interval, options: AggregateConfigurationOptionsEx): DataValue;
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param node
|
|
11
|
+
* @param processingInterval
|
|
12
|
+
* @param startDate
|
|
13
|
+
* @param endDate
|
|
14
|
+
* @param callback
|
|
15
|
+
*/
|
|
16
|
+
export declare function getInterpolatedData(node: UAVariable, processingInterval: number, startDate: Date, endDate: Date, callback: (err: Error | null, dataValues?: DataValue[]) => void): void;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInterpolatedData = exports.interpolatedValue = void 0;
|
|
4
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
5
|
+
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
6
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
7
|
+
const common_1 = require("./common");
|
|
8
|
+
const interval_1 = require("./interval");
|
|
9
|
+
/*
|
|
10
|
+
For any intervals containing regions where the StatusCodes are Bad,
|
|
11
|
+
the total duration of all Bad regions is calculated and divided by the width of the interval.
|
|
12
|
+
The resulting ratio is multiplied by 100 and compared to the PercentDataBad parameter.
|
|
13
|
+
The StatusCode for the interval is Bad if the ratio is greater than or equal to the PercentDataBad parameter.
|
|
14
|
+
For any interval which is not Bad, the total duration of all Good regions is then calculated and divided by
|
|
15
|
+
the width of the interval. The resulting ratio is multiplied by 100 and compared to the PercentDataGood parameter.
|
|
16
|
+
The StatusCode for the interval is Good if the ratio is greater than or equal to the PercentDataGood parameter.
|
|
17
|
+
If for an interval neither ratio applies then that interval is Uncertain_DataSubNormal.
|
|
18
|
+
*/
|
|
19
|
+
function interpolatedValue(interval, options) {
|
|
20
|
+
options = (0, interval_1.adjustProcessingOptions)(options);
|
|
21
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "useSlopedExtrapolation"));
|
|
22
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "treatUncertainAsBad"));
|
|
23
|
+
const bTreatUncertainAsBad = options.treatUncertainAsBad;
|
|
24
|
+
const steppedValue = (previousDataValue) => {
|
|
25
|
+
if (!previousDataValue.statusCode) {
|
|
26
|
+
throw new Error("Expecting statusCode");
|
|
27
|
+
}
|
|
28
|
+
const interpValue = new node_opcua_data_value_1.DataValue({
|
|
29
|
+
sourceTimestamp: interval.startTime,
|
|
30
|
+
statusCode: node_opcua_status_code_1.StatusCodes.Bad,
|
|
31
|
+
value: previousDataValue.value
|
|
32
|
+
});
|
|
33
|
+
interpValue.statusCode = node_opcua_status_code_1.StatusCode.makeStatusCode(node_opcua_status_code_1.StatusCodes.UncertainDataSubNormal, "HistorianInterpolated");
|
|
34
|
+
return interpValue;
|
|
35
|
+
};
|
|
36
|
+
if (interval.index === -1) {
|
|
37
|
+
// the interval is beyond end Data
|
|
38
|
+
// we need to find previous good value
|
|
39
|
+
// and second previous good value to extrapolate
|
|
40
|
+
const prev1 = (0, interval_1._findGoodDataValueBefore)(interval.dataValues, interval.dataValues.length, bTreatUncertainAsBad);
|
|
41
|
+
if (prev1.index <= 0) {
|
|
42
|
+
return new node_opcua_data_value_1.DataValue({
|
|
43
|
+
sourceTimestamp: interval.startTime,
|
|
44
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNoData,
|
|
45
|
+
value: undefined
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!options.useSlopedExtrapolation) {
|
|
49
|
+
return steppedValue(prev1.dataValue);
|
|
50
|
+
}
|
|
51
|
+
const prev2 = (0, interval_1._findGoodDataValueBefore)(interval.dataValues, prev1.index, bTreatUncertainAsBad);
|
|
52
|
+
if (prev2.index <= 0) {
|
|
53
|
+
// use step value
|
|
54
|
+
return steppedValue(prev1.dataValue);
|
|
55
|
+
}
|
|
56
|
+
// else interpolate
|
|
57
|
+
const interpVal = (0, common_1.interpolateValue)(prev2.dataValue, prev1.dataValue, interval.startTime);
|
|
58
|
+
// tslint:disable:no-bitwise
|
|
59
|
+
if (prev2.index + 1 < prev1.index || prev1.index < interval.dataValues.length - 1) {
|
|
60
|
+
// some bad data exist in between = change status code
|
|
61
|
+
const mask = 0x0000ffffff;
|
|
62
|
+
const extraBits = interpVal.statusCode.value & mask;
|
|
63
|
+
interpVal.statusCode = node_opcua_status_code_1.StatusCode.makeStatusCode(node_opcua_status_code_1.StatusCodes.UncertainDataSubNormal, extraBits);
|
|
64
|
+
}
|
|
65
|
+
return interpVal;
|
|
66
|
+
}
|
|
67
|
+
/* istanbul ignore next */
|
|
68
|
+
if (interval.index < 0 && interval.count === 0) {
|
|
69
|
+
return new node_opcua_data_value_1.DataValue({
|
|
70
|
+
sourceTimestamp: interval.startTime,
|
|
71
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNoData
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const dataValue1 = interval.dataValues[interval.index];
|
|
75
|
+
// if a non-Bad Raw value exists at the timestamp then it is the bounding value;
|
|
76
|
+
if (!dataValue1.statusCode.isBad() && interval.hasRawDataAsStart()) {
|
|
77
|
+
return dataValue1;
|
|
78
|
+
}
|
|
79
|
+
// find the first non-Bad Raw value before the timestamp;
|
|
80
|
+
// find previous good value
|
|
81
|
+
const before = interval.beforeStartDataValue(bTreatUncertainAsBad);
|
|
82
|
+
if (before.dataValue.statusCode.isBad()) {
|
|
83
|
+
return new node_opcua_data_value_1.DataValue({
|
|
84
|
+
sourceTimestamp: interval.startTime,
|
|
85
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNoData
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (options.stepped) {
|
|
89
|
+
if (before.index + 1 === interval.index) {
|
|
90
|
+
return new node_opcua_data_value_1.DataValue({
|
|
91
|
+
sourceTimestamp: interval.startTime,
|
|
92
|
+
statusCode: node_opcua_status_code_1.StatusCode.makeStatusCode(before.dataValue.statusCode, "HistorianInterpolated"),
|
|
93
|
+
value: before.dataValue.value
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return steppedValue(before.dataValue);
|
|
97
|
+
}
|
|
98
|
+
// find the first non-Bad Raw value after the timestamp;
|
|
99
|
+
const next = interval.nextStartDataValue(bTreatUncertainAsBad);
|
|
100
|
+
// draw a line between before value and after value;
|
|
101
|
+
// use point where the line crosses the timestamp as an estimate of the bounding value.
|
|
102
|
+
// The calculation can be expressed with the following formula:
|
|
103
|
+
// V bound = (T bound – T before)x( V after – V before)/( T after – T before) + V before
|
|
104
|
+
// where V
|
|
105
|
+
// x is a value at ‘x’ and Tx is the timestamp associated with Vx.
|
|
106
|
+
const interpolatedDataValue = (0, common_1.interpolateValue)(before.dataValue, next.dataValue, interval.startTime);
|
|
107
|
+
if (before.index + 1 < next.index || !next.dataValue.statusCode.isGood() || !before.dataValue.statusCode.isGood()) {
|
|
108
|
+
// tslint:disable:no-bitwise
|
|
109
|
+
// some bad data exist in between = change status code
|
|
110
|
+
const mask = 0x0000ffffff;
|
|
111
|
+
const extraBits = interpolatedDataValue.statusCode.value & mask;
|
|
112
|
+
interpolatedDataValue.statusCode = node_opcua_status_code_1.StatusCode.makeStatusCode(node_opcua_status_code_1.StatusCodes.UncertainDataSubNormal, extraBits);
|
|
113
|
+
}
|
|
114
|
+
// check if uncertain or bad value exist between before/next
|
|
115
|
+
// todo
|
|
116
|
+
return interpolatedDataValue;
|
|
117
|
+
}
|
|
118
|
+
exports.interpolatedValue = interpolatedValue;
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @param node
|
|
122
|
+
* @param processingInterval
|
|
123
|
+
* @param startDate
|
|
124
|
+
* @param endDate
|
|
125
|
+
* @param callback
|
|
126
|
+
*/
|
|
127
|
+
function getInterpolatedData(node, processingInterval, startDate, endDate, callback) {
|
|
128
|
+
(0, common_1.getAggregateData)(node, processingInterval, startDate, endDate, interpolatedValue, callback);
|
|
129
|
+
}
|
|
130
|
+
exports.getInterpolatedData = getInterpolatedData;
|
|
131
|
+
//# sourceMappingURL=interpolate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interpolate.js","sourceRoot":"","sources":["../source/interpolate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opca-aggregates
|
|
3
|
+
*/
|
|
4
|
+
import { DataValue } from "node-opcua-data-value";
|
|
5
|
+
import { StatusCode } from "node-opcua-status-code";
|
|
6
|
+
import { AggregateConfigurationOptions } from "node-opcua-types";
|
|
7
|
+
export { AggregateConfigurationOptions } from "node-opcua-types";
|
|
8
|
+
export interface AggregateConfigurationOptionsEx extends AggregateConfigurationOptions {
|
|
9
|
+
stepped?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function isGoodish2(statusCode: StatusCode, { treatUncertainAsBad }: {
|
|
12
|
+
treatUncertainAsBad?: boolean;
|
|
13
|
+
}): boolean;
|
|
14
|
+
export declare function isUncertain(statusCode: StatusCode): boolean;
|
|
15
|
+
export interface IntervalOptions {
|
|
16
|
+
startTime: Date;
|
|
17
|
+
dataValues: DataValue[];
|
|
18
|
+
index: number;
|
|
19
|
+
count: number;
|
|
20
|
+
isPartial: boolean;
|
|
21
|
+
processingInterval: number;
|
|
22
|
+
}
|
|
23
|
+
interface DataValueWithIndex {
|
|
24
|
+
index: number;
|
|
25
|
+
dataValue: DataValue;
|
|
26
|
+
}
|
|
27
|
+
export declare function _findGoodDataValueBefore(dataValues: DataValue[], index: number, bTreatUncertainAsBad: boolean): DataValueWithIndex;
|
|
28
|
+
export declare function _findGoodDataValueAfter(dataValues: DataValue[], index: number, bTreatUncertainAsBad: boolean): DataValueWithIndex;
|
|
29
|
+
export declare function adjustProcessingOptions(options: AggregateConfigurationOptionsEx | null): AggregateConfigurationOptionsEx;
|
|
30
|
+
export declare class Interval {
|
|
31
|
+
startTime: Date;
|
|
32
|
+
dataValues: DataValue[];
|
|
33
|
+
index: number;
|
|
34
|
+
count: number;
|
|
35
|
+
isPartial: boolean;
|
|
36
|
+
processingInterval: number;
|
|
37
|
+
constructor(options: IntervalOptions);
|
|
38
|
+
getPercentBad(): number;
|
|
39
|
+
/**
|
|
40
|
+
* returns true if a raw data exists at start
|
|
41
|
+
*/
|
|
42
|
+
hasRawDataAsStart(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Find the first good or uncertain dataValue
|
|
45
|
+
* just preceding this interval
|
|
46
|
+
* @returns {*}
|
|
47
|
+
*/
|
|
48
|
+
beforeStartDataValue(bTreatUncertainAsBad: boolean): DataValueWithIndex;
|
|
49
|
+
nextStartDataValue(bTreatUncertainAsBad: boolean): DataValueWithIndex;
|
|
50
|
+
toString(): string;
|
|
51
|
+
getEffectiveEndTime(): number;
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @returns the interval duration
|
|
55
|
+
*/
|
|
56
|
+
duration(): number;
|
|
57
|
+
/**
|
|
58
|
+
* returns the region duration starting at index and finishing at index+1 or end limit of the interval
|
|
59
|
+
*/
|
|
60
|
+
regionDuration(index: number): number;
|
|
61
|
+
}
|
|
62
|
+
export declare function getInterval(startTime: Date, processingInterval: number, indexHint: number, dataValues: DataValue[]): Interval;
|
package/dist/interval.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInterval = exports.Interval = exports.adjustProcessingOptions = exports._findGoodDataValueAfter = exports._findGoodDataValueBefore = exports.isUncertain = exports.isGoodish2 = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @module node-opca-aggregates
|
|
6
|
+
*/
|
|
7
|
+
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
8
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
9
|
+
function isGoodish2(statusCode, { treatUncertainAsBad }) {
|
|
10
|
+
if (statusCode.isGoodish())
|
|
11
|
+
return true;
|
|
12
|
+
if (isUncertain(statusCode))
|
|
13
|
+
return !treatUncertainAsBad;
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
exports.isGoodish2 = isGoodish2;
|
|
17
|
+
function isUncertain(statusCode) {
|
|
18
|
+
return (statusCode.value & 0x40000000) === 0x40000000 && statusCode.value !== node_opcua_status_code_1.StatusCodes.BadNoData.value;
|
|
19
|
+
}
|
|
20
|
+
exports.isUncertain = isUncertain;
|
|
21
|
+
function _findGoodDataValueBefore(dataValues, index, bTreatUncertainAsBad) {
|
|
22
|
+
index--;
|
|
23
|
+
while (index >= 0) {
|
|
24
|
+
const dataValue1 = dataValues[index];
|
|
25
|
+
if (!bTreatUncertainAsBad && !dataValue1.statusCode.isBad()) {
|
|
26
|
+
return { index, dataValue: dataValue1 };
|
|
27
|
+
}
|
|
28
|
+
if (bTreatUncertainAsBad && dataValue1.statusCode.isGood()) {
|
|
29
|
+
return { index, dataValue: dataValue1 };
|
|
30
|
+
}
|
|
31
|
+
index -= 1;
|
|
32
|
+
}
|
|
33
|
+
// not found
|
|
34
|
+
return {
|
|
35
|
+
dataValue: new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoData }),
|
|
36
|
+
index: -1
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
exports._findGoodDataValueBefore = _findGoodDataValueBefore;
|
|
40
|
+
function _findGoodDataValueAfter(dataValues, index, bTreatUncertainAsBad) {
|
|
41
|
+
while (index < dataValues.length) {
|
|
42
|
+
const dataValue1 = dataValues[index];
|
|
43
|
+
if (!bTreatUncertainAsBad && !dataValue1.statusCode.isBad()) {
|
|
44
|
+
return {
|
|
45
|
+
dataValue: dataValue1,
|
|
46
|
+
index
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (bTreatUncertainAsBad && dataValue1.statusCode.isGood()) {
|
|
50
|
+
return {
|
|
51
|
+
dataValue: dataValue1,
|
|
52
|
+
index
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
index += 1;
|
|
56
|
+
}
|
|
57
|
+
// not found
|
|
58
|
+
return {
|
|
59
|
+
dataValue: new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoData }),
|
|
60
|
+
index: -1
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
exports._findGoodDataValueAfter = _findGoodDataValueAfter;
|
|
64
|
+
function adjustProcessingOptions(options) {
|
|
65
|
+
options = options || {};
|
|
66
|
+
options.treatUncertainAsBad = options.treatUncertainAsBad || false;
|
|
67
|
+
options.useSlopedExtrapolation = options.useSlopedExtrapolation || false;
|
|
68
|
+
options.stepped = options.stepped || false;
|
|
69
|
+
options.percentDataBad = parseInt(options.percentDataBad, 10);
|
|
70
|
+
options.percentDataGood = parseInt(options.percentDataGood, 10);
|
|
71
|
+
return options;
|
|
72
|
+
}
|
|
73
|
+
exports.adjustProcessingOptions = adjustProcessingOptions;
|
|
74
|
+
class Interval {
|
|
75
|
+
// startTime
|
|
76
|
+
// dataValues
|
|
77
|
+
// index: index of first dataValue inside the interval
|
|
78
|
+
// count: number of dataValue inside the interval
|
|
79
|
+
constructor(options) {
|
|
80
|
+
this.startTime = options.startTime;
|
|
81
|
+
this.dataValues = options.dataValues;
|
|
82
|
+
this.index = options.index;
|
|
83
|
+
this.count = options.count;
|
|
84
|
+
this.isPartial = options.isPartial;
|
|
85
|
+
this.processingInterval = options.processingInterval;
|
|
86
|
+
}
|
|
87
|
+
getPercentBad() {
|
|
88
|
+
return 100;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* returns true if a raw data exists at start
|
|
92
|
+
*/
|
|
93
|
+
hasRawDataAsStart() {
|
|
94
|
+
const index = this.index;
|
|
95
|
+
if (index < 0) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const dataValue1 = this.dataValues[index];
|
|
99
|
+
return this.startTime.getTime() === dataValue1.sourceTimestamp.getTime();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Find the first good or uncertain dataValue
|
|
103
|
+
* just preceding this interval
|
|
104
|
+
* @returns {*}
|
|
105
|
+
*/
|
|
106
|
+
beforeStartDataValue(bTreatUncertainAsBad) {
|
|
107
|
+
return _findGoodDataValueBefore(this.dataValues, this.index, bTreatUncertainAsBad);
|
|
108
|
+
}
|
|
109
|
+
nextStartDataValue(bTreatUncertainAsBad) {
|
|
110
|
+
return _findGoodDataValueAfter(this.dataValues, this.index, bTreatUncertainAsBad);
|
|
111
|
+
}
|
|
112
|
+
toString() {
|
|
113
|
+
let str = "";
|
|
114
|
+
str += "startTime " + this.startTime.toUTCString() + "\n";
|
|
115
|
+
str += "start " + this.index + " ";
|
|
116
|
+
str += "count " + this.count + " ";
|
|
117
|
+
str += "isPartial " + this.isPartial + "\n";
|
|
118
|
+
if (this.index >= 0) {
|
|
119
|
+
for (let i = this.index; i < this.index + this.count; i++) {
|
|
120
|
+
const dataValue = this.dataValues[i];
|
|
121
|
+
str += " " + dataValue.sourceTimestamp.toUTCString() + dataValue.statusCode.toString();
|
|
122
|
+
str += dataValue.value ? dataValue.value.toString() : "";
|
|
123
|
+
str += "\n";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return str;
|
|
127
|
+
}
|
|
128
|
+
getEffectiveEndTime() {
|
|
129
|
+
const e = this.startTime.getTime() + this.processingInterval;
|
|
130
|
+
if (!this.dataValues || this.dataValues.length === 0) {
|
|
131
|
+
return e;
|
|
132
|
+
}
|
|
133
|
+
let i = this.dataValues.length - 1;
|
|
134
|
+
while (i >= 0 && this.dataValues[i].statusCode.equals(node_opcua_status_code_1.StatusCodes.BadNoData)) {
|
|
135
|
+
i--;
|
|
136
|
+
}
|
|
137
|
+
if (i < 0) {
|
|
138
|
+
return e;
|
|
139
|
+
}
|
|
140
|
+
const lastTimestamp = this.dataValues[i].sourceTimestamp;
|
|
141
|
+
return Math.min(e, lastTimestamp.getTime() + 1);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* @returns the interval duration
|
|
146
|
+
*/
|
|
147
|
+
duration() {
|
|
148
|
+
const t1 = this.dataValues[this.index].sourceTimestamp.getTime();
|
|
149
|
+
const e = this.getEffectiveEndTime();
|
|
150
|
+
return e - t1;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* returns the region duration starting at index and finishing at index+1 or end limit of the interval
|
|
154
|
+
*/
|
|
155
|
+
regionDuration(index) {
|
|
156
|
+
const t1 = this.dataValues[index].sourceTimestamp.getTime();
|
|
157
|
+
const e = this.getEffectiveEndTime();
|
|
158
|
+
const t2 = index < this.dataValues.length - 1 ? Math.min(this.dataValues[index + 1].sourceTimestamp.getTime(), e) : e;
|
|
159
|
+
return t2 - t1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.Interval = Interval;
|
|
163
|
+
function getInterval(startTime, processingInterval, indexHint, dataValues) {
|
|
164
|
+
let count = 0;
|
|
165
|
+
let index = -1;
|
|
166
|
+
for (let i = indexHint; i < dataValues.length; i++) {
|
|
167
|
+
if (dataValues[i].sourceTimestamp.getTime() < startTime.getTime()) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
index = i;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
if (index >= 0) {
|
|
174
|
+
for (let i = index; i < dataValues.length; i++) {
|
|
175
|
+
if (dataValues[i].sourceTimestamp.getTime() >= startTime.getTime() + processingInterval) {
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
count++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// check if interval is complete or partial (end or start)
|
|
182
|
+
let isPartial = false;
|
|
183
|
+
if (index + count >= dataValues.length &&
|
|
184
|
+
dataValues[dataValues.length - 1].sourceTimestamp.getTime() < startTime.getTime() + processingInterval) {
|
|
185
|
+
isPartial = true;
|
|
186
|
+
}
|
|
187
|
+
if (index <= 0 && dataValues[0].sourceTimestamp.getTime() > startTime.getTime()) {
|
|
188
|
+
isPartial = true;
|
|
189
|
+
}
|
|
190
|
+
return new Interval({
|
|
191
|
+
count,
|
|
192
|
+
dataValues,
|
|
193
|
+
index,
|
|
194
|
+
isPartial,
|
|
195
|
+
startTime,
|
|
196
|
+
processingInterval
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
exports.getInterval = getInterval;
|
|
200
|
+
//# sourceMappingURL=interval.js.map
|