APIs

Show:
"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 AddressSpace = require("../address_space").AddressSpace;
const Namespace = require("../namespace").Namespace;
/**
 * @module opcua.address_space.AlarmsAndConditions
 */

const UADiscreteAlarm = require("./discrete_alarm").UADiscreteAlarm;

/**
 * The OffNormalAlarmType is a specialization of the DiscreteAlarmType intended to represent a
 * discrete Condition that is considered to be not normal.
 * This sub type is usually used to indicate that a discrete value is in an Alarm state, it is active as
 * long as a non-normal value is present.
 *
 * @class UAOffNormalAlarm
 * @extends UADiscreteAlarm
 * @constructor
 */
function UAOffNormalAlarm() {
    // HasProperty Variable NormalState NodeId PropertyType Mandatory
    // The NormalState Property is a Property that points to a Variable which has a value that
    // corresponds to one of the possible values of the Variable pointed to by the InputNode
    // Property where the NormalState Property Variable value is the value that is considered to be
    // the normal state of the Variable pointed to by the InputNode Property. When the value of the
    // Variable referenced by the InputNode Property is not equal to the value of the NormalState
    // Property the Alarm is Active. If this Variable is not in the AddressSpace, a Null NodeId shall
    // be provided.
    /**
     * @property NormalState {UAVariableType}
     *
     */
}
util.inherits(UAOffNormalAlarm, UADiscreteAlarm);

/**
 * @method getNormalStateNode
 * @return {BaseNode}
 */
UAOffNormalAlarm.prototype.getNormalStateNode = function () {
    const nodeId = this.normalState.readValue().value.value;
    const node = this.addressSpace.findNode(nodeId);
    assert(node, "getNormalStateNode ");
    return node;
};

/**
 * @method getNormalStateValue
 * @return {Any}
 */
UAOffNormalAlarm.prototype.getNormalStateValue = function () {
    const normalStateNode = this.getNormalStateNode();
    return normalStateNode.readValue().value.value;
};

/**
 * @method setNormalStateValue
 * @param value
 */
UAOffNormalAlarm.prototype.setNormalStateValue = function (value) {
    const normalStateNode = this.getNormalStateNode();
    throw new Error("Not Implemented yet");
};
const utils = require("node-opcua-utils");

function isEqual(value1, value2) {
    return value1 === value2;
}
UAOffNormalAlarm.prototype._updateAlarmState = function (normalStateValue, inputValue) {

    const alarm = this;

    if (utils.isNullOrUndefined(normalStateValue) || utils.isNullOrUndefined(inputValue)) {
        this.activeState.setValue(false);
        return;
    }
    const isActive = !isEqual(normalStateValue, inputValue);

    if (isActive === alarm.activeState.getValue()) {
        // no change => ignore !
        return;
    }

    const stateName = isActive ? "Active" : "Inactive";
    // also raise the event
    alarm._signalNewCondition(stateName, isActive, "");

};



UAOffNormalAlarm.prototype._onInputDataValueChange = function (dataValue) {

    if (dataValue.statusCode !== StatusCodes.Good) {
        // what shall we do ?
        return;
    }
    if (dataValue.value.dataType === DataType.Null) {
        // what shall we do ?
        return;
    }
    const inputValue = dataValue.value.value;
    const normalStateValue = this.getNormalStateValue();
    this._updateAlarmState(normalStateValue, inputValue);

};
UAOffNormalAlarm.prototype._onNormalStateDataValueChange = function (dataValue) {

    if (dataValue.statusCode !== StatusCodes.Good) {
        // what shall we do ?
        return;
    }
    if (dataValue.value.dataType === DataType.Null) {
        // what shall we do ?
        return;
    }
    const normalStateValue = dataValue.value.value;
    const inputValue = this.getInputNodeValue();
    this._updateAlarmState(normalStateValue, inputValue);
};


/**
 * @method (static)UAOffNormalAlarm.instantiate
 * @param namespace {Namespace}
 * @param limitAlarmTypeId
 * @param options
 * @param options.inputNode   {NodeId|UAVariable} the input node
 * @param options.normalState {NodeId|UAVariable} the normalStateNode node
 * @param data
 *
 * When the value of inputNode doesn't match the normalState node value, then the alarm is raised.
 *
 */
UAOffNormalAlarm.instantiate = function (namespace, limitAlarmTypeId, options, data) {

    assert(namespace instanceof Namespace);
    const addressSpace = namespace.addressSpace;
    assert(addressSpace instanceof AddressSpace);

    const offNormalAlarmType = addressSpace.findEventType("OffNormalAlarmType");
    /* istanbul ignore next */
    if (!offNormalAlarmType) {
        throw new Error("cannot find offNormalAlarmType");
    }

    assert(options.hasOwnProperty("inputNode"), "must provide inputNode");          // must provide a inputNode
    assert(options.hasOwnProperty("normalState"), "must provide a normalState Node"); // must provide a inputNode
    options.optionals = options.optionals || [];

    assert(options.hasOwnProperty("inputNode"), "must provide inputNode"); // must provide a inputNode
    const alarmNode = UADiscreteAlarm.instantiate(namespace, limitAlarmTypeId, options, data);
    Object.setPrototypeOf(alarmNode, UAOffNormalAlarm.prototype);

    const inputNode = addressSpace._coerceNode(options.inputNode);
    assert(inputNode, "Expecting a valid input node");

    const normalState = addressSpace._coerceNode(options.normalState);
    assert(normalState, "Expecting a valid normalState node");

    alarmNode.normalState.setValueFromSource({ dataType: DataType.NodeId, value: normalState.nodeId });

    // install inputNode Node monitoring for change
    alarmNode._installInputNodeMonitoring(options.inputNode);

    alarmNode.normalState.on("value_changed", function (newDataValue, oldDataValue) {
        // The node that contains the normalState value has changed.
        //   we must remove the listener on current normalState and replace
        //   normalState with the new one and set listener again
        //   to do:
    });

    // install normalState monitoring for change
    normalState.on("value_changed", function (newDataValue, oldDataValue) {
        alarmNode._onNormalStateDataValueChange(newDataValue);
    });

    alarmNode._updateAlarmState();

    return alarmNode;
};

module.exports.UAOffNormalAlarm = UAOffNormalAlarm;


/**
 * System Off Normal Alarm.
 *
 * This Condition is used by a Server to indicate that an underlying system that is providing  Alarm information is
 * having a communication problem and that the Server may have invalid or incomplete Condition state in the
 * Subscription.
 *
 * @class UASystemOffNormalAlarm
 * @constructor
 * @extends UAOffNormalAlarm
 */
function UASystemOffNormalAlarm() {
}
util.inherits(UASystemOffNormalAlarm, UAOffNormalAlarm);