/// <summary> /// Recursively collects the variables in a NodeState and returns a collection of BrowsePaths. /// </summary> public void GetBrowsePathFromNodeState( ISystemContext context, NodeId rootId, NodeState parent, RelativePath parentPath, BrowsePathCollection browsePaths) { List<BaseInstanceState> children = new List<BaseInstanceState>(); parent.GetChildren(context, children); for (int ii = 0; ii < children.Count; ii++) { BaseInstanceState child = children[ii]; BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = rootId; browsePath.Handle = child; if (parentPath != null) { browsePath.RelativePath.Elements.AddRange(parentPath.Elements); } RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = child.ReferenceTypeId; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = child.BrowseName; browsePath.RelativePath.Elements.Add(element); if (child.NodeClass == NodeClass.Variable) { browsePaths.Add(browsePath); } GetBrowsePathFromNodeState(context, rootId, child, browsePath.RelativePath, browsePaths); } }
/// <summary> /// Returns the node ids for a set of relative paths. /// </summary> /// <param name="session">An open session with the server to use.</param> /// <param name="startNodeId">The starting node for the relative paths.</param> /// <param name="relativePaths">The relative paths.</param> /// <returns>A collection of local nodes.</returns> static List<NodeOfInterest> GetNodeIds( Session session, NodeId startNodeId, params string[] relativePaths) { // build the list of browse paths to follow by parsing the relative paths. BrowsePathCollection browsePaths = new BrowsePathCollection(); if (relativePaths != null) { for (int ii = 0; ii < relativePaths.Length; ii++) { BrowsePath browsePath = new BrowsePath(); // The relative paths used indexes in the namespacesUris table. These must be // converted to indexes used by the server. An error occurs if the relative path // refers to a namespaceUri that the server does not recognize. // The relative paths may refer to ReferenceType by their BrowseName. The TypeTree object // allows the parser to look up the server's NodeId for the ReferenceType. browsePath.RelativePath = RelativePath.Parse( relativePaths[ii], session.TypeTree, session.NamespaceUris, session.NamespaceUris); browsePath.StartingNode = startNodeId; browsePaths.Add(browsePath); } } // make the call to the server. BrowsePathResultCollection results; DiagnosticInfoCollection diagnosticInfos; ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); // ensure that the server returned valid results. Session.ValidateResponse(results, browsePaths); Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); Console.WriteLine("Translated {0} browse paths.", relativePaths.Length); // collect the list of node ids found. List<NodeOfInterest> nodes = new List<NodeOfInterest>(); for (int ii = 0; ii < results.Count; ii++) { // check if the start node actually exists. if (StatusCode.IsBad(results[ii].StatusCode)) { ServiceResult error = new ServiceResult( results[ii].StatusCode, diagnosticInfos[ii], responseHeader.StringTable); Console.WriteLine("Path '{0}' is not valid. Error = {1}", relativePaths[ii], error); continue; } // an empty list is returned if no node was found. if (results[ii].Targets.Count == 0) { Console.WriteLine("Path '{0}' does not exist.", relativePaths[ii]); continue; } // Multiple matches are possible, however, the node that matches the type model is the // one we are interested in here. The rest can be ignored. BrowsePathTarget target = results[ii].Targets[0]; if (target.RemainingPathIndex != UInt32.MaxValue) { Console.WriteLine("Path '{0}' refers to a node in another server.", relativePaths[ii]); continue; } // The targetId is an ExpandedNodeId because it could be node in another server. // The ToNodeId function is used to convert a local NodeId stored in a ExpandedNodeId to a NodeId. NodeOfInterest node = new NodeOfInterest(); node.NodeId = ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris); nodes.Add(node); } Console.WriteLine("Translate found {0} local nodes.", nodes.Count); // return whatever was found. return nodes; }
/// <summary> /// Updates the list of references. /// </summary> private void UpdateArguments(Session session, NodeId nodeId) { ArgumentsLV.Items.Clear(); // need to fetch the node ids for the argument properties. BrowsePathCollection browsePaths = new BrowsePathCollection(); foreach (string browseName in new string[] { BrowseNames.InputArguments, BrowseNames.OutputArguments }) { BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = nodeId; browsePath.Handle = browseName; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = true; element.TargetName = browseName; browsePath.RelativePath.Elements.Add(element); browsePaths.Add(browsePath); } // translate property names. BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); // create a list of values to read. ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < results.Count; ii++) { if (StatusCode.IsBad(results[ii].StatusCode) || results[ii].Targets.Count <= 0) { continue; } ReadValueId valueToRead = new ReadValueId(); valueToRead.NodeId = (NodeId)results[ii].Targets[0].TargetId; valueToRead.AttributeId = Attributes.Value; valueToRead.Handle = browsePaths[ii].Handle; valuesToRead.Add(valueToRead); } // read the values. if (valuesToRead.Count > 0) { DataValueCollection values = null; session.Read( null, 0, TimestampsToReturn.Neither, valuesToRead, out values, out diagnosticInfos); ClientBase.ValidateResponse(results, valuesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); // update the list control. for (int ii = 0; ii < values.Count; ii++) { // all structures are wrapped in extension objects. ExtensionObject[] extensions = values[ii].GetValue<ExtensionObject[]>(null); if (extensions != null) { // convert to an argument structure. Argument[] arguments = (Argument[])ExtensionObject.ToArray(extensions, typeof(Argument)); UpdateList(session, arguments, (string)valuesToRead[ii].Handle); } } } // auto size the columns. for (int ii = 0; ii < ArgumentsLV.Columns.Count; ii++) { ArgumentsLV.Columns[ii].Width = -2; } }