- "use strict";
- /**
- * @module opcua.address_space.AlarmsAndConditions
- */
-
-
- const util = require("util");
- const assert = require("node-opcua-assert").assert;
- const _ = require("underscore");
-
- const StatusCodes = require("node-opcua-status-code").StatusCodes;
- const DataType = require("node-opcua-variant").DataType;
-
- const UAAlarmConditionBase = require("./alarm_condition").UAAlarmConditionBase;
- const UAVariable = require("../ua_variable").UAVariable;
- const ConditionInfo = require("./condition").ConditionInfo;
- const DataValue = require("node-opcua-data-value").DataValue;
- const NodeId = require("node-opcua-nodeid").NodeId;
-
- const AddressSpace =require("../address_space").AddressSpace;
- const Namespace = require("../namespace").Namespace;
- /**
- * @class UALimitAlarm
- * @constructor
- * @extends UAAlarmConditionBase
- */
- function UALimitAlarm() {
- /**
- * @property activeState
- * @type UATwoStateVariable
- */
-
- }
- util.inherits(UALimitAlarm, UAAlarmConditionBase);
-
- /**
- * @method getHighHighLimit
- * @return {Number}
- */
- UALimitAlarm.prototype.getHighHighLimit = function () {
- return this.highHighLimit.readValue().value.value;
- };
-
- /**
- * @method getHighLimit
- * @return {Number}
- */
- UALimitAlarm.prototype.getHighLimit = function () {
- return this.highLimit.readValue().value.value;
- };
-
- /**
- * @method getLowLimit
- * @return {Float}
- */
- UALimitAlarm.prototype.getLowLimit = function () {
- return this.lowLimit.readValue().value.value;
- };
-
- /**
- * @method getLowLowLimit
- * @return {Float}
- */
- UALimitAlarm.prototype.getLowLowLimit = function () {
- return this.lowLowLimit.readValue().value.value;
- };
-
- /**
- * @method setHighHighLimit
- * @param value {Float}
- */
- UALimitAlarm.prototype.setHighHighLimit = function (value) {
- assert(this.highHighLimit, "LimitAlarm instance must expose the optional HighHighLimit property");
- this.highHighLimit.setValueFromSource({ dataType: this._dataType, value: value });
-
- };
-
- /**
- * @method setHighLimit
- * @param value {Float}
- */
- UALimitAlarm.prototype.setHighLimit = function (value) {
- assert(this.highLimit, "LimitAlarm instance must expose the optional HighLimit property");
- this.highLimit.setValueFromSource({ dataType: this._dataType, value: value });
- };
-
- /**
- * @method setLowLimit
- * @param value {Float}
- */
- UALimitAlarm.prototype.setLowLimit = function (value) {
- assert(this.lowLimit, "LimitAlarm instance must expose the optional LowLimit property");
- this.lowLimit.setValueFromSource({ dataType: this._dataType, value: value });
-
- };
-
- /**
- * @method setLowLowLimit
- * @param value {Float}
- */
- UALimitAlarm.prototype.setLowLowLimit = function (value) {
- assert(this.lowLowLimit, "LimitAlarm instance must expose the optional LowLowLimit property");
- this.lowLowLimit.setValueFromSource({ dataType: this._dataType, value: value });
- };
-
- UALimitAlarm.prototype._onInputDataValueChange = function (dataValue) {
-
- assert(dataValue instanceof DataValue);
- const alarm = this;
-
- if (dataValue.statusCode === StatusCodes.BadWaitingForInitialData) {
- // we are not ready yet to use the input node value
- return;
- }
- if (dataValue.statusCode !== StatusCodes.Good) {
- // what shall we do ?
- alarm._signalNewCondition(null);
- return;
- }
- if (dataValue.value.dataType === DataType.Null) {
- // what shall we do ?
- alarm._signalNewCondition(null);
- return;
- }
- const value = dataValue.value.value;
- alarm._setStateBasedOnInputValue(value);
- };
-
-
- UALimitAlarm.prototype._watchLimits = function() {
-
- const alarm = this;
- /// ----------------------------------------------------------------------
- /// Installing Limits monitored
- function _updateState() { alarm.updateState(); }
- if (alarm.highHighLimit) {alarm.highHighLimit.on("value_changed",_updateState);}
- if (alarm.highLimit) {alarm.highLimit.on("value_changed",_updateState);}
- if (alarm.lowLimit) {alarm.lowLimit.on("value_changed",_updateState);}
- if (alarm.lowLowLimit) {alarm.lowLowLimit.on("value_changed",_updateState);}
- };
-
-
-
-
-
-
-
- exports.UALimitAlarm = UALimitAlarm;
-
- /**
- * @method (static)UALimitAlarm.instantiate
- * @param namespace {Namespace}
- * @param limitAlarmTypeId
- * @param options
- * @param options.inputNode
- * @param options.optionals
- * @param options.highHighLimit {Double}
- * @param options.highLimit {Double}
- * @param options.lowLimit {Double}
- * @param options.lowLowLimit {Double}
- * @param data
- * @return {UALimitAlarm}
- */
- UALimitAlarm.instantiate = function (namespace, limitAlarmTypeId, options, data) {
- assert(namespace instanceof Namespace);
- const addressSpace = namespace.addressSpace;
- assert(addressSpace instanceof AddressSpace);
-
- /* eslint max-instructions: off */
- // must provide a inputNode
- //xx assert(options.hasOwnProperty("conditionOf")); // must provide a conditionOf
- assert(options.hasOwnProperty("inputNode"), "UALimitAlarm.instantiate: options must provide the inputNode");
-
- options.optionals = options.optionals || [];
- let count = 0;
- if (options.hasOwnProperty("highHighLimit")) {
- options.optionals.push("HighHighLimit");
- options.optionals.push("HighHighState");
- count++;
- }
- if (options.hasOwnProperty("highLimit")) {
- options.optionals.push("HighLimit");
- options.optionals.push("HighState");
- count++;
- }
- if (options.hasOwnProperty("lowLimit")) {
- options.optionals.push("LowLimit");
- options.optionals.push("LowState");
- count++;
- }
- if (options.hasOwnProperty("lowLowLimit")) {
- options.optionals.push("LowLowLimit");
- options.optionals.push("LowLowState");
- count++;
- }
-
- //xx assert(options.optionals,"must provide an optionals");
- const alarmNode = UAAlarmConditionBase.instantiate(namespace, limitAlarmTypeId, options, data);
- Object.setPrototypeOf(alarmNode, UALimitAlarm.prototype);
-
- assert(alarmNode.conditionOfNode() !== null);
-
- const inputNode = addressSpace._coerceNode(options.inputNode);
- assert(inputNode, "Expecting a valid input node");
- assert(inputNode instanceof UAVariable);
-
- // ----------------------- Install Limit Alarm specifics
- // from spec 1.03:
- // Four optional limits are defined that configure the states of the derived limit Alarm Types.
- // These Properties shall be set for any Alarm limits that are exposed by the derived limit Alarm
- // Types. These Properties are listed as optional but at least one is required. For cases where
- // an underlying system cannot provide the actual value of a limit, the limit Property shall still be
- // provided, but will have its AccessLevel set to not readable. It is assumed that the limits are
- // described using the same Engineering Unit that is assigned to the variable that is the source
- // of the alarm. For Rate of change limit alarms, it is assumed this rate is units per second
- // unless otherwise specified.
- if (count === 0) {
- throw new Error("at least one limit is required");
- }
-
- const dataType = addressSpace.findCorrespondingBasicDataType(options.inputNode.dataType);
- alarmNode._dataType = dataType;
-
- if (options.hasOwnProperty("highHighLimit")) {
- alarmNode.setHighHighLimit(options.highHighLimit);
- }
- if (options.hasOwnProperty("highLimit")) {
- alarmNode.setHighLimit(options.highLimit);
- }
- if (options.hasOwnProperty("lowLimit")) {
- alarmNode.setLowLimit(options.lowLimit);
- }
- if (options.hasOwnProperty("lowLowLimit")) {
- alarmNode.setLowLowLimit(options.lowLowLimit);
- }
-
- /*
- * The InputNode Property provides the NodeId of the Variable the Value of which is used as
- * primary input in the calculation of the Alarm state. If this Variable is not in the AddressSpace,
- * a Null NodeId shall be provided. In some systems, an Alarm may be calculated based on
- * multiple Variables Values; it is up to the system to determine which Variable’s NodeId is used.
- */
- assert(alarmNode.inputNode instanceof UAVariable);
- alarmNode.inputNode.setValueFromSource({ dataType: "NodeId", value: inputNode.nodeId });
-
-
- // install inputNode monitoring for change
- alarmNode._installInputNodeMonitoring(options.inputNode);
- alarmNode._watchLimits();
-
- return alarmNode;
- };
-
- UALimitAlarm.prototype.evaluateConditionsAfterEnabled = function () {
- assert(this.getEnabledState() === true);
- //simulate input value event
- const alarmNode = this;
- const dataValue = alarmNode.getInputNodeNode().readValue();
- alarmNode._onInputDataValueChange(dataValue);
- };
-
-