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); } }
public static Entry For(BrowsePath path) { ObjectEntry entry = new ObjectEntry(); entry.Add("StartingNode", For(path.StartingNode)); entry.Add("RelativePath", For(path.RelativePath)); return(entry); }
private void button4_Click(object sender, EventArgs e) { if (BrowsePath.ShowDialog() != DialogResult.OK) { return; } Settings.Default.ExistingEventPath = BrowsePath.SelectedPath; }
private void SelectBasePath_Click(object sender, EventArgs e) { if (BrowsePath.ShowDialog() != DialogResult.OK) { return; } Settings.Default.TempEventBasePath = BrowsePath.SelectedPath.ToString(); }
private void SelectBackupBasePathButton_Click(object sender, EventArgs e) { if (BrowsePath.ShowDialog() != DialogResult.OK) { return; } Settings.Default.TempBackupBasePath = BrowsePath.SelectedPath; }
private void SelectNewEventPath_Click(object sender, EventArgs e) { if (BrowsePath.ShowDialog() != DialogResult.OK) { return; } Settings.Default.Eventpath = BrowsePath.SelectedPath; Settings.Default.FullEventPath = Path.Combine(Settings.Default.Eventpath, Settings.Default.DateSetTemplate.Replace("{Eventname}", EventNameBox.Text)); if (Settings.Default.SetBackupPath) { Settings.Default.BackupPath = Path.Combine(Settings.Default.BackupBasePath, Settings.Default.DateSetTemplate.Replace("{Eventname}", EventNameBox.Text)); return; } Settings.Default.BackupPath = Settings.Default.FullEventPath; }
/// <summary> /// Reads the attributes, verifies the results and updates the nodes. /// </summary> private bool Translate(BrowsePathCollection pathsToTranslate) { bool success = true; BrowsePathResultCollection results; DiagnosticInfoCollection diagnosticInfos; RequestHeader requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.TranslateBrowsePathsToNodeIds( requestHeader, pathsToTranslate, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, pathsToTranslate); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, pathsToTranslate); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array during Read."); return(false); } // check results. for (int ii = 0; ii < pathsToTranslate.Count; ii++) { BrowsePath request = pathsToTranslate[ii]; Node node = (Node)request.Handle; if (!VerifyPaths(node, request, results[ii])) { success = false; continue; } } return(success); }
public virtual StatusCode HandleTranslateBrowsePathRequest( object session, BrowsePath path, List <BrowsePathTarget> res) { if (!this.AddressSpaceTable.TryGetValue(path.StartingNode, out Node node1) || !this.SessionHasPermissionToRead(session, path.StartingNode)) { return(StatusCode.BadNodeIdUnknown); } for (int index1 = 0; index1 < path.RelativePath.Length; ++index1) { RelativePathElement relativePathElement = path.RelativePath[index1]; ReferenceNode referenceNode = null; for (int index2 = 0; index2 < node1.References.Count; ++index2) { ReferenceNode reference = node1.References[index2]; if (relativePathElement.IsInverse == reference.IsInverse && (relativePathElement.IncludeSubtypes || reference.ReferenceType.Equals(relativePathElement.ReferenceTypeId)) && ((!relativePathElement.IncludeSubtypes || this.IsSubtypeOrEqual(reference.ReferenceType, relativePathElement.ReferenceTypeId)) && (this.AddressSpaceTable.TryGetValue(reference.Target, out Node node2) && this.SessionHasPermissionToRead(session, reference.Target) && node2.BrowseName.Equals(relativePathElement.TargetName)))) { referenceNode = node1.References[index2]; node1 = node2; break; } } if (referenceNode == null || node1 == null) { res.Add(new BrowsePathTarget() { Target = node1.Id, RemainingPathIndex = (uint)index1 }); return(StatusCode.BadNoMatch); } } res.Add(new BrowsePathTarget() { Target = node1.Id, RemainingPathIndex = (uint)path.RelativePath.Length }); return(StatusCode.Good); }
/// <summary> /// Constructs the browse path. /// </summary> /// <param name="nodeId">The node id.</param> /// <param name="hdaAttributeId">The hda attribute id.</param> /// <param name="browsePaths">The browse paths.</param> /// <returns></returns> private BrowsePath Construct(NodeId nodeId, uint hdaAttributeId, params string[] browsePaths) { BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = nodeId; browsePath.Handle = hdaAttributeId; for (int ii = 0; ii < browsePaths.Length; ii++) { RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasChild; element.IsInverse = false; element.IncludeSubtypes = true; element.TargetName = browsePaths[ii]; browsePath.RelativePath.Elements.Add(element); } return(browsePath); }
private BrowsePath ResolveRelativePath(OpcUAQuery query, NamespaceTable namespaceTable) { var path = new BrowsePath(); var nodeId = Converter.GetNodeId(query.nodePath.node.nodeId, namespaceTable); path.StartingNode = nodeId; if (query.useTemplate && query.relativePath != null && query.relativePath.Length > 0) { var r = new RelativePath(); path.RelativePath = r; for (int i = 0; i < query.relativePath.Length; i++) { r.Elements.Add(new RelativePathElement() { TargetName = Converter.GetQualifiedName(query.relativePath[i], namespaceTable), IncludeSubtypes = true, ReferenceTypeId = Opc.Ua.ReferenceTypes.References, IsInverse = false }); } } return(path); }
/// <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); } }
internal static string GetFieldName(OpcUAQuery query, BrowsePath relativePath) { string fieldName = query.alias; if (string.IsNullOrEmpty(fieldName)) { fieldName = String.Join(" / ", query.nodePath.browsePath.Select(a => a.name).ToArray()); if (relativePath?.RelativePath?.Elements?.Count > 0) { StringBuilder sb = new StringBuilder(); sb.Append(fieldName); var pelemt = relativePath.RelativePath.Elements; for (int i = 0; i < pelemt.Count; i++) { sb.Append(" / "); sb.Append(pelemt[i].TargetName.Name); } fieldName = sb.ToString(); } } return(fieldName); }
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> /// 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; }
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> /// 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> /// Verifies that the timestamps match the requested filter. /// </summary> private bool VerifyPaths( Node node, BrowsePath request, BrowsePathResult result) { // check empty path. if (request.RelativePath.Elements == null || request.RelativePath.Elements.Count == 0) { if (result.StatusCode != StatusCodes.BadBrowseNameInvalid) { Log( "Unexpected error returned during translate for Node '{0}'. NodeId = {1}, Expected = {2}, Actual = {3}", node, node.NodeId, (StatusCode)StatusCodes.BadBrowseNameInvalid, result.StatusCode); return false; } } BrowsePathResult expectedResult = new BrowsePathResult(); GetTargets(node, request.RelativePath.Elements, 0, expectedResult); if (result.StatusCode == StatusCodes.BadNoMatch) { if (expectedResult.Targets.Count > 0) { Log( "Translate returned BadNoMatch when targets expected '{0}'. NodeId = {1}, Path = {2}, ExpectedCount = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedResult.Targets.Count); return false; } if (result.Targets.Count > 0) { Log( "Translate returned targets with a BadNoMatch code '{0}'. NodeId = {1}, Path = {2}, ActualCount = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), result.Targets.Count); return false; } return true; } if (expectedResult.Targets.Count == 0) { Log( "Translate returned invalided error code when no targets exist '{0}'. NodeId = {1}, Path = {2}, StatusCode = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), (StatusCode)result.StatusCode); return false; } // check status code. if (result.StatusCode != StatusCodes.Good) { Log( "Translate returned an error for Node '{0}'. NodeId = {1}, Path = {2}, StatusCode = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), (StatusCode)result.StatusCode); return false; } // check for expected targets. for (int ii = 0; ii < expectedResult.Targets.Count; ii++) { BrowsePathTarget expectedTarget = expectedResult.Targets[ii]; bool found = false; for (int jj = 0; jj < result.Targets.Count; jj++) { BrowsePathTarget actualTarget = result.Targets[jj]; if (actualTarget.TargetId != expectedTarget.TargetId) { continue; } found = true; if (actualTarget.RemainingPathIndex != expectedTarget.RemainingPathIndex) { Log( "Translate did not return correct remaining path index for target Node '{0}'. NodeId = {1}, Path = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedTarget.RemainingPathIndex, actualTarget.RemainingPathIndex); return false; } break; } if (!found) { Log( "Translate did not return expected target Node '{0}'. NodeId = {1}, Path = {2}, TargetId = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedTarget.TargetId); return false; } } // check for unexpected targets. for (int ii = 0; ii < result.Targets.Count; ii++) { BrowsePathTarget actualTarget = result.Targets[ii]; bool found = false; for (int jj = 0; jj < expectedResult.Targets.Count; jj++) { BrowsePathTarget expectedTarget = expectedResult.Targets[jj]; if (actualTarget.TargetId == expectedTarget.TargetId) { found = true; break; } } if (!found) { Log( "Translate returned unexpected target Node '{0}'. NodeId = {1}, Path = {2}, TargetId = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), actualTarget.TargetId); return false; } } // all ok. return true; }
/// <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> /// 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> /// Translates a browse path. /// </summary> protected ServiceResult TranslateBrowsePath( OperationContext context, BrowsePath browsePath, BrowsePathResult result) { Debug.Assert(browsePath != null); Debug.Assert(result != null); // check for valid start node. INodeManager nodeManager = null; object sourceHandle = GetManagerHandle(browsePath.StartingNode, out nodeManager); if (sourceHandle == null) { return StatusCodes.BadNodeIdUnknown; } // check the relative path. RelativePath relativePath = browsePath.RelativePath; if (relativePath.Elements == null || relativePath.Elements.Count == 0) { return StatusCodes.BadNothingToDo; } for (int ii = 0; ii < relativePath.Elements.Count; ii++) { RelativePathElement element = relativePath.Elements[ii]; if (element == null || QualifiedName.IsNull(relativePath.Elements[ii].TargetName)) { return StatusCodes.BadBrowseNameInvalid; } if (NodeId.IsNull(element.ReferenceTypeId)) { element.ReferenceTypeId = ReferenceTypeIds.References; } } // translate path. TranslateBrowsePath( context, nodeManager, sourceHandle, relativePath, result.Targets, 0); return ServiceResult.Good; }
/// <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; }
internal static Result <DataResponse> GetDataResponseForDataValue(ILogger log, DataValue dataValue, NodeId nodeId, OpcUAQuery query, BrowsePath relativePath) { try { if (Opc.Ua.StatusCode.IsGood(dataValue.StatusCode)) { DataResponse dataResponse = new DataResponse(); DataFrame dataFrame = new DataFrame(query.refId); var timeField = dataFrame.AddField("Time", typeof(DateTime)); var fieldName = GetFieldName(query, relativePath); Field valueField = dataFrame.AddField(fieldName, dataValue?.Value != null ? dataValue.Value.GetType() : typeof(string)); timeField.Append(LimitDateTime(dataValue.SourceTimestamp)); valueField.Append(dataValue?.Value != null ? dataValue?.Value : ""); dataResponse.Frames.Add(dataFrame.ToGprcArrowFrame()); return(new Result <DataResponse>(dataResponse)); } else { return(new Result <DataResponse>(dataValue.StatusCode, string.Format("Error reading node with id {0}", nodeId.ToString()))); } } catch (Exception e) { log.LogError(e.Message); return(new Result <DataResponse>(dataValue.StatusCode, string.Format("Error reading node with id {0}: {1}", nodeId.ToString(), e.Message))); } }
internal static Result <DataResponse> CreateHistoryDataResponse(Result <HistoryData> valuesResult, OpcUAQuery query, BrowsePath relativePath) { if (valuesResult.Success) { var dataResponse = new DataResponse(); var dataFrame = new DataFrame(query.refId); var timeField = dataFrame.AddField("Time", typeof(DateTime)); Field valueField = null; foreach (DataValue entry in valuesResult.Value.DataValues) { if (valueField == null && entry.Value != null) { var fieldName = GetFieldName(query, relativePath); valueField = dataFrame.AddField(fieldName, entry.Value.GetType()); } if (valueField != null) { valueField.Append(entry.Value); timeField.Append(entry.SourceTimestamp); } } dataResponse.Frames.Add(dataFrame.ToGprcArrowFrame()); return(new Result <DataResponse>(dataResponse)); } else { return(new Result <DataResponse>(valuesResult.StatusCode, valuesResult.Error)); } }
/// <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> /// Follows the browse path and returns any targets found. /// </summary> public void TranslateBrowsePath( BrowsePath request, BrowsePathResult result, DiagnosticInfo diagnosticInfo) { lock (m_lock) { // find the starting node. Node source = m_nodes.Find(request.StartingNode); if (source == null) { result.StatusCode = new StatusCode(StatusCodes.BadNodeIdUnknown); return; } // check if there is nothing to do. if (request.RelativePath.Elements == null || request.RelativePath.Elements.Count == 0) { result.StatusCode = new StatusCode(StatusCodes.BadNothingToDo); return; } result.Targets = new ListOfBrowsePathTarget(); Node current = source; // follow each element in the browse path. for (int ii = 0; ii < request.RelativePath.Elements.Count; ii++) { RelativePathElement element = request.RelativePath.Elements[ii]; bool found = false; // need to find any matching reference. foreach (ReferenceNode reference in current.References) { // inverse is a quick check - do that first. if (reference.IsInverse != element.IsInverse) { continue; } // check for reference type matches. if (reference.ReferenceTypeId != element.ReferenceTypeId) { if (!element.IncludeSubtypes) { continue; } if (!IsTypeOf(reference.ReferenceTypeId, element.ReferenceTypeId)) { continue; } } // The UA type model requires that the browse names of all targets of hierarchial references // be unique within a parent. This means most browse paths will point to no more than one node. // However, instances are allowed to add additional nodes with duplicate browse names. If the server // allows this it must keep track of the child that matches the type model and return it as the // first target. // need to find the target to check the browse name. Node target = m_nodes.Find(reference.TargetId); if (target != null) { if (element.TargetName == target.BrowseName) { found = true; current = target; break; } } } if (found) { // check if the complete path has been followed. if (ii == request.RelativePath.Elements.Count - 1) { BrowsePathTarget item = new BrowsePathTarget(); item.TargetId = new ExpandedNodeId(current.NodeId); item.RemainingPathIndex = UInt32.MaxValue; result.Targets.Add(item); } } } } }
/// <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> /// 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> /// Verifies that the timestamps match the requested filter. /// </summary> private bool VerifyPaths( Node node, BrowsePath request, BrowsePathResult result) { // check empty path. if (request.RelativePath.Elements == null || request.RelativePath.Elements.Count == 0) { if (result.StatusCode != StatusCodes.BadBrowseNameInvalid) { Log( "Unexpected error returned during translate for Node '{0}'. NodeId = {1}, Expected = {2}, Actual = {3}", node, node.NodeId, (StatusCode)StatusCodes.BadBrowseNameInvalid, result.StatusCode); return(false); } } BrowsePathResult expectedResult = new BrowsePathResult(); GetTargets(node, request.RelativePath.Elements, 0, expectedResult); if (result.StatusCode == StatusCodes.BadNoMatch) { if (expectedResult.Targets.Count > 0) { Log( "Translate returned BadNoMatch when targets expected '{0}'. NodeId = {1}, Path = {2}, ExpectedCount = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedResult.Targets.Count); return(false); } if (result.Targets.Count > 0) { Log( "Translate returned targets with a BadNoMatch code '{0}'. NodeId = {1}, Path = {2}, ActualCount = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), result.Targets.Count); return(false); } return(true); } if (expectedResult.Targets.Count == 0) { Log( "Translate returned invalided error code when no targets exist '{0}'. NodeId = {1}, Path = {2}, StatusCode = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), (StatusCode)result.StatusCode); return(false); } // check status code. if (result.StatusCode != StatusCodes.Good) { Log( "Translate returned an error for Node '{0}'. NodeId = {1}, Path = {2}, StatusCode = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), (StatusCode)result.StatusCode); return(false); } // check for expected targets. for (int ii = 0; ii < expectedResult.Targets.Count; ii++) { BrowsePathTarget expectedTarget = expectedResult.Targets[ii]; bool found = false; for (int jj = 0; jj < result.Targets.Count; jj++) { BrowsePathTarget actualTarget = result.Targets[jj]; if (actualTarget.TargetId != expectedTarget.TargetId) { continue; } found = true; if (actualTarget.RemainingPathIndex != expectedTarget.RemainingPathIndex) { Log( "Translate did not return correct remaining path index for target Node '{0}'. NodeId = {1}, Path = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedTarget.RemainingPathIndex, actualTarget.RemainingPathIndex); return(false); } break; } if (!found) { Log( "Translate did not return expected target Node '{0}'. NodeId = {1}, Path = {2}, TargetId = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), expectedTarget.TargetId); return(false); } } // check for unexpected targets. for (int ii = 0; ii < result.Targets.Count; ii++) { BrowsePathTarget actualTarget = result.Targets[ii]; bool found = false; for (int jj = 0; jj < expectedResult.Targets.Count; jj++) { BrowsePathTarget expectedTarget = expectedResult.Targets[jj]; if (actualTarget.TargetId == expectedTarget.TargetId) { found = true; break; } } if (!found) { Log( "Translate returned unexpected target Node '{0}'. NodeId = {1}, Path = {2}, TargetId = {3}", node, node.NodeId, GetRelativePath(request.RelativePath.Elements), actualTarget.TargetId); return(false); } } // all ok. return(true); }
/// <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> /// 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> /// Constructs the browse path. /// </summary> /// <param name="nodeId">The node id.</param> /// <param name="hdaAttributeId">The hda attribute id.</param> /// <param name="browsePaths">The browse paths.</param> /// <returns></returns> private BrowsePath Construct(NodeId nodeId, uint hdaAttributeId, params string[] browsePaths) { BrowsePath browsePath = new BrowsePath(); browsePath.StartingNode = nodeId; browsePath.Handle = hdaAttributeId; for (int ii = 0; ii < browsePaths.Length; ii++) { RelativePathElement element = new RelativePathElement(); element.ReferenceTypeId = ReferenceTypeIds.HasChild; element.IsInverse = false; element.IncludeSubtypes = true; element.TargetName = browsePaths[ii]; browsePath.RelativePath.Elements.Add(element); } return browsePath; }
/// <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> /// Follows the browse path and returns any targets found. /// </summary> public void TranslateBrowsePath( BrowsePath request, BrowsePathResult result, DiagnosticInfo diagnosticInfo) { lock (m_lock) { // find the starting node. Node source = m_nodes.Find(request.StartingNode); if (source == null) { result.StatusCode = new StatusCode(StatusCodes.BadNodeIdUnknown); return; } // check if there is nothing to do. if (request.RelativePath.Elements == null || request.RelativePath.Elements.Count == 0) { result.StatusCode = new StatusCode(StatusCodes.BadNothingToDo); return; } result.Targets = new ListOfBrowsePathTarget(); Node current = source; // follow each element in the browse path. for (int ii = 0; ii < request.RelativePath.Elements.Count; ii++) { RelativePathElement element = request.RelativePath.Elements[ii]; bool found = false; // need to find any matching reference. foreach (ReferenceNode reference in current.References) { // inverse is a quick check - do that first. if (reference.IsInverse != element.IsInverse) { continue; } // check for reference type matches. if (reference.ReferenceTypeId != element.ReferenceTypeId) { if (!element.IncludeSubtypes) { continue; } if (!IsTypeOf(reference.ReferenceTypeId, element.ReferenceTypeId)) { continue; } } // The UA type model requires that the browse names of all targets of hierarchial references // be unique within a parent. This means most browse paths will point to no more than one node. // However, instances are allowed to add additional nodes with duplicate browse names. If the server // allows this it must keep track of the child that matches the type model and return it as the // first target. // need to find the target to check the browse name. Node target = m_nodes.Find(reference.TargetId); if (target != null) { if (element.TargetName == target.BrowseName) { found = true; current = target; break; } } } if (found) { // check if the complete path has been followed. if (ii == request.RelativePath.Elements.Count - 1) { BrowsePathTarget item = new BrowsePathTarget(); item.TargetId = new ExpandedNodeId(current.NodeId); item.RemainingPathIndex = UInt32.MaxValue; result.Targets.Add(item); } } } } }
/// <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; } } }
private void button1_Click(object sender, EventArgs e) { BrowsePath.ShowDialog(); }