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 UALimitAlarm = require("./limit_alarm").UALimitAlarm;
const DataValue =  require("node-opcua-data-value").DataValue;
const AddressSpace = require("../address_space").AddressSpace;
const Namespace = require("../namespace").Namespace;
const ConditionInfo = require("./condition").ConditionInfo;

/***
 * @class  UANonExclusiveLimitAlarm
 * @extends UALimitAlarm
 * @constructor
 */
function UANonExclusiveLimitAlarm() {

    /**
     * @property lowLowState
     * @type UATwoStateVariable
     */
    /**
     * @property lowState
     * @type UATwoStateVariable
     */
    /**
     * @property highState
     * @type UATwoStateVariable
     */
    /**
     * @property highHighState
     * @type UATwoStateVariable
     */
}
util.inherits(UANonExclusiveLimitAlarm, UALimitAlarm);

UANonExclusiveLimitAlarm.prototype._calculateConditionInfo = function (states, isActive, value, oldConditionInfo) {

    if (!isActive) {
        return new ConditionInfo({
            severity: 0,
            message: "Back to normal",
            quality: StatusCodes.Good,
            retain: true
        });

    } else {
        // build-up state string
        let state_str = Object.keys(states).map(function(s) {
            return  states[s] === true ? s : null;
        }).filter(function(a) { return !!a;}).join(";"); //

        state_str = JSON.stringify(states);

        return new ConditionInfo({
            severity: 150,
            message: "Condition value is " + value + " and state is " + state_str,
            quality: StatusCodes.Good,
            retain: true
        });

    }

};

UANonExclusiveLimitAlarm.prototype._signalNewCondition = function (states, isActive, value) {

    const alarm = this;

    if (!states) {
        return;
    }
    function _install(name) {
        if (states[name] !== "unset") {
            alarm[name + "State"].setValue(states[name]);
        }
    }

    _install("highHigh");
    _install("high");
    _install("low");
    _install("lowLow");

    UALimitAlarm.prototype._signalNewCondition.call(this, states, isActive, value);
};

UANonExclusiveLimitAlarm.prototype._setStateBasedOnInputValue = function (value) {

    assert(_.isFinite(value),"expecting a valid value here");

    const alarm = this;

    let isActive = false;

    const states = {
        highHigh: alarm.highHighState ? alarm.highHighState.getValue() : "unset",
        high: alarm.highState ? alarm.highState.getValue() : "unset",
        low: alarm.lowState ? alarm.lowState.getValue() : "unset",
        lowLow: alarm.lowLowState ? alarm.lowLowState.getValue() : "unset"
    };

    let count = 0;

    function ___p(stateName, func_value) {
        if (states[stateName] !== "unset") {
            const value = func_value();
            isActive = isActive || value;
            if (states[stateName] !== value) {
                states[stateName] = value;
                count += 1;
            }
        }
    }

    ___p("highHigh", function () {
        return alarm.getHighHighLimit() < value;
    });
    ___p("high", function () {
        return alarm.getHighLimit() < value;
    });
    ___p("low", function () {
        return alarm.getLowLimit() > value;
    });
    ___p("lowLow", function () {
        return alarm.getLowLowLimit() > value;
    });

    if (count > 0) {
        alarm._signalNewCondition(states, isActive, value)
    }
};

exports.UANonExclusiveLimitAlarm = UANonExclusiveLimitAlarm;

/**
 * @method (static)instantiate
 * @param namespace {Namespace}
 * @param type
 * @param options
 * @param data
 * @return {UANonExclusiveLimitAlarm}
 */
UANonExclusiveLimitAlarm.instantiate = function (namespace, type, options, data) {

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

    options.optionals = options.optionals || [];

    if (options.hasOwnProperty("lowLowLimit")) {
        options.optionals.push("LowLowLimit");
        options.optionals.push("LowLowState");
    }
    if (options.hasOwnProperty("lowLimit")) {
        options.optionals.push("LowLimit");
        options.optionals.push("LowState");
    }
    if (options.hasOwnProperty("highLimit")) {
        options.optionals.push("HighLimit");
        options.optionals.push("HighState");
    }
    if (options.hasOwnProperty("highHighLimit")) {
        options.optionals.push("HighHighLimit");
        options.optionals.push("HighHighState");
    }
    const nonExclusiveAlarmType = addressSpace.findEventType(type);

    /* istanbul ignore next */
    if (!nonExclusiveAlarmType) {
        throw new Error(" cannot find Alarm Condition Type for " + type);
    }

    const nonExclusiveLimitAlarmType = addressSpace.findEventType("NonExclusiveLimitAlarmType");
    /* istanbul ignore next */
    if (!nonExclusiveLimitAlarmType) {
        throw new Error("cannot find NonExclusiveLimitAlarmType");
    }
    //assert(type nonExclusiveLimitAlarmType.browseName.toString());

    const alarm = UALimitAlarm.instantiate(namespace, type, options, data);
    Object.setPrototypeOf(alarm, UANonExclusiveLimitAlarm.prototype);
    assert(alarm instanceof UALimitAlarm);
    assert(alarm instanceof UANonExclusiveLimitAlarm);

    // ---------------- install States
    if (alarm.lowLowState) {
        AddressSpace._install_TwoStateVariable_machinery(alarm.lowLowState, {
            trueState: "LowLow active",
            falseState: "LowLow inactive"
        });
        alarm.lowLowState.setValue(false);
        assert(alarm.hasOwnProperty("lowLowLimit"));
    }
    if (alarm.lowState) {
        AddressSpace._install_TwoStateVariable_machinery(alarm.lowState, {
            trueState: "Low active",
            falseState: "Low inactive"
        });
        alarm.lowState.setValue(false);
        assert(alarm.hasOwnProperty("lowLimit"));
    }
    if (alarm.highState) {
        AddressSpace._install_TwoStateVariable_machinery(alarm.highState, {
            trueState: "High active",
            falseState: "High inactive"
        });
        alarm.highState.setValue(false);
        assert(alarm.hasOwnProperty("highLimit"));
    }
    if (alarm.highHighState) {
        AddressSpace._install_TwoStateVariable_machinery(alarm.highHighState, {
            trueState: "HighHigh active",
            falseState: "HighHigh inactive"
        });
        alarm.highHighState.setValue(false);
        assert(alarm.hasOwnProperty("highHighLimit"));
    }

    alarm.activeState.setValue(false);

    alarm.updateState();

    return alarm;
};