/// <summary> /// Returns a list of remote browse paths for a list of local relative paths. /// </summary> public BrowsePathCollection GetRemoteBrowsePaths(NodeId localNodeId, params string[] relativePaths) { BrowsePathCollection browsePaths = new BrowsePathCollection(); if (relativePaths != null) { for (int ii = 0; ii < relativePaths.Length; ii++) { BrowsePath browsePath = new BrowsePath(); browsePath.RelativePath = RelativePath.Parse(relativePaths[ii], this.m_typeTable); browsePath.StartingNode = GetRemoteNodeId(localNodeId); for (int jj = 0; jj < browsePath.RelativePath.Elements.Count; jj++) { QualifiedName targetName = browsePath.RelativePath.Elements[jj].TargetName; targetName = GetRemoteQualifiedName(targetName); browsePath.RelativePath.Elements[jj].TargetName = targetName; NodeId referenceTypeId = browsePath.RelativePath.Elements[jj].ReferenceTypeId; referenceTypeId = GetRemoteNodeId(referenceTypeId); browsePath.RelativePath.Elements[jj].ReferenceTypeId = referenceTypeId; } browsePaths.Add(browsePath); } } return(browsePaths); }
private void OkBTN_Click(object sender, EventArgs e) { try { BrowsePathCollection browsePaths = new BrowsePathCollection(); BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = NodeId.Parse(StartNode.Text); browsePath.RelativePath = Opc.Ua.RelativePath.Parse(RelativePath.Text, m_session.TypeTree); browsePaths.Add(browsePath); BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); if (results != null && results.Count == 1) { // NodesCTRL.SetNodeList(results[0].MatchingNodeIds); } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
/// <summary> /// Adds a single hop path for all references for the node. /// </summary> private void AddSingleHopPaths(Node node, BrowsePathCollection pathsToTranslate) { ReferenceDescriptionCollection references = node.Handle as ReferenceDescriptionCollection; if (references == null) { return; } for (int ii = 0; ii < references.Count; ii++) { BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = node.NodeId; browsePath.Handle = node; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = references[ii].ReferenceTypeId; element.IsInverse = !references[ii].IsForward; element.IncludeSubtypes = false; element.TargetName = references[ii].BrowseName; browsePath.RelativePath.Elements.Add(element); pathsToTranslate.Add(browsePath); } }
public async Task TranslateBrowsePathsToNodeIdsAsync() { var browsePaths = new BrowsePathCollection(); var browsePath = new BrowsePath() { StartingNode = ObjectIds.RootFolder, RelativePath = new RelativePath("Types") }; for (int ii = 0; ii < kOperationLimit * 2; ii++) { browsePaths.Add(browsePath); } var requestHeader = new RequestHeader(); var response = await Session.TranslateBrowsePathsToNodeIdsAsync(requestHeader, browsePaths, CancellationToken.None).ConfigureAwait(false); BrowsePathResultCollection results = response.Results; DiagnosticInfoCollection diagnosticInfos = response.DiagnosticInfos; ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); Assert.NotNull(response.ResponseHeader); }
private void OkBTN_Click(object sender, EventArgs e) { try { BrowsePathCollection browsePaths = new BrowsePathCollection(); BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = NodeId.Parse(StartNode.Text); browsePath.RelativePath = Opc.Ua.RelativePath.Parse(RelativePath.Text, m_session.TypeTree); browsePaths.Add(browsePath); BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); if (results != null && results.Count == 1) { // NodesCTRL.SetNodeList(results[0].MatchingNodeIds); } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
/// <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); } }
private CallResourceResponse TranslateBrowsePathToNode(CallResourceRequest request, Session connection, NameValueCollection queryParams, NamespaceTable nsTable) { CallResourceResponse response = new CallResourceResponse(); var body = request.Body.ToString(Encoding.UTF8); var relativeBrowsePath = JsonSerializer.Deserialize <RelativeBrowsePath>(body); var rootId = relativeBrowsePath.startNode; var bp = relativeBrowsePath.browsePath; var bpColl = new BrowsePathCollection(); var browsePath = new BrowsePath(); browsePath.StartingNode = Converter.GetNodeId(rootId, nsTable); var relativePaths = bp.Select(qm => new RelativePathElement() { TargetName = Converter.GetQualifiedName(qm, nsTable), IsInverse = false, IncludeSubtypes = true, ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HierarchicalReferences }); browsePath.RelativePath.Elements.AddRange(relativePaths); bpColl.Add(browsePath); connection.TranslateBrowsePathsToNodeIds(null, bpColl, out BrowsePathResultCollection results, out DiagnosticInfoCollection diagnosticInfos); if (Opc.Ua.StatusCode.IsBad(results[0].StatusCode)) { throw new ArgumentException(results[0].StatusCode.ToString()); } if (results[0].Targets.Count == 0) { throw new ArgumentException("Could find node for browse path."); } var nodeId = ExpandedNodeId.ToNodeId(results[0].Targets[0].TargetId, nsTable); var nodeInfo = ReadNodeInfo(connection, nsTable, Converter.GetNodeIdAsJson(nodeId, nsTable)); var result = JsonSerializer.Serialize(nodeInfo); response.Code = 200; response.Body = ByteString.CopyFrom(result, Encoding.ASCII); return(response); }
public void TranslateBrowsePathsToNodeIds() { var browsePaths = new BrowsePathCollection(); var browsePath = new BrowsePath() { StartingNode = ObjectIds.RootFolder, RelativePath = new RelativePath("Objects") }; for (int ii = 0; ii < kOperationLimit * 2; ii++) { browsePaths.Add(browsePath); } var requestHeader = new RequestHeader(); var responseHeader = Session.TranslateBrowsePathsToNodeIds(requestHeader, browsePaths, out BrowsePathResultCollection results, out DiagnosticInfoCollection diagnosticInfos); ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); Assert.NotNull(responseHeader); }
/// <summary> /// Finds an element identified by the path from the root. /// </summary> private AeBrowseElement Find(Session session, string itemId, AeBrowseElement root, Stack <string> names, bool isArea) { string browseText = null; BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = root.NodeId; while (names.Count > 0) { RelativePathElement path = new RelativePathElement(); path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasNotifier; path.IsInverse = false; path.IncludeSubtypes = true; // final hop can be HasEventSource for sources. if (!isArea && names.Count == 1) { path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; } browseText = names.Pop(); path.TargetName = m_mapper.GetRemoteBrowseName(browseText); browsePath.RelativePath.Elements.Add(path); } BrowsePathCollection browsePaths = new BrowsePathCollection(); 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); // check if the start node actually exists. if (StatusCode.IsBad(results[0].StatusCode)) { return(null); } // must be exact one target. if (results[0].Targets.Count != 1) { return(null); } // can't be an external reference. BrowsePathTarget target = results[0].Targets[0]; if (target.RemainingPathIndex != UInt32.MaxValue) { return(null); } // need to check if at the end of the tree. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)target.TargetId; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.IncludeSubtypes = true; ReferenceDescriptionCollection children = ComAeUtils.Browse(session, nodeToBrowse, false); if (!isArea) { if (children != null && children.Count > 0) { return(null); } } else { if (children == null || children.Count == 0) { return(null); } } // construct the element. AeBrowseElement element = new AeBrowseElement(); element.NodeId = (NodeId)target.TargetId; element.ItemId = itemId; element.BrowseText = browseText; element.IsArea = isArea; return(element); }
/// <summary> /// Reads an verifies all of the nodes. /// </summary> private bool DoMultiHopTest(int hops) { // follow tree from each starting node. bool success = true; Log("Starting TranslatePath with {2} hops for {0} Nodes ({1}% Coverage)", AvailableNodes.Values.Count, Configuration.Coverage, hops + 1); // collect the available paths. BrowsePathCollection availablePaths = new BrowsePathCollection(); int counter = 0; foreach (Node node in AvailableNodes.Values) { if (!CheckCoverage(ref counter)) { continue; } if (hops <= 0) { AddSingleHopPaths(node, availablePaths); } else { AddMultiHopPaths(node, node, null, availablePaths, hops); } } // process paths in blocks. int paths = 0; double increment = MaxProgress / availablePaths.Count; double position = 0; BrowsePathCollection pathsToTranslate = new BrowsePathCollection(); for (int ii = 0; ii < availablePaths.Count; ii++) { paths++; pathsToTranslate.Add(availablePaths[ii]); // process batch. if (pathsToTranslate.Count > 500) { if (!Translate(pathsToTranslate)) { success = false; break; } if (paths > availablePaths.Count / 5) { Log("Translated {0} browse paths.", paths); paths = 0; } pathsToTranslate.Clear(); } position += increment; ReportProgress(position); } // process final batch. if (success) { if (pathsToTranslate.Count > 0) { if (!Translate(pathsToTranslate)) { success = false; } else { Log("Translated {0} browse paths.", paths); } } } return(success); }
/// <summary> /// Adds a single hop path for all references for the node. /// </summary> private void AddMultiHopPaths( Node node, Node baseNode, IList <RelativePathElement> basePath, BrowsePathCollection pathsToTranslate, int hops) { ReferenceDescriptionCollection references = node.Handle as ReferenceDescriptionCollection; if (references == null) { return; } for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = baseNode.NodeId; browsePath.Handle = baseNode; if (basePath != null) { browsePath.RelativePath.Elements.AddRange(basePath); } RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.NonHierarchicalReferences; element.IsInverse = !reference.IsForward; element.IncludeSubtypes = true; element.TargetName = reference.BrowseName; browsePath.RelativePath.Elements.Add(element); pathsToTranslate.Add(browsePath); // only follow forward heiarchical if (!Session.TypeTree.IsTypeOf(reference.ReferenceTypeId, ReferenceTypeIds.HierarchicalReferences)) { continue; } element.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; // can't do anything with absolute or inverse references. if (!reference.IsForward || reference.NodeId.IsAbsolute) { continue; } // look up target if (browsePath.RelativePath.Elements.Count < hops) { Node target = null; if (!AvailableNodes.TryGetValue((NodeId)reference.NodeId, out target)) { continue; } AddMultiHopPaths(target, baseNode, browsePath.RelativePath.Elements, pathsToTranslate, hops); } } }
/// <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; } }
/// <summary> /// Gets the available attributes for an HDA item. /// </summary> /// <param name="session">The session.</param> /// <param name="nodeId">The node id.</param> /// <returns></returns> private ReadValueIdCollection GetAvailableAttributes(Session session, NodeId nodeId) { ReadValueIdCollection supportedAttributes = new ReadValueIdCollection(); // add mandatory HDA attributes. supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ITEMID, Attributes.DisplayName)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DATA_TYPE, Attributes.DataType)); supportedAttributes.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_VALUE_RANK, Attributes.ValueRank)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DESCRIPTION, Attributes.Description)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ARCHIVING, Attributes.Historizing)); // check if nodes are defined for all optional HDA attributes. BrowsePathCollection pathsToRead = new BrowsePathCollection(); pathsToRead.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_ANNOTATION, Opc.Ua.BrowseNames.Annotations)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ENG_UNITS, Opc.Ua.BrowseNames.EngineeringUnits));; pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DERIVE_EQUATION, Opc.Ua.BrowseNames.Definition)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MAXIMUM, Opc.Ua.BrowseNames.EURange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MINIMUM, Opc.Ua.BrowseNames.EURange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_HIGH_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_LOW_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_STEPPED, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.Stepped)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MAX_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MaxTimeInterval)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MIN_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MinTimeInterval)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviation)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV_TYPE, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviationFormat)); BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.TranslateBrowsePathsToNodeIds( null, pathsToRead, out results, out diagnosticInfos); Session.ValidateResponse(results, pathsToRead); Session.ValidateDiagnosticInfos(diagnosticInfos, pathsToRead); for (int ii = 0; ii < pathsToRead.Count; ii++) { uint attributeId = (uint)pathsToRead[ii].Handle; // path does not exist. if (StatusCode.IsBad(results[ii].StatusCode)) { continue; } // nothing found. if (results[ii].Targets.Count == 0) { continue; } // choose the first valid target. for (int jj = 0; jj < results[ii].Targets.Count; jj++) { BrowsePathTarget target = results[ii].Targets[jj]; if (target.RemainingPathIndex == UInt32.MaxValue && !NodeId.IsNull(target.TargetId) && !target.TargetId.IsAbsolute) { supportedAttributes.Add(Construct((NodeId)target.TargetId, attributeId, Attributes.Value)); break; } } } return(supportedAttributes); }
/// <summary> /// Reads an verifies all of the nodes. /// </summary> private bool DoMultiHopTest(int hops) { // follow tree from each starting node. bool success = true; Log("Starting TranslatePath with {2} hops for {0} Nodes ({1}% Coverage)", AvailableNodes.Values.Count, Configuration.Coverage, hops+1); // collect the available paths. BrowsePathCollection availablePaths = new BrowsePathCollection(); int counter = 0; foreach (Node node in AvailableNodes.Values) { if (!CheckCoverage(ref counter)) { continue; } if (hops <= 0) { AddSingleHopPaths(node, availablePaths); } else { AddMultiHopPaths(node, node, null, availablePaths, hops); } } // process paths in blocks. int paths = 0; double increment = MaxProgress/availablePaths.Count; double position = 0; BrowsePathCollection pathsToTranslate = new BrowsePathCollection(); for (int ii = 0; ii < availablePaths.Count; ii++) { paths++; pathsToTranslate.Add(availablePaths[ii]); // process batch. if (pathsToTranslate.Count > 500) { if (!Translate(pathsToTranslate)) { success = false; break; } if (paths > availablePaths.Count/5) { Log("Translated {0} browse paths.", paths); paths = 0; } pathsToTranslate.Clear(); } position += increment; ReportProgress(position); } // process final batch. if (success) { if (pathsToTranslate.Count > 0) { if (!Translate(pathsToTranslate)) { success = false; } else { Log("Translated {0} browse paths.", paths); } } } return success; }
/// <summary> /// Gets the available attributes for an HDA item. /// </summary> /// <param name="session">The session.</param> /// <param name="nodeId">The node id.</param> /// <returns></returns> private ReadValueIdCollection GetAvailableAttributes(Session session, NodeId nodeId) { ReadValueIdCollection supportedAttributes = new ReadValueIdCollection(); // add mandatory HDA attributes. supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ITEMID, Attributes.DisplayName)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DATA_TYPE, Attributes.DataType)); supportedAttributes.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_VALUE_RANK, Attributes.ValueRank)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DESCRIPTION, Attributes.Description)); supportedAttributes.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ARCHIVING, Attributes.Historizing)); // check if nodes are defined for all optional HDA attributes. BrowsePathCollection pathsToRead = new BrowsePathCollection(); pathsToRead.Add(Construct(nodeId, ComHdaProxy.INTERNAL_ATTRIBUTE_ANNOTATION, Opc.Ua.BrowseNames.Annotations)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_ENG_UNITS, Opc.Ua.BrowseNames.EngineeringUnits)); ; pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_DERIVE_EQUATION, Opc.Ua.BrowseNames.Definition)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MAXIMUM, Opc.Ua.BrowseNames.EURange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_NORMAL_MINIMUM, Opc.Ua.BrowseNames.EURange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_HIGH_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_LOW_ENTRY_LIMIT, Opc.Ua.BrowseNames.InstrumentRange)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_STEPPED, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.Stepped)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MAX_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MaxTimeInterval)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_MIN_TIME_INT, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.MinTimeInterval)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviation)); pathsToRead.Add(Construct(nodeId, OpcRcw.Hda.Constants.OPCHDA_EXCEPTION_DEV_TYPE, Opc.Ua.BrowseNames.HAConfiguration, Opc.Ua.BrowseNames.ExceptionDeviationFormat)); BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.TranslateBrowsePathsToNodeIds( null, pathsToRead, out results, out diagnosticInfos); Session.ValidateResponse(results, pathsToRead); Session.ValidateDiagnosticInfos(diagnosticInfos, pathsToRead); for (int ii = 0; ii < pathsToRead.Count; ii++) { uint attributeId = (uint)pathsToRead[ii].Handle; // path does not exist. if (StatusCode.IsBad(results[ii].StatusCode)) { continue; } // nothing found. if (results[ii].Targets.Count == 0) { continue; } // choose the first valid target. for (int jj = 0; jj < results[ii].Targets.Count; jj++) { BrowsePathTarget target = results[ii].Targets[jj]; if (target.RemainingPathIndex == UInt32.MaxValue && !NodeId.IsNull(target.TargetId) && !target.TargetId.IsAbsolute) { supportedAttributes.Add(Construct((NodeId)target.TargetId, attributeId, Attributes.Value)); break; } } } return supportedAttributes; }
public static void BrowseNode(String currentNode, String browseName) { BrowseResultCollection browseResultCollection = null; DiagnosticInfoCollection diagnosticInfos; BrowseDescriptionCollection browseDescriptionCollection = null; List <NodeClass> nodeClasses = new List <NodeClass>() { NodeClass.Unspecified }; foreach (NodeClass nodeClass in nodeClasses) { browseDescriptionCollection = PrepareBrowseDescriptionCollection(currentNode, (uint)nodeClass); clientSession.Browse( null, null, 100, browseDescriptionCollection, out browseResultCollection, out diagnosticInfos); if (browseResultCollection.Where(br => br.References.Count > 0).FirstOrDefault() == null) { continue; } int browseResultCounter = browseResultCollection.FindIndex(br => br.References.Count > 0); String referenceType = String.Empty; foreach (BrowseResult browseResult in browseResultCollection) { switch (browseResultCounter) { case 0: referenceType = "Organizes"; break; case 1: referenceType = "HasComponent"; break; case 2: referenceType = "HasChild"; break; case 3: referenceType = "HasDescription"; break; case 4: referenceType = "HasProperty"; break; default: referenceType = "HasProperty"; break; } if (browseResult.References.Count > 0) { foreach (ReferenceDescription referenceDescription in browseResult.References) { if (referenceDescription.BrowseName.NamespaceIndex != UaDefaultNamespaceIndex) { BrowseNode(referenceDescription.NodeId.ToString(), referenceDescription.BrowseName.ToString()); } //TBD - If a node id has different relations with its parent node, the additional "relation" should be added //OpcuaNodeList opcuaNodeSubStructure = new OpcuaNodeList(); //opcuaNodeSubStructure.nodeId = referenceDescription.NodeId.ToString(); //opcuaNodeSubStructure.browseName = referenceDescription.BrowseName.ToString(); OpcuaNodeLink opcuaNodeLink = new OpcuaNodeLink(); opcuaNodeLink.nodeID = referenceDescription.NodeId.ToString(); opcuaNodeLink.browseName = referenceDescription.BrowseName.ToString(); opcuaNodeLink.parentNodeId = currentNode; opcuaNodeLink.parentNodebrowseName = browseName; opcuaNodeLink.referenceType = referenceType; if (referenceDescription.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } opcuaNodeLink.NodeClassMask = nodeClass.ToString("G"); opcuaNodeLink.browseResultMask = BrowseResultMask.All.ToString("G"); //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(opcuaNodeLink); if (referenceDescription.NodeClass == NodeClass.Method) { Node methodNode = clientSession.ReadNode((NodeId)(referenceDescription.NodeId.ToString())); browseDescriptionCollection = PrepareBrowseDescriptionCollection(referenceDescription.NodeId.ToString(), (uint)nodeClass); clientSession.Browse( null, null, 100, browseDescriptionCollection, out browseResultCollection, out diagnosticInfos); if (browseResultCollection.Where(br => br.References.Count > 0).FirstOrDefault() == null) { continue; } String inputArgumentsNodeId = String.Empty, outputArgumentsNodeId = String.Empty; foreach (BrowseResult br in browseResultCollection) { foreach (ReferenceDescription rd in br.References) { OpcuaNodeLink nodeLink = new OpcuaNodeLink(); nodeLink.nodeID = rd.NodeId.ToString(); nodeLink.browseName = rd.BrowseName.ToString(); if (nodeLink.browseName == "InputArguments") { inputArgumentsNodeId = nodeLink.nodeID; } else if (nodeLink.browseName == "OutputArguments") { outputArgumentsNodeId = nodeLink.nodeID; } nodeLink.parentNodeId = referenceDescription.NodeId.ToString(); nodeLink.parentNodebrowseName = referenceDescription.BrowseName.ToString(); nodeLink.referenceType = referenceType; if (rd.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } nodeLink.NodeClassMask = nodeClass.ToString("G"); nodeLink.browseResultMask = BrowseResultMask.All.ToString("G"); //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(nodeLink); } } opcuaNodeLink.isMethod = true; BrowsePathCollection pathsToArgs = new BrowsePathCollection(); BrowsePath pathToInputArgs = new BrowsePath(); pathToInputArgs.StartingNode = methodNode.NodeId; pathToInputArgs.RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, false, true, new QualifiedName("InputArguments")); pathsToArgs.Add(pathToInputArgs); BrowsePath pathToOutputArgs = new BrowsePath(); pathToOutputArgs.StartingNode = methodNode.NodeId; pathToOutputArgs.RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, false, true, new QualifiedName("OutputArguments")); pathsToArgs.Add(pathToOutputArgs); BrowsePathResultCollection results = null; // Get the nodeId of the input argument ResponseHeader responseHeader = clientSession.TranslateBrowsePathsToNodeIds( null, pathsToArgs, out results, out diagnosticInfos ); ArgumentCollection[] arguments = new ArgumentCollection[2]; for (int i = 0; i < 2; i++) { arguments[i] = new ArgumentCollection(); foreach (BrowsePathTarget bptarget in results[i].Targets) { DataValueCollection readResults = null; ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)bptarget.TargetId; nodeToRead.AttributeId = Attributes.Value; ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); nodesToRead.Add(nodeToRead); DiagnosticInfoCollection readDiagnoistcInfos = null; clientSession.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out readResults, out readDiagnoistcInfos ); ExtensionObject[] exts = (ExtensionObject[])readResults[0].Value; for (int j = 0; j < exts.Length; ++j) { ExtensionObject ext = exts[j]; arguments[i].Add((Argument)ext.Body); OpcuaNodeLink nl = new OpcuaNodeLink(); nl.nodeID = ((Opc.Ua.Argument)ext.Body).BinaryEncodingId.ToString(); nl.browseName = ((Opc.Ua.Argument)ext.Body).Name; if (((Opc.Ua.Argument)ext.Body).Description.Text.Equals("Input argument")) { nl.parentNodeId = inputArgumentsNodeId; } else if (((Opc.Ua.Argument)ext.Body).Description.Text.Equals("Output argument")) { nl.parentNodeId = outputArgumentsNodeId; } nl.parentNodebrowseName = referenceDescription.BrowseName.ToString(); nl.referenceType = referenceType; if (referenceDescription.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } nl.NodeClassMask = NodeClass.Variable.ToString("G"); nl.browseResultMask = BrowseResultMask.All.ToString("G"); nl.isArgument = true; //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(nl); } } } } } } } } }
/// <summary> /// Finds an element identified by the path from the root. /// </summary> private AeBrowseElement Find(Session session, string itemId, AeBrowseElement root, Stack<string> names, bool isArea) { string browseText = null; BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = root.NodeId; while (names.Count > 0) { RelativePathElement path = new RelativePathElement(); path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasNotifier; path.IsInverse = false; path.IncludeSubtypes = true; // final hop can be HasEventSource for sources. if (!isArea && names.Count == 1) { path.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; } browseText = names.Pop(); path.TargetName = m_mapper.GetRemoteBrowseName(browseText); browsePath.RelativePath.Elements.Add(path); } BrowsePathCollection browsePaths = new BrowsePathCollection(); 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); // check if the start node actually exists. if (StatusCode.IsBad(results[0].StatusCode)) { return null; } // must be exact one target. if (results[0].Targets.Count != 1) { return null; } // can't be an external reference. BrowsePathTarget target = results[0].Targets[0]; if (target.RemainingPathIndex != UInt32.MaxValue) { return null; } // need to check if at the end of the tree. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)target.TargetId; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.IncludeSubtypes = true; ReferenceDescriptionCollection children = ComAeUtils.Browse(session, nodeToBrowse, false); if (!isArea) { if (children != null && children.Count > 0) { return null; } } else { if (children == null || children.Count == 0) { return null; } } // construct the element. AeBrowseElement element = new AeBrowseElement(); element.NodeId = (NodeId)target.TargetId; element.ItemId = itemId; element.BrowseText = browseText; element.IsArea = isArea; return element; }
/// <summary> /// Calls the TraslateBrowsePathsToNodeIds service to get the nodeIds for each of the Relative Paths in the list /// </summary> /// <param name="RelativePaths">The List of Relative Paths</param> public BrowsePathResultCollection GetBrowseTargets(List<String> RelativePaths) { BrowsePathCollection browsePaths = new BrowsePathCollection(); NamespaceTable clientUris = null; try { clientUris = new NamespaceTable(m_configFile.SavedNamespaceTable); } catch (Exception) { return null; } foreach (string relativePath in RelativePaths) { BrowsePath browsePath = new BrowsePath(); browsePath.RelativePath = RelativePath.Parse(relativePath, m_session.TypeTree, clientUris, m_session.NamespaceUris); browsePath.StartingNode = Objects.Server; browsePaths.Add(browsePath); } BrowsePathResultCollection results; DiagnosticInfoCollection diagnosticInfos; ResponseHeader responseHeader = m_session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); // ensure that the server returned valid results. Session.ValidateResponse(results, browsePaths); Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); return results; }
/// <summary> /// Updates the EUInfo for the items. /// </summary> /// <param name="group">The group.</param> /// <param name="items">The items. Null entries are ignored.</param> public void UpdateItemEuInfo( ComDaGroup group, IList<ComDaGroupItem> items) { // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // build list of properties that need to be read. BrowsePathCollection browsePaths = new BrowsePathCollection(); for (int ii = 0; ii < items.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)items[ii]; // ignore invalid items or items which have already checked their EU type. if (item == null || item.EuType >= 0) { continue; } BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EURange; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EnumStrings; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); } // check if nothing to do. if (browsePaths.Count == 0) { return; } // translate browse paths. BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; try { session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); } catch (Exception) { for (int ii = 0; ii < browsePaths.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; item.EuType = 0; } return; } // build list of properties that need to be read. ReadValueIdCollection propertiesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < results.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; BrowsePathResult result = results[ii]; if (StatusCode.IsBad(result.StatusCode)) { if (item.EuType < 0 && result.StatusCode == StatusCodes.BadNoMatch) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } if (result.Targets.Count == 0 || result.Targets[0].TargetId.IsAbsolute) { if (item.EuType < 0) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } ReadValueId propertyToRead = new ReadValueId(); propertyToRead.NodeId = (NodeId)result.Targets[0].TargetId; propertyToRead.AttributeId = Attributes.Value; propertyToRead.Handle = item; propertiesToRead.Add(propertyToRead); if (browsePaths[ii].RelativePath.Elements[0].TargetName.Name == Opc.Ua.BrowseNames.EURange) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; } else { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; } } // check if nothing to do. if (propertiesToRead.Count == 0) { return; } // read attribute values from the server. DataValueCollection values = null; try { session.Read( null, 0, TimestampsToReturn.Neither, propertiesToRead, out values, out diagnosticInfos); ClientBase.ValidateResponse(values, propertiesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, propertiesToRead); } catch (Exception) { for (int ii = 0; ii < propertiesToRead.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; item.EuType = 0; } return; } // process results. for (int ii = 0; ii < values.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; if (StatusCode.IsBad(values[ii].StatusCode)) { item.EuType = 0; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) { Range range = (Range)values[ii].GetValue<Range>(null); if (range == null) { item.EuType = 0; continue; } item.EuInfo = new double[] { range.Low, range.High }; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED) { LocalizedText[] texts = (LocalizedText[])values[ii].GetValue<LocalizedText[]>(null); if (texts == null) { item.EuType = 0; continue; } string[] strings = new string[texts.Length]; for (int jj = 0; jj < strings.Length; jj++) { if (!LocalizedText.IsNullOrEmpty(texts[jj])) { strings[jj] = texts[jj].Text; } } item.EuInfo = strings; continue; } } }
/// <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; } }
/// <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> /// Adds a single hop path for all references for the node. /// </summary> private void AddMultiHopPaths( Node node, Node baseNode, IList<RelativePathElement> basePath, BrowsePathCollection pathsToTranslate, int hops) { ReferenceDescriptionCollection references = node.Handle as ReferenceDescriptionCollection; if (references == null) { return; } for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = baseNode.NodeId; browsePath.Handle = baseNode; if (basePath != null) { browsePath.RelativePath.Elements.AddRange(basePath); } RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.NonHierarchicalReferences; element.IsInverse = !reference.IsForward; element.IncludeSubtypes = true; element.TargetName = reference.BrowseName; browsePath.RelativePath.Elements.Add(element); pathsToTranslate.Add(browsePath); // only follow forward heiarchical if (!Session.TypeTree.IsTypeOf(reference.ReferenceTypeId, ReferenceTypeIds.HierarchicalReferences)) { continue; } element.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; // can't do anything with absolute or inverse references. if (!reference.IsForward || reference.NodeId.IsAbsolute) { continue; } // look up target if (browsePath.RelativePath.Elements.Count < hops) { Node target = null; if (!AvailableNodes.TryGetValue((NodeId)reference.NodeId, out target)) { continue; } AddMultiHopPaths(target, baseNode, browsePath.RelativePath.Elements, pathsToTranslate, hops); } } }
/// <summary> /// Finds the NodeIds for the components for an instance. /// </summary> public void FindComponentIds( NodeId instanceId, IList<string> componentPaths, out NodeIdCollection componentIds, out List<ServiceResult> errors) { componentIds = new NodeIdCollection(); errors = new List<ServiceResult>(); // build list of paths to translate. BrowsePathCollection pathsToTranslate = new BrowsePathCollection(); for (int ii = 0; ii < componentPaths.Count; ii++) { BrowsePath pathToTranslate = new BrowsePath(); pathToTranslate.StartingNode = instanceId; pathToTranslate.RelativePath = RelativePath.Parse(componentPaths[ii], TypeTree); pathsToTranslate.Add(pathToTranslate); } // translate the paths. BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = TranslateBrowsePathsToNodeIds( null, pathsToTranslate, out results, out diagnosticInfos); // verify that the server returned the correct number of results. ClientBase.ValidateResponse(results, pathsToTranslate); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, pathsToTranslate); for (int ii = 0; ii < componentPaths.Count; ii++) { componentIds.Add(NodeId.Null); errors.Add(ServiceResult.Good); // process any diagnostics associated with any error. if (StatusCode.IsBad(results[ii].StatusCode)) { errors[ii] = new ServiceResult(results[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable); continue; } // Expecting exact one NodeId for a local node. // Report an error if the server returns anything other than that. if (results[ii].Targets.Count == 0) { errors[ii] = ServiceResult.Create( StatusCodes.BadTargetNodeIdInvalid, "Could not find target for path: {0}.", componentPaths[ii]); continue; } if (results[ii].Targets.Count != 1) { errors[ii] = ServiceResult.Create( StatusCodes.BadTooManyMatches, "Too many matches found for path: {0}.", componentPaths[ii]); continue; } if (results[ii].Targets[0].RemainingPathIndex != UInt32.MaxValue) { errors[ii] = ServiceResult.Create( StatusCodes.BadTargetNodeIdInvalid, "Cannot follow path to external server: {0}.", componentPaths[ii]); continue; } if (NodeId.IsNull(results[ii].Targets[0].TargetId)) { errors[ii] = ServiceResult.Create( StatusCodes.BadUnexpectedError, "Server returned a null NodeId for path: {0}.", componentPaths[ii]); continue; } if (results[ii].Targets[0].TargetId.IsAbsolute) { errors[ii] = ServiceResult.Create( StatusCodes.BadUnexpectedError, "Server returned a remote node for path: {0}.", componentPaths[ii]); continue; } // suitable target found. componentIds[ii] = ExpandedNodeId.ToNodeId(results[ii].Targets[0].TargetId, m_namespaceUris); } }
/// <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="namespacesUris">The namespace URIs referenced by the relative paths.</param> /// <param name="relativePaths">The relative paths.</param> /// <returns>A collection of local nodes.</returns> public static List <NodeId> TranslateBrowsePaths( Session session, NodeId startNodeId, NamespaceTable namespacesUris, 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, namespacesUris, 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); // collect the list of node ids found. List <NodeId> nodes = new List <NodeId>(); for (int ii = 0; ii < results.Count; ii++) { // check if the start node actually exists. if (StatusCode.IsBad(results[ii].StatusCode)) { nodes.Add(null); continue; } // an empty list is returned if no node was found. if (results[ii].Targets.Count == 0) { nodes.Add(null); 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) { nodes.Add(null); 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. nodes.Add(ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris)); } // return whatever was found. return(nodes); }
/// <summary> /// Adds a single hop path for all references for the node. /// </summary> private void AddSingleHopPaths(Node node, BrowsePathCollection pathsToTranslate) { ReferenceDescriptionCollection references = node.Handle as ReferenceDescriptionCollection; if (references == null) { return; } for (int ii = 0; ii < references.Count; ii++) { BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = node.NodeId; browsePath.Handle = node; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = references[ii].ReferenceTypeId; element.IsInverse = !references[ii].IsForward; element.IncludeSubtypes = false; element.TargetName = references[ii].BrowseName; browsePath.RelativePath.Elements.Add(element); pathsToTranslate.Add(browsePath); } }
/// <summary> /// Updates the EUInfo for the items. /// </summary> /// <param name="group">The group.</param> /// <param name="items">The items. Null entries are ignored.</param> public void UpdateItemEuInfo( ComDaGroup group, IList <ComDaGroupItem> items) { // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // build list of properties that need to be read. BrowsePathCollection browsePaths = new BrowsePathCollection(); for (int ii = 0; ii < items.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)items[ii]; // ignore invalid items or items which have already checked their EU type. if (item == null || item.EuType >= 0) { continue; } BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EURange; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); browsePath = new BrowsePath(); browsePath.StartingNode = item.NodeId; element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasProperty; element.IsInverse = false; element.IncludeSubtypes = false; element.TargetName = Opc.Ua.BrowseNames.EnumStrings; browsePath.RelativePath.Elements.Add(element); browsePath.Handle = item; browsePaths.Add(browsePath); } // check if nothing to do. if (browsePaths.Count == 0) { return; } // translate browse paths. BrowsePathResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; try { session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, browsePaths); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); } catch (Exception) { for (int ii = 0; ii < browsePaths.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; item.EuType = 0; } return; } // build list of properties that need to be read. ReadValueIdCollection propertiesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < results.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)browsePaths[ii].Handle; BrowsePathResult result = results[ii]; if (StatusCode.IsBad(result.StatusCode)) { if (item.EuType < 0 && result.StatusCode == StatusCodes.BadNoMatch) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } if (result.Targets.Count == 0 || result.Targets[0].TargetId.IsAbsolute) { if (item.EuType < 0) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_NOENUM; } continue; } ReadValueId propertyToRead = new ReadValueId(); propertyToRead.NodeId = (NodeId)result.Targets[0].TargetId; propertyToRead.AttributeId = Attributes.Value; propertyToRead.Handle = item; propertiesToRead.Add(propertyToRead); if (browsePaths[ii].RelativePath.Elements[0].TargetName.Name == Opc.Ua.BrowseNames.EURange) { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG; } else { item.EuType = (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED; } } // check if nothing to do. if (propertiesToRead.Count == 0) { return; } // read attribute values from the server. DataValueCollection values = null; try { session.Read( null, 0, TimestampsToReturn.Neither, propertiesToRead, out values, out diagnosticInfos); ClientBase.ValidateResponse(values, propertiesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, propertiesToRead); } catch (Exception) { for (int ii = 0; ii < propertiesToRead.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; item.EuType = 0; } return; } // process results. for (int ii = 0; ii < values.Count; ii++) { ComDaGroupItem item = (ComDaGroupItem)propertiesToRead[ii].Handle; if (StatusCode.IsBad(values[ii].StatusCode)) { item.EuType = 0; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ANALOG) { Range range = (Range)values[ii].GetValue <Range>(null); if (range == null) { item.EuType = 0; continue; } item.EuInfo = new double[] { range.Low, range.High }; continue; } if (item.EuType == (int)OpcRcw.Da.OPCEUTYPE.OPC_ENUMERATED) { LocalizedText[] texts = (LocalizedText[])values[ii].GetValue <LocalizedText[]>(null); if (texts == null) { item.EuType = 0; continue; } string[] strings = new string[texts.Length]; for (int jj = 0; jj < strings.Length; jj++) { if (!LocalizedText.IsNullOrEmpty(texts[jj])) { strings[jj] = texts[jj].Text; } } item.EuInfo = strings; continue; } } }
/// <summary> /// Returns a list of remote browse paths for a list of local relative paths. /// </summary> public BrowsePathCollection GetRemoteBrowsePaths(NodeId localNodeId, params string[] relativePaths) { BrowsePathCollection browsePaths = new BrowsePathCollection(); if (relativePaths != null) { for (int ii = 0; ii < relativePaths.Length; ii++) { BrowsePath browsePath = new BrowsePath(); browsePath.RelativePath = RelativePath.Parse(relativePaths[ii], this.m_typeTable); browsePath.StartingNode = GetRemoteNodeId(localNodeId); for (int jj = 0; jj < browsePath.RelativePath.Elements.Count; jj++) { QualifiedName targetName = browsePath.RelativePath.Elements[jj].TargetName; targetName = GetRemoteQualifiedName(targetName); browsePath.RelativePath.Elements[jj].TargetName = targetName; NodeId referenceTypeId = browsePath.RelativePath.Elements[jj].ReferenceTypeId; referenceTypeId = GetRemoteNodeId(referenceTypeId); browsePath.RelativePath.Elements[jj].ReferenceTypeId = referenceTypeId; } browsePaths.Add(browsePath); } } return browsePaths; }