X Tutup
Skip to content

Commit a0bf4f0

Browse files
committed
improve node historisation
1 parent 54d1e1a commit a0bf4f0

File tree

10 files changed

+395
-202
lines changed

10 files changed

+395
-202
lines changed

packages/node-opcua-address-space/source/address_space_ts.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import {
1818
BrowseDescriptionOptions,
1919
BrowseResult
2020
} from "node-opcua-service-browse";
21+
import {
22+
HistoryReadDetails,
23+
HistoryReadResult,
24+
ReadRawModifiedDetails
25+
} from "node-opcua-service-history";
2126
import {
2227
WriteValueOptions
2328
} from "node-opcua-service-write";
@@ -471,19 +476,39 @@ export interface RootFolder extends Folder {
471476
views: Folder;
472477
}
473478

474-
import { HistoryReadDetails, HistoryReadResult, ReadRawModifiedDetails } from "node-opcua-service-history";
475-
476479
export interface IVariableHistorian {
477480

478-
push(newDataValue: DataValue): void;
481+
/**
482+
* push a new value into the history for this variable
483+
* the method should take a very small amount of time and not
484+
* directly write to the underlying database
485+
* @param newDataValue
486+
*/
487+
push(newDataValue: DataValue): Promise<void>;
479488

489+
/**
490+
* Extract a series of dataValue from the History database for this value
491+
* @param historyReadRawModifiedDetails
492+
* @param maxNumberToExtract
493+
* @param isReversed
494+
* @param reverseDataValue
495+
* @param callback
496+
*/
480497
extractDataValues(
481498
historyReadRawModifiedDetails: ReadRawModifiedDetails,
482499
maxNumberToExtract: number,
483500
isReversed: boolean,
484501
reverseDataValue: boolean,
485502
callback: (err?: Error | null, dataValue?: DataValue[]) => void
486503
): void;
504+
505+
/* extractDataValues(
506+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
507+
maxNumberToExtract: number,
508+
isReversed: boolean,
509+
reverseDataValue: boolean
510+
): Promise<DataValue[]>;
511+
*/
487512
}
488513

