node-opcua-aggregates
Version:
pure nodejs OPCUA SDK - module aggregates
206 lines • 7.16 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Interval = void 0;
exports.isGoodish2 = isGoodish2;
exports.isUncertain = isUncertain;
exports._findGoodDataValueBefore = _findGoodDataValueBefore;
exports._findGoodDataValueAfter = _findGoodDataValueAfter;
exports.adjustProcessingOptions = adjustProcessingOptions;
exports.getInterval = getInterval;
/**
* @module node-opca-aggregates
*/
const node_opcua_data_value_1 = require("node-opcua-data-value");
const node_opcua_status_code_1 = require("node-opcua-status-code");
function isGoodish2(statusCode, { treatUncertainAsBad }) {
if (statusCode.isGoodish())
return true;
if (isUncertain(statusCode))
return !treatUncertainAsBad;
return false;
}
function isUncertain(statusCode) {
return (statusCode.value & 0x40000000) === 0x40000000 && statusCode.value !== node_opcua_status_code_1.StatusCodes.BadNoData.value;
}
function _findGoodDataValueBefore(dataValues, index, bTreatUncertainAsBad) {
index--;
while (index >= 0) {
const dataValue1 = dataValues[index];
if (!bTreatUncertainAsBad && !dataValue1.statusCode.isBad()) {
return { index, dataValue: dataValue1 };
}
if (bTreatUncertainAsBad && dataValue1.statusCode.isGood()) {
return { index, dataValue: dataValue1 };
}
index -= 1;
}
// not found
return {
dataValue: new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoData }),
index: -1
};
}
function _findGoodDataValueAfter(dataValues, index, bTreatUncertainAsBad) {
while (index < dataValues.length) {
const dataValue1 = dataValues[index];
if (!bTreatUncertainAsBad && !dataValue1.statusCode.isBad()) {
return {
dataValue: dataValue1,
index
};
}
if (bTreatUncertainAsBad && dataValue1.statusCode.isGood()) {
return {
dataValue: dataValue1,
index
};
}
index += 1;
}
// not found
return {
dataValue: new node_opcua_data_value_1.DataValue({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoData }),
index: -1
};
}
function adjustProcessingOptions(options) {
options = options || {};
options.treatUncertainAsBad = options.treatUncertainAsBad || false;
options.useSlopedExtrapolation = options.useSlopedExtrapolation || false;
options.stepped = options.stepped || false;
options.percentDataBad = parseInt(options.percentDataBad, 10);
options.percentDataGood = parseInt(options.percentDataGood, 10);
return options;
}
class Interval {
startTime;
dataValues;
index;
count;
isPartial;
processingInterval;
// startTime
// dataValues
// index: index of first dataValue inside the interval
// count: number of dataValue inside the interval
constructor(options) {
this.startTime = options.startTime;
this.dataValues = options.dataValues;
this.index = options.index;
this.count = options.count;
this.isPartial = options.isPartial;
this.processingInterval = options.processingInterval;
}
getPercentBad() {
return 100;
}
/**
* returns true if a raw data exists at start
*/
hasRawDataAsStart() {
const index = this.index;
if (index < 0) {
return false;
}
const dataValue1 = this.dataValues[index];
return this.startTime.getTime() === dataValue1.sourceTimestamp.getTime();
}
/**
* Find the first good or uncertain dataValue
* just preceding this interval
* @returns {*}
*/
beforeStartDataValue(bTreatUncertainAsBad) {
return _findGoodDataValueBefore(this.dataValues, this.index, bTreatUncertainAsBad);
}
nextStartDataValue(bTreatUncertainAsBad) {
return _findGoodDataValueAfter(this.dataValues, this.index, bTreatUncertainAsBad);
}
toString() {
let str = "";
str += "startTime " + this.startTime.toUTCString() + "\n";
str += "start " + this.index + " ";
str += "count " + this.count + " ";
str += "isPartial " + this.isPartial + "\n";
if (this.index >= 0) {
for (let i = this.index; i < this.index + this.count; i++) {
const dataValue = this.dataValues[i];
str += " " + dataValue.sourceTimestamp.toUTCString() + dataValue.statusCode.toString();
str += dataValue.value ? dataValue.value.toString() : "";
str += "\n";
}
}
return str;
}
getEffectiveEndTime() {
const e = this.startTime.getTime() + this.processingInterval;
if (!this.dataValues || this.dataValues.length === 0) {
return e;
}
let i = this.dataValues.length - 1;
while (i >= 0 && this.dataValues[i].statusCode.equals(node_opcua_status_code_1.StatusCodes.BadNoData)) {
i--;
}
if (i < 0) {
return e;
}
const lastTimestamp = this.dataValues[i].sourceTimestamp;
return Math.min(e, lastTimestamp.getTime() + 1);
}
/**
*
* @returns the interval duration
*/
duration() {
const t1 = this.dataValues[this.index].sourceTimestamp.getTime();
const e = this.getEffectiveEndTime();
return e - t1;
}
/**
* returns the region duration starting at index and finishing at index+1 or end limit of the interval
*/
regionDuration(index) {
const t1 = this.dataValues[index].sourceTimestamp.getTime();
const e = this.getEffectiveEndTime();
const t2 = index < this.dataValues.length - 1 ? Math.min(this.dataValues[index + 1].sourceTimestamp.getTime(), e) : e;
return t2 - t1;
}
}
exports.Interval = Interval;
function getInterval(startTime, processingInterval, indexHint, dataValues) {
let count = 0;
let index = -1;
for (let i = indexHint; i < dataValues.length; i++) {
if (dataValues[i].sourceTimestamp.getTime() < startTime.getTime()) {
continue;
}
index = i;
break;
}
if (index >= 0) {
for (let i = index; i < dataValues.length; i++) {
if (dataValues[i].sourceTimestamp.getTime() >= startTime.getTime() + processingInterval) {
break;
}
count++;
}
}
// check if interval is complete or partial (end or start)
let isPartial = false;
if (index + count >= dataValues.length &&
dataValues[dataValues.length - 1].sourceTimestamp.getTime() < startTime.getTime() + processingInterval) {
isPartial = true;
}
if (index <= 0 && dataValues[0].sourceTimestamp.getTime() > startTime.getTime()) {
isPartial = true;
}
return new Interval({
count,
dataValues,
index,
isPartial,
startTime,
processingInterval
});
}
//# sourceMappingURL=interval.js.map