Example #1
0
function callConditionRefresh(subscription,callback) {

    var the_session    = subscription.publish_engine.session;
    var subscriptionId = subscription.subscriptionId;

    assert(_.isFinite(subscriptionId),"May be subscription is not yet initialized");
    assert(_.isFunction(callback));

    var conditionTypeNodeId = resolveNodeId("ConditionType");

    var browsePath = [
        makeBrowsePath(conditionTypeNodeId,".ConditionRefresh")
    ];
    var conditionRefreshId  = resolveNodeId("ConditionType_ConditionRefresh");

    //xx console.log("browsePath ", browsePath[0].toString({addressSpace: server.engine.addressSpace}));

    async.series([

        // find conditionRefreshId
        function (callback) {

            the_session.translateBrowsePath(browsePath, function (err, results) {
                if(!err ) {
                    // istanbul ignore else
                    if (results[0].targets.length > 0){
                        conditionRefreshId = results[0].targets[0].targetId;
                    } else {
                        // cannot find conditionRefreshId
                        console.log("cannot find conditionRefreshId",results[0].toString());
                        err = new Error(" cannot find conditionRefreshId");
                    }
                }
                callback(err);
            });
        },
        function (callback) {

            var methodsToCall = [{
                objectId: conditionTypeNodeId,
                methodId: conditionRefreshId,
                inputArguments: [
                    new Variant({ dataType: DataType.UInt32, value: subscriptionId })
                ]
            }];

            the_session.call(methodsToCall,function(err,results) {
                if (err) {
                    return callback(err);
                }
                // istanbul ignore next
                if (results[0].statusCode !== StatusCodes.Good) {
                    return callback(new Error("Error " + results[0].statusCode.toString()));
                }
                callback();
            });
        }
    ],callback);
}
/**
 *
 * @method extractEventField
 * extract a eventField from a event node, matching the given selectClause
 * @param eventData
 * @param selectClause
 */
function extractEventField(eventData, selectClause) {

    assert_valid_event_data(eventData);
    assert(selectClause instanceof SimpleAttributeOperand);

    selectClause.browsePath = selectClause.browsePath || [];

    if (selectClause.browsePath.length === 0 && selectClause.attributeId === AttributeIds.NodeId) {

        // "ns=0;i=2782" => ConditionType
        // "ns=0;i=2041" => BaseEventType
        if (selectClause.typeId.toString() !== "ns=0;i=2782") {
            // not ConditionType
            console.warn("this case is not handled yet : selectClause.typeId = " + selectClause.typeId.toString());
            const eventSource = eventData.$eventDataSource;
            return new Variant({dataType: DataType.NodeId, value: eventSource.nodeId});
        }
        const conditionTypeNodeId = resolveNodeId("ConditionType");
        assert(sameNodeId(selectClause.typeId,conditionTypeNodeId));

        const eventSource  = eventData.$eventDataSource;
        const eventSourceTypeDefinition = eventSource.typeDefinitionObj;
        if (!eventSourceTypeDefinition) {
            // eventSource is a EventType class
            return new Variant();
        }
        const addressSpace = eventSource.addressSpace;
        const conditionType = addressSpace.findObjectType(conditionTypeNodeId);

        if (!eventSourceTypeDefinition.isSupertypeOf(conditionType)) {
            return new Variant();
        }
        //xx assert(eventSource instanceof UAConditionBase);
        // Yeh : our EventType is a Condition Type !
        return new Variant({dataType: DataType.NodeId, value: eventSource.nodeId});
    }


    var handle = eventData.resolveSelectClause(selectClause);

    if (handle !== null) {
        var value = eventData.readValue(handle,selectClause);
        assert(value instanceof Variant);
        return value;

    } else {

        ///xx console.log(" Cannot find selectClause ",selectClause.toString());
        // Part 4 - 7.17.3
        // A null value is returned in the corresponding event field in the Publish response if the selected
        // field is not part of the Event or an error was returned in the selectClauseResults of the EventFilterResult.
        // return new Variant({dataType: DataType.StatusCode, value: browsePathResult.statusCode});
        return new Variant();
    }
    //xx var innerNode =
}
Example #3
0
        init: function (name, attrs) {
            this.obj = {};
            this.obj.nodeClass = NodeClass.Method;
            // MethodDeclarationId
            // ParentNodeId
            this.obj.browseName = convertQualifiedName(attrs.BrowseName);
            this.obj.parentNodeId = attrs.ParentNodeId || null;
            this.obj.nodeId = convertToNodeId(attrs.NodeId) || null;
            this.obj.methodDeclarationId = attrs.MethodDeclarationId ? resolveNodeId(attrs.MethodDeclarationId) : null;

        },