489514
export interface IVariableHistorianOptions {
@@ -492,6 +517,8 @@ export interface IVariableHistorianOptions {
492517

493518
export declare class AddressSpace {
494519

520+
static historizerFactory: any;
521+
495522
public rootFolder: RootFolder;
496523

497524
public findNode(node: NodeIdLike): BaseNode;
@@ -535,3 +562,31 @@ export declare function generate_address_space(
535562
xmlFiles: string | string[],
536563
callback: (err?: Error) => void
537564
): void;
565+
566+
export declare class VariableHistorian implements IVariableHistorian {
567+
568+
public constructor(node: UAVariable, options: IVariableHistorianOptions);
569+
/**
570+
* push a new value into the history for this variable
571+
* the method should take a very small amount of time and not
572+
* directly write to the underlying database
573+
* @param newDataValue
574+
*/
575+
public push(newDataValue: DataValue): Promise<void>;
576+
577+
/**
578+
* Extract a series of dataValue from the History database for this value
579+
* @param historyReadRawModifiedDetails
580+
* @param maxNumberToExtract
581+
* @param isReversed
582+
* @param reverseDataValue
583+
* @param callback
584+
*/
585+
public extractDataValues(
586+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
587+
maxNumberToExtract: number,
588+
isReversed: boolean,
589+
reverseDataValue: boolean,
590+
callback: (err?: Error | null, dataValue?: DataValue[]) => void
591+
): void;
592+
}

packages/node-opcua-address-space/src/historical_access/address_space_historical_data_node.js

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const isMinDate = require("node-opcua-date-time").isMinDate;
2929

3030
const UAVariable = require("../ua_variable").UAVariable;
3131
const SessionContext = require("../session_context").SessionContext;
32+
const AddressSpace = require("../address_space").AddressSpace;
3233

3334

3435
/* interface Historian */
@@ -96,7 +97,6 @@ function filter_dequeue(q, historyReadRawModifiedDetails, onlyThisNumber, isReve
9697
return r;
9798
}
9899

99-
100100
class VariableHistorian {
101101

102102
constructor(node, options) {
@@ -163,6 +163,15 @@ class VariableHistorian {
163163
callback(null, dataValues);
164164
}
165165
}
166+
exports.VariableHistorian = VariableHistorian;
167+
168+
169+
AddressSpace.historizerFactory = AddressSpace.historizerFactory || {
170+
171+
create: function (node, options) {
172+
return new VariableHistorian(node, options);
173+
}
174+
};
166175

167176
exports.install = function (AddressSpace) {
168177

@@ -175,6 +184,13 @@ exports.install = function (AddressSpace) {
175184
return node.$historicalDataConfiguration.startOfArchive.readValue();
176185
}
177186

187+
function _update_startOfArchive(newDate) {
188+
const node = this;
189+
node.$historicalDataConfiguration.startOfArchive.setValueFromSource({
190+
dataType: DataType.DateTime, value: newDate
191+
});
192+
}
193+
178194
function _update_startOfOnlineArchive(newDate) {
179195
const node = this;
180196

@@ -186,13 +202,12 @@ exports.install = function (AddressSpace) {
186202

187203
const startOfArchiveDataValue = _get_startOfOfflineArchive(node);
188204
if (startOfArchiveDataValue.statusCode !== StatusCodes.Good || startOfArchiveDataValue.value.value.getTime() >= newDate.getTime()) {
189-
node.$historicalDataConfiguration.startOfArchive.setValueFromSource({
190-
dataType: DataType.DateTime, value: newDate
191-
});
205+
node._update_startOfArchive(newDate);
192206
}
193207
}
194208

195209
UAVariable.prototype._update_startOfOnlineArchive = _update_startOfOnlineArchive;
210+
UAVariable.prototype._update_startOfArchive = _update_startOfArchive;
196211

197212
function _historyPush(newDataValue) {
198213

@@ -209,14 +224,9 @@ exports.install = function (AddressSpace) {
209224

210225
}
211226

212-
213-
214-
215-
216-
217-
218227
function createContinuationPoint() {
219-
return new Buffer("ABCDEF");
228+
// todo: improve
229+
return Buffer.from("ABCDEF");
220230
}
221231

222232
function _historyReadModify(
@@ -428,27 +438,35 @@ exports.install = function (AddressSpace) {
428438
let isReversed = false;
429439
let reverseDataValue = false;
430440
if (isMinDate(historyReadRawModifiedDetails.endTime)) {
441+
// end time is not specified
431442
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
432-
433443
if (isMinDate(historyReadRawModifiedDetails.startTime)) {
444+
// end start and start time are not specified, this is invalid
434445
const result = new HistoryReadResult({
435446
statusCode: StatusCodes.BadHistoryOperationInvalid // should be an error
436447
});
437448
return callback(null, result);
438449
}
439450

440451
} else if (isMinDate(historyReadRawModifiedDetails.startTime)) {
452+
// start time is not specified
453+
// end time is specified
441454
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
442455
isReversed = true;
443456
reverseDataValue = false;
444457

445458
if (historyReadRawModifiedDetails.numValuesPerNode === 0) {
459+
// when start time is not specified
460+
// and end time is specified
461+
// numValuesPerNode shall be greater than 0
446462
const result = new HistoryReadResult({
447463
statusCode: StatusCodes.BadHistoryOperationInvalid // should be an error
448464
});
449465
return callback(null, result);
450466
}
451467
} else {
468+
// start time is specified
469+
// end time is specified
452470
if (historyReadRawModifiedDetails.endTime.getTime() < historyReadRawModifiedDetails.startTime.getTime()) {
453471
reverseDataValue = true;
454472
const tmp = historyReadRawModifiedDetails.endTime;
@@ -720,7 +738,8 @@ exports.install = function (AddressSpace) {
720738
node._historyReadRawAsync = _historyReadRawAsync;
721739

722740

723-
node.varHistorian = options.historian || new VariableHistorian(node, options);
741+
node.varHistorian = options.historian ||
742+
AddressSpace.historizerFactory.create(node,options);
724743

725744
const historicalDataConfigurationType = addressSpace.findObjectType("HistoricalDataConfigurationType");
726745
node.historizing = true;

packages/node-opcua-address-space/src/historical_access/ua_variable_history.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ const HistoryReadResult = historizing_service.HistoryReadResult;
1919
* @param callback.err
2020
* @param callback.result {HistoryReadResult}
2121
*/
22-
UAVariable.prototype.historyRead = function (context, historyReadDetails, indexRange, dataEncoding, continuationPoint, callback) {
22+
UAVariable.prototype.historyRead = function (
23+
context,
24+
historyReadDetails,
25+
indexRange,
26+
dataEncoding,
27+
continuationPoint,
28+
callback
29+
) {
2330

2431
assert(context instanceof SessionContext);
2532
assert(callback instanceof Function);

packages/node-opcua-address-space/src/index_current.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ module.exports = {
5959

6060
generate_address_space: require("./loader/load_nodeset2").generate_address_space,
6161

62-
PseudoSession : require("../dist").PseudoSession
62+
PseudoSession : require("../dist").PseudoSession,
63+
64+
VariableHistorian: require("./historical_access/address_space_historical_data_node").VariableHistorian
6365
};
6466
require("../src/nodeset_to_xml");

0 commit comments

Comments
 (0)
X Tutup