NodeCrawler.prototype._createCacheNode = function (nodeId) {
    var self = this;
    var key = resolveNodeId(nodeId).toString();
    var cacheNode = self._objectCache[key];
    if (cacheNode) {
        throw new Error("NodeCrawler#_createCacheNode : cache node should not exist already : " + nodeId.toString());
    }
    cacheNode = new CacheNode(nodeId);
    assert(!self._objectCache.hasOwnProperty(key));
    self._objectCache[key] = cacheNode;
    return cacheNode;
};
NodeCrawler.prototype._crawl_task = function (task, callback) {

    var self = this;

    var cacheNode = task.params.cacheNode;
    var nodeId = task.params.cacheNode.nodeId;

    nodeId = resolveNodeId(nodeId);
    var key = nodeId.toString();

    if (self._visited_node.hasOwnProperty(key)) {
        console.log("skipping already visited", key);
        callback();
        return;// already visited
    }
    // mark as visited to avoid infinite recursion
    self._visited_node[key] = true;

    function browse_node_action(err, cacheNode) {
        if (!err) {
            for (var i = 0; i < cacheNode.references.length; i++) {

                var reference = cacheNode.references[i];
                // those ones come for free
                if (!self.has_cache_NodeAttribute(reference.nodeId, AttributeIds.BrowseName)) {
                    self.set_cache_NodeAttribute(reference.nodeId, AttributeIds.BrowseName, reference.browseName);
                }
                if (!self.has_cache_NodeAttribute(reference.nodeId, AttributeIds.DisplayName)) {
                    self.set_cache_NodeAttribute(reference.nodeId, AttributeIds.DisplayName, reference.displayName);
                }
                if (!self.has_cache_NodeAttribute(reference.nodeId, AttributeIds.NodeClass)) {
                    self.set_cache_NodeAttribute(reference.nodeId, AttributeIds.NodeClass, reference.nodeClass);
                }
            }
            self._emit_on_crawled(cacheNode, task.params.userData);
            var userData = task.params.userData;
            if (userData.onBrowse) {
                userData.onBrowse(self, cacheNode, userData);
            }

        }
    }

    self._defer_browse_node(cacheNode, referencesId, browse_node_action);
    callback();
};
Example #6
0
                    finish: function () {

                        var typeId = this.text.trim();
                        this.parent.parent.typeId = resolveNodeId(typeId);

                        switch (typeId) {
                            case "i=297":  // Argument
                                break;
                            case "i=7616": // EnumValueType
                                break;
                            case "i=888":  // EUInformation
                                break;
                            default:
                                console.warn("loadnodeset2 ( checking identifier type) : unsupported typeId in ExtensionObject " + typeId);
                                break;
                        }
                    }
ClientSubscription.prototype.monitor = function (itemToMonitor, requestedParameters, timestampsToReturn, done) {
    var self = this;
    assert(done === undefined || _.isFunction(done));

    itemToMonitor.nodeId = resolveNodeId(itemToMonitor.nodeId);
    var monitoredItem = new ClientMonitoredItem(this, itemToMonitor, requestedParameters, timestampsToReturn);

    self._wait_for_subscription_to_be_ready(function (err) {
        if (err) {
            return done && done(err);
        }
        monitoredItem._monitor(function (err) {
            if (err) {
                return done && done(err);
            }
            done && done(err, monitoredItem);
        });
    });
    return monitoredItem;
};
Example #8
0
    construct_hook: function(options) {

        var dataType = options.dataType;
        if (dataType) {
            if (typeof dataType === "string") {
                dataType = resolveNodeId(dataType);
            } else if ( dataType instanceof NodeId ) {
                // nothing
            } else {
                assert(dataType.hasOwnProperty("value"));
                dataType = coerceNodeId(dataType.value,dataType.namespace);
            }
           options.dataType = dataType;
        }

        // fix missing ArrayDimension (The value is an array with one dimension.)
        if (!options.valueRank === 1 || !options.arrayDimensions) {
            options.arrayDimensions = [0];
        }

        return options;

    },
NodeCrawler.prototype._defer_readNode = function (nodeId, attributeId, callback) {
    var self = this;

    nodeId = resolveNodeId(nodeId);
    assert(nodeId instanceof NodeId);

    var key = make_node_attribute_key(nodeId, attributeId);

    if (self.has_cache_NodeAttribute(nodeId, attributeId)) {
        callback(null, self.get_cache_NodeAttribute(nodeId, attributeId));
    } else {
        self.browseNameMap[key] = "?";
        self._nodesToReadEx.push({
            nodeToRead: {
                nodeId: nodeId,
                attributeId: attributeId
            },
            action: function (dataValue) {
                self.set_cache_NodeAttribute(nodeId, attributeId, dataValue);
                callback(null, dataValue);
            }
        });
    }
};
 *   .                      The period (dot) character indicates that the Server is to follow
 *                          any subtype of a Aggregates ReferenceType.
 *  <[#!ns:]ReferenceType>
 *                          A string delimited by the ‘<’ and ‘>’ symbols specifies the BrowseName
 *                          of a ReferenceType to follow. By default, any References of the subtypes
 *                          the ReferenceType are followed as well. A ‘#’ placed in front of the BrowseName
 *                          indicates that subtypes should not be followed.
 *                          A ‘!’ in front of the BrowseName is used to indicate that the inverse Reference
 *                          should be followed.
 *                          The BrowseName may be qualified with a namespace index (indicated by a numeric
 *                          prefix followed by a colon). This namespace index is used specify the namespace
 *                          component of the BrowseName for the ReferenceType. If the namespace prefix is
 *                          omitted then namespace index 0 is used.
 */

var hierarchicalReferenceTypeNodeId = resolveNodeId("HierarchicalReferences");
var aggregatesReferenceTypeNodeId = resolveNodeId("Aggregates");

var RelativePath  = require("../_generated_/_auto_generated_RelativePath").RelativePath;


//  The following BNF describes the syntax of the RelativePath text format.
//  <relative-path> ::= <reference-type> <browse-name> [relative-path]
//  <reference-type> ::= '/' | '.' | '<' ['#'] ['!'] <browse-name> '>'
//  <browse-name> ::= [<namespace-index> ':'] <name>
//  <namespace-index> ::= <digit> [<digit>]
//  <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
//  <name>  ::= (<name-char> | '&' <reserved-char>) [<name>]
//  <reserved-char> ::= '/' | '.' | '<' | '>' | ':' | '#' | '!' | '&'
//  <name-char> ::= All valid characters for a String (see Part 3) excluding reserved-chars.
//
Example #11
0
 function add_alias(alias_name, nodeId) {
     nodeId = resolveNodeId(nodeId);
     addressSpace.add_alias(alias_name, nodeId);
 }
Example #12
0
 finish: function () {
     this.parent.parent.argument.dataType = resolveNodeId(this.text.trim());
 }
 itemsToMonitor.forEach(function (itemToMonitor) {
     itemToMonitor.nodeId = resolveNodeId(itemToMonitor.nodeId);
 });
NodeCrawler.prototype.read = function (nodeId, callback) {

    var self = this;

    try {
        nodeId = resolveNodeId(nodeId);
    } catch (err) {
        callback(err);
    }

    function remove_cycle(object, callback) {


        var visitedNodeIds = {};

        function hasBeenVisited(e) {
            var key = e.nodeId.toString();
            return visitedNodeIds[key];
        }

        function setVisited(e) {
            var key = e.nodeId.toString();
            return visitedNodeIds[key] = e;
        }

        function mark_array(arr) {
            if (!arr) {
                return;
            }
            assert(_.isArray(arr));
            for (var index = 0; index < arr.length; index++) {
                var e = arr[index];
                if (hasBeenVisited(e)) {
                    return;
                } else {
                    setVisited(e);
                    explorerObject(e);
                }
            }
        }

        function explorerObject(obj) {
            mark_array(obj.organizes);
            mark_array(obj.hasComponent);
            mark_array(obj.hasNotifier);
            mark_array(obj.hasProperty);
        }


        explorerObject(object);
        callback(null, object);
    }

    function simplify_object(objMap, object, final_callback) {

        assert(_.isFunction(final_callback));

        var queue = async.queue(function (task, callback) {

            setImmediate(function () {
                assert(_.isFunction(task.func));
                task.func(task.data, callback);
            });
        }, 1);

        var key = object.nodeId.toString();

        function add_for_reconstruction(object, extra_func) {
            assert(_.isFunction(extra_func));
            assert(typeof object.nodeId.toString() === "string");
            queue.push({
                data: object,
                func: function (data, callback) {

                    _reconstruct_manageable_object(data, function (err, obj) {
                        extra_func(err, obj);
                        callback(err);
                    });
                }
            });
        }

        function _reconstruct_manageable_object(object, callback) {

            assert(_.isFunction(callback));
            assert(object);
            assert(object.nodeId);

            var key = object.nodeId.toString();

            if (objMap.hasOwnProperty(key)) {
                return callback(null, objMap[key]);
            }
            /* reconstruct a more manageable object
             * var obj = {
             *    browseName: "Objects",
             *    organises : [
             *       {
             *            browseName: "Server",
             *            hasComponent: [
             *            ]
             *            hasProperty: [
             *            ]
             *       }
             *    ]
             * }
             */
            var obj = {
                browseName: object.browseName.name,
                nodeId: object.nodeId.toString()
            };

            // Append nodeClass
            if (object.nodeClass) {
                obj.nodeClass = object.nodeClass.toString();
            }
            if (object.dataType) {
                obj.dataType = object.dataType.toString();
                obj.dataTypeName = object.dataTypeName;
                //xx  console.log("dataTypeObj",object.dataTypeObj.browseName);
            }
            if (object.dataValue) {
                if (object.dataValue instanceof Array || object.dataValue.length > 10) {
                    // too much verbosity here
                } else {
                    obj.dataValue = object.dataValue.toString();
                }
            }
            objMap[key] = obj;

            var referenceMap = obj;

            object.references = object.references || [];


            object.references.map(function (ref) {

                assert(ref);
                var ref_index = ref.referenceTypeId.toString();

                var referenceType = self._objectCache[ref_index];

                if (!referenceType) {
                    console.log(("Unknown reference type " + ref_index).red.bold);
                    console.log(util.inspect(object, {colorize: true, depth: 10}));
                }
                var reference = self._objectCache[ref.nodeId.toString()];
                if (!reference) {
                    console.log(ref.nodeId.toString(), "bn=", ref.browseName.toString(), "class =", ref.nodeClass.toString(), ref.typeDefinition.toString());
                    console.log("#_reconstruct_manageable_object: Cannot find reference", ref.nodeId.toString(), "in cache");
                }
                // Extract nodeClass so it can be appended
                reference.nodeClass = ref.$nodeClass;

                var refName = lowerFirstLetter(referenceType.browseName.name);

                if (refName === "hasTypeDefinition") {
                    obj.typeDefinition = reference.browseName.name;
                } else {
                    if (!referenceMap[refName]) {
                        referenceMap[refName] = [];
                    }
                    add_for_reconstruction(reference, function (err, mobject) {
                        if (!err) {
                            referenceMap[refName].push(mobject);
                        }
                    });
                }
            });
            callback(null, obj);

        }

        add_for_reconstruction(object, function () {
        });

        queue.drain = function () {
            var object = self._objMap[key];
            remove_cycle(object, callback);
        };
    }

    var key = nodeId.toString();

    // check if object has already been crawled
    if (self._objMap.hasOwnProperty(key)) {
        var object = self._objMap[key];
        return callback(null, object);
    }

    var userData = {
        onBrowse: NodeCrawler.follow
    };


    self.crawl(nodeId, userData, function () {

        if (self._objectCache.hasOwnProperty(key)) {

            var cacheNode = self._objectCache[key];
            assert(cacheNode.browseName.name !== "pending");

            simplify_object(self._objMap, cacheNode, callback);

        } else {
            callback(new Error("Cannot find nodeid" + key));
        }
    });
};
/**
 * construct a RelativePath from a string containing the relative path description.
 * The string must comply to the OPCUA BNF for RelativePath ( see part 4 - Annexe A)
 * @method makeRelativePath
 * @param str {String}
 * @param addressSpace {AddressSpace}
 * @return {RelativePath}
 *
 * @example:
 *
 *      var relativePath = makeRelativePath("/Server.ServerStatus.CurrentTime");
 *
 */
function makeRelativePath(str,addressSpace) {


    var r ={
        elements:[]
    };

    while (str.length>0) {

        var matches = str.match(regRelativePath);
        if (!matches) {
            throw new Error("Malformed relative path  :'" + str +"'");
        }
        // console.log(mm);

        var referenceTypeId,includeSubtypes,isInverse;

        //
        // ------------ extract reference type
        //
        var refStr = matches[1];
        if (refStr === "/" ) {

            referenceTypeId= hierarchicalReferenceTypeNodeId;
            isInverse= false;
            includeSubtypes= true;
        }else if (refStr === "." ) {

            referenceTypeId= aggregatesReferenceTypeNodeId;
            isInverse= false;
            includeSubtypes= true;
        } else {

            // match  3 =>    "#" or null
            includeSubtypes = (matches[3] !== "#");

            // match  4 =>    "!" or null
            isInverse = (matches[4] === "!");

            // match 5
            // namespace match 6 ( ns:)
            // name      match 7
            var ns = matches[6] ? parseInt(matches[6]) :0;
            var name = matches[7];
            if ( !matches[6] ) {
                //xx console.log( mm[6])
                referenceTypeId = resolveNodeId(name);

            } else {
                // AddressSpace.prototype.findReferenceType = function (refType,namespace)
                referenceTypeId = addressSpace.findReferenceType(name,ns);
            }
            assert(referenceTypeId && !referenceTypeId.isEmpty());
        }

        r.elements.push({
            referenceTypeId: referenceTypeId,
            isInverse: isInverse,
            includeSubtypes: includeSubtypes,
            targetName: makeQualifiedName(matches)
        });

        str = str.substr(matches[0].length);
    }


    r = new RelativePath(r);
    //xx console.log(r.toString());
    return r;
}
NodeCrawler.prototype._defer_browse_node = function (cacheNode, referenceTypeId, actionOnBrowse) {
    var self = this;
    self._objectToBrowse.push({
        cacheNode: cacheNode,
        nodeId: cacheNode.nodeId,
        referenceTypeId: referenceTypeId,
        action: function (object) {
            assert(object === cacheNode);
            assert(_.isArray(object.references));
            assert(cacheNode.browseName.name !== "pending");
            actionOnBrowse(null, cacheNode);
        }
    });
};

var referencesId = resolveNodeId("References");
var hierarchicalReferencesId = resolveNodeId("HierarchicalReferences");
var hasTypeDefinitionId = resolveNodeId("HasTypeDefinition");


function dedup_reference(references) {
    var results = [];
    var dedup = {};
    for (var i = 0; i < references.length; i++) {

        const reference = references[i];

        const key = reference.referenceTypeId.toString() + reference.nodeId.toString();
        if (dedup[key]) {
            console.log(" Warning => Duplicated reference found  !!!! please contact the server vendor");
            console.log(reference.toString());
NodeCrawler.prototype._getCacheNode = function (nodeId) {
    var self = this;
    var key = resolveNodeId(nodeId).toString();
    var cacheNode = self._objectCache[key];
    return cacheNode;
};