/// <summary> /// Browses the children of the node and updates the tree. /// </summary> private bool BrowseChildren(TreeNode parent) { ReferenceDescription reference = parent.Tag as ReferenceDescription; if (reference == null) { return(false); } parent.Nodes.Clear(); if (reference.NodeId.IsAbsolute) { return(false); } BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)reference.NodeId; nodeToBrowse.BrowseDirection = m_browseDirection; nodeToBrowse.ReferenceTypeId = m_referenceTypeId; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)(int)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); ViewDescription view = null; if (NodeId.IsNull(m_viewId)) { view = new ViewDescription(); view.ViewId = m_viewId; view.Timestamp = DateTime.MinValue; view.ViewVersion = 0; } BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Browse( null, view, 0, nodesToBrowse, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return(false); } UpdateNode(parent, results[0].References); while (results[0].ContinuationPoint != null && results[0].ContinuationPoint.Length > 0) { ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); m_session.BrowseNext( null, parent == null, continuationPoints, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return(false); } UpdateNode(parent, results[0].References); } return(true); }
/// <summary> /// Worker function to browse the full address space of a server. /// </summary> /// <param name="services">The service interface.</param> /// <param name="operationLimits">The operation limits.</param> public static ReferenceDescriptionCollection BrowseFullAddressSpaceWorker( IServerTestServices services, RequestHeader requestHeader, OperationLimits operationLimits = null, BrowseDescription browseDescription = null) { operationLimits = operationLimits ?? new OperationLimits(); requestHeader.Timestamp = DateTime.UtcNow; // Browse template var startingNode = Objects.RootFolder; var browseTemplate = browseDescription ?? new BrowseDescription { NodeId = startingNode, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All }; var browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId( new NodeIdCollection(new NodeId[] { Objects.RootFolder }), browseTemplate); // Browse ResponseHeader response = null; uint requestedMaxReferencesPerNode = operationLimits.MaxNodesPerBrowse; bool verifyMaxNodesPerBrowse = operationLimits.MaxNodesPerBrowse > 0; var referenceDescriptions = new ReferenceDescriptionCollection(); // Test if server responds with BadNothingToDo { var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection.Take(0).ToArray(), out var results, out var infos)); Assert.AreEqual(StatusCodes.BadNothingToDo, sre.StatusCode); } while (browseDescriptionCollection.Any()) { BrowseResultCollection allResults = new BrowseResultCollection(); if (verifyMaxNodesPerBrowse && browseDescriptionCollection.Count > operationLimits.MaxNodesPerBrowse) { verifyMaxNodesPerBrowse = false; // Test if server responds with BadTooManyOperations var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); // Test if server responds with BadTooManyOperations var tempBrowsePath = browseDescriptionCollection.Take((int)operationLimits.MaxNodesPerBrowse + 1).ToArray(); sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, tempBrowsePath, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); } bool repeatBrowse; var maxNodesPerBrowse = operationLimits.MaxNodesPerBrowse; BrowseResultCollection browseResultCollection = new BrowseResultCollection(); DiagnosticInfoCollection diagnosticsInfoCollection; do { var browseCollection = (maxNodesPerBrowse == 0) ? browseDescriptionCollection : browseDescriptionCollection.Take((int)maxNodesPerBrowse).ToArray(); repeatBrowse = false; try { requestHeader.Timestamp = DateTime.UtcNow; response = services.Browse(requestHeader, null, requestedMaxReferencesPerNode, browseCollection, out browseResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, browseCollection); allResults.AddRange(browseResultCollection); } catch (ServiceResultException sre) { if (sre.StatusCode == StatusCodes.BadEncodingLimitsExceeded || sre.StatusCode == StatusCodes.BadResponseTooLarge) { // try to address by overriding operation limit maxNodesPerBrowse = maxNodesPerBrowse == 0 ? (uint)browseCollection.Count / 2 : maxNodesPerBrowse / 2; repeatBrowse = true; } else { throw; } } } while (repeatBrowse); if (maxNodesPerBrowse == 0) { browseDescriptionCollection.Clear(); } else { browseDescriptionCollection = browseDescriptionCollection.Skip((int)maxNodesPerBrowse).ToArray(); } // Browse next var continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseResultCollection); while (continuationPoints.Any()) { requestHeader.Timestamp = DateTime.UtcNow; response = services.BrowseNext(requestHeader, false, continuationPoints, out var browseNextResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, continuationPoints); allResults.AddRange(browseNextResultCollection); continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseNextResultCollection); } // Build browse request for next level var browseTable = new NodeIdCollection(); foreach (var result in allResults) { referenceDescriptions.AddRange(result.References); foreach (var reference in result.References) { browseTable.Add(ExpandedNodeId.ToNodeId(reference.NodeId, null)); } } browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId(browseTable, browseTemplate); } referenceDescriptions.Sort((x, y) => (x.NodeId.CompareTo(y.NodeId))); TestContext.Out.WriteLine("Found {0} references on server.", referenceDescriptions.Count); foreach (var reference in referenceDescriptions) { TestContext.Out.WriteLine("NodeId {0} {1} {2}", reference.NodeId, reference.NodeClass, reference.BrowseName); } return(referenceDescriptions); }
/// <summary> /// Collects the fields for the instance node. /// </summary> /// <param name="session">The session.</param> /// <param name="nodeId">The node id.</param> /// <param name="parentPath">The parent path.</param> /// <param name="fields">The event fields.</param> /// <param name="fieldNodeIds">The node id for the declaration of the field.</param> /// <param name="foundNodes">The table of found nodes.</param> private static void CollectFields( Session session, NodeId nodeId, QualifiedNameCollection parentPath, SimpleAttributeOperandCollection fields, List <NodeId> fieldNodeIds, Dictionary <NodeId, QualifiedNameCollection> foundNodes) { // find all of the children of the field. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.Aggregates; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; ReferenceDescriptionCollection children = FormUtils.Browse(session, nodeToBrowse, false); if (children == null) { return; } // process the children. for (int ii = 0; ii < children.Count; ii++) { ReferenceDescription child = children[ii]; if (child.NodeId.IsAbsolute) { continue; } // construct browse path. QualifiedNameCollection browsePath = new QualifiedNameCollection(parentPath); browsePath.Add(child.BrowseName); // check if the browse path is already in the list. int index = ContainsPath(fields, browsePath); if (index < 0) { SimpleAttributeOperand field = new SimpleAttributeOperand(); field.TypeDefinitionId = ObjectTypeIds.BaseEventType; field.BrowsePath = browsePath; field.AttributeId = (child.NodeClass == NodeClass.Variable) ? Attributes.Value : Attributes.NodeId; fields.Add(field); fieldNodeIds.Add((NodeId)child.NodeId); } // recusively find all of the children. NodeId targetId = (NodeId)child.NodeId; // need to guard against loops. if (!foundNodes.ContainsKey(targetId)) { foundNodes.Add(targetId, browsePath); CollectFields(session, (NodeId)child.NodeId, browsePath, fields, fieldNodeIds, foundNodes); } } }
/// <summary> /// Displays the attributes and properties in the attributes view. /// </summary> /// <param name="sourceId">The NodeId of the Node to browse.</param> private void DisplayAttributes(NodeId sourceId) { try { AttributesLV.Items.Clear(); ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); // attempt to read all possible attributes. for (uint ii = Attributes.NodeClass; ii <= Attributes.UserExecutable; ii++) { ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = sourceId; nodeToRead.AttributeId = ii; nodesToRead.Add(nodeToRead); } int startOfProperties = nodesToRead.Count; // find all of the pror of the node. BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.HasProperty; nodeToBrowse1.IncludeSubtypes = true; nodeToBrowse1.NodeClassMask = 0; nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse1); // fetch property references from the server. ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); if (references == null) { return; } for (int ii = 0; ii < references.Count; ii++) { // ignore external references. if (references[ii].NodeId.IsAbsolute) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)references[ii].NodeId; nodeToRead.AttributeId = Attributes.Value; nodesToRead.Add(nodeToRead); } // read all values. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // process results. for (int ii = 0; ii < results.Count; ii++) { string name = null; string datatype = null; string value = null; // process attribute value. if (ii < startOfProperties) { // ignore attributes which are invalid for the node. if (results[ii].StatusCode == StatusCodes.BadAttributeIdInvalid) { continue; } // get the name of the attribute. name = Attributes.GetBrowseName(nodesToRead[ii].AttributeId); // display any unexpected error. if (StatusCode.IsBad(results[ii].StatusCode)) { datatype = Utils.Format("{0}", Attributes.GetDataTypeId(nodesToRead[ii].AttributeId)); value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); datatype = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { datatype += "[]"; } value = Utils.Format("{0}", results[ii].Value); } } // process property value. else { // ignore properties which are invalid for the node. if (results[ii].StatusCode == StatusCodes.BadNodeIdUnknown) { continue; } // get the name of the property. name = Utils.Format("{0}", references[ii - startOfProperties]); // display any unexpected error. if (StatusCode.IsBad(results[ii].StatusCode)) { datatype = String.Empty; value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); datatype = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { datatype += "[]"; } value = Utils.Format("{0}", results[ii].Value); } } // add the attribute name/value to the list view. ListViewItem item = new ListViewItem(name); item.SubItems.Add(datatype); item.SubItems.Add(value); AttributesLV.Items.Add(item); } // adjust width of all columns. for (int ii = 0; ii < AttributesLV.Columns.Count; ii++) { AttributesLV.Columns[ii].Width = -2; } } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
/// <summary> /// Browses the address space and returns the references found. /// </summary> /// <param name="session">The session.</param> /// <param name="nodeToBrowse">The NodeId for the starting node.</param> /// <param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param> /// <returns> /// The references found. Null if an error occurred. /// </returns> public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError) { try { ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); // construct browse request. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); do { // check for error. if (StatusCode.IsBad(results[0].StatusCode)) { throw new ServiceResultException(results[0].StatusCode); } // process results. for (int ii = 0; ii < results[0].References.Count; ii++) { references.Add(results[0].References[ii]); } // check if all references have been fetched. if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) { break; } // continue browse operation. ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); session.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); }while (true); //return complete list. return(references); } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return(null); } }
/// <summary> /// Reads the arguments for the method. /// </summary> private void ReadArguments(NodeId nodeId) { m_inputArguments = null; m_outputArguments = null; // build list of references to browse. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)NodeClass.Variable; nodeToBrowse.ResultMask = (uint)BrowseResultMask.BrowseName; nodesToBrowse.Add(nodeToBrowse); // find properties. ReferenceDescriptionCollection references = ClientUtils.Browse(m_session, null, nodesToBrowse, false); // build list of properties to read. ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int ii = 0; references != null && ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; // ignore out of server references. if (reference.NodeId.IsAbsolute) { continue; } // ignore other properties. if (reference.BrowseName != Opc.Ua.BrowseNames.InputArguments && reference.BrowseName != Opc.Ua.BrowseNames.OutputArguments) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)reference.NodeId; nodeToRead.AttributeId = Attributes.Value; nodeToRead.Handle = reference; nodesToRead.Add(nodeToRead); } // method has no arguments. if (nodesToRead.Count == 0) { return; } // read the arguments. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // save the results. for (int ii = 0; ii < results.Count; ii++) { ReferenceDescription reference = (ReferenceDescription)nodesToRead[ii].Handle; if (StatusCode.IsGood(results[ii].StatusCode)) { if (reference.BrowseName == Opc.Ua.BrowseNames.InputArguments) { m_inputArguments = (Argument[])ExtensionObject.ToArray(results[ii].GetValue <ExtensionObject[]>(null), typeof(Argument)); } if (reference.BrowseName == Opc.Ua.BrowseNames.OutputArguments) { m_outputArguments = (Argument[])ExtensionObject.ToArray(results[ii].GetValue <ExtensionObject[]>(null), typeof(Argument)); } } } // set default values for input arguments. if (m_inputArguments != null) { foreach (Argument argument in m_inputArguments) { argument.Value = TypeInfo.GetDefaultValue(argument.DataType, argument.ValueRank, m_session.TypeTree); } } }
/// <summary> /// Reads the properties for the node. /// </summary> private void ReadProperties(NodeId nodeId) { // build list of references to browse. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)NodeClass.Variable; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; nodesToBrowse.Add(nodeToBrowse); // find properties. ReferenceDescriptionCollection references = ClientUtils.Browse(m_session, View, nodesToBrowse, false); // build list of properties to read. ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int ii = 0; references != null && ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; // ignore out of server references. if (reference.NodeId.IsAbsolute) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)reference.NodeId; nodeToRead.AttributeId = Attributes.Value; nodeToRead.Handle = reference; nodesToRead.Add(nodeToRead); } if (nodesToRead.Count == 0) { return; } // read the properties. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // add the results to the display. for (int ii = 0; ii < results.Count; ii++) { ReferenceDescription reference = (ReferenceDescription)nodesToRead[ii].Handle; TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); // add the metadata for the attribute. ListViewItem item = new ListViewItem(reference.ToString()); item.SubItems.Add(typeInfo.BuiltInType.ToString()); if (typeInfo.ValueRank >= 0) { item.SubItems[1].Text += "[]"; } // add the value. if (StatusCode.IsBad(results[ii].StatusCode)) { item.SubItems.Add(results[ii].StatusCode.ToString()); } else { item.SubItems.Add(results[ii].WrappedValue.ToString()); } item.Tag = new AttributeInfo() { NodeToRead = nodesToRead[ii], Value = results[ii] }; item.ImageIndex = ClientUtils.GetImageIndex(m_session, NodeClass.Variable, Opc.Ua.VariableTypeIds.PropertyType, false); // display in list. AttributesLV.Items.Add(item); } }
/// <summary> /// Recursively populates the event types table. /// </summary> private void IndexTypesFromServer(NodeId baseTypeId, int eventType) { // check if event type needs to be revised. if (baseTypeId == Opc.Ua.ObjectTypeIds.ConditionType) { eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; } else if (baseTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) { eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; } else if (baseTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) { eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; } // browse for subtypes. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = baseTypeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasSubtype; nodeToBrowse.IncludeSubtypes = false; nodeToBrowse.NodeClassMask = (uint)NodeClass.ObjectType; nodeToBrowse.ResultMask = (uint)(BrowseResultMask.BrowseName | BrowseResultMask.DisplayName | BrowseResultMask.NodeClass); ReferenceDescriptionCollection references = ComAeUtils.Browse( m_session, nodeToBrowse, false); for (int ii = 0; ii < references.Count; ii++) { // these types have t if (references[ii].NodeId.IsAbsolute) { continue; } NodeId typeId = (NodeId)references[ii].NodeId; if (!m_eventTypes.ContainsKey(typeId)) { // collection the instances declared by the type. List<AeEventAttribute> declarations = new List<AeEventAttribute>(); Dictionary<string, AeEventAttribute> map = new Dictionary<string, AeEventAttribute>(); ComAeUtils.CollectInstanceDeclarations( m_session, this, (NodeId)references[ii].NodeId, null, declarations, map); AeEventCategory declaration = new AeEventCategory(); declaration.TypeId = (NodeId)references[ii].NodeId; declaration.SuperTypeId = baseTypeId; declaration.EventType = eventType; declaration.Description = (LocalizedText.IsNullOrEmpty(references[ii].DisplayName)) ? references[ii].BrowseName.Name : references[ii].DisplayName.Text; declaration.Attributes = declarations; m_eventTypes[declaration.TypeId] = declaration; } // recursively look for subtypes. IndexTypesFromServer(typeId, eventType); } }
/// <summary> /// Verifies the reference type id. /// </summary> private bool VerifyReferenceTypeId(Node node, BrowseDescription description, ReferenceDescription reference) { // check if field was not requested. if ((description.ResultMask & (uint)BrowseResultMask.ReferenceTypeId) == 0) { if (!NodeId.IsNull(reference.ReferenceTypeId)) { Log("Returned unexpected non-null ReferenceTypeId when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } return true; } // check for null. if (NodeId.IsNull(reference.ReferenceTypeId)) { Log("Returned unexpected null ReferenceTypeId when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } // check for valid reference. IReferenceType referenceType = Session.NodeCache.Find(reference.ReferenceTypeId) as IReferenceType; if (NodeId.IsNull(reference.ReferenceTypeId)) { Log("Returned invalid ReferenceTypeId when Browsing Node '{0}'. NodeId = {1}, ReferenceTypeId = {2}", node, node.NodeId, reference.ReferenceTypeId); return false; } // check for valid subtype. if (!Session.TypeTree.IsTypeOf(referenceType.NodeId, description.ReferenceTypeId)) { string expectedName = description.ReferenceTypeId.ToString(); IReferenceType expectedType = Session.NodeCache.Find(description.ReferenceTypeId) as IReferenceType; if (expectedType != null) { expectedName = Utils.Format("{0}", expectedType.DisplayName); } Log("ReferenceType {2} is not a subtype of {3} when browsing Node '{0}'. NodeId = {1}", node, node.NodeId, referenceType.DisplayName, expectedName); return false; } 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> /// Browses the references for the specified node. /// </summary> public void Browse( BrowseDescription request, BrowseResult result, DiagnosticInfo diagnosticInfo) { lock (m_lock) { // find the starting nodes. Node source = m_nodes.Find(request.NodeId); if (source == null) { result.StatusCode = new StatusCode(StatusCodes.BadNodeIdUnknown); return; } result.References = new ListOfReferenceDescription(); // return all of the references that meet the filter criteria. foreach (ReferenceNode reference in source.References) { if (reference.IsInverse && request.BrowseDirection == BrowseDirection.Forward_0) { continue; } if (!reference.IsInverse && request.BrowseDirection == BrowseDirection.Inverse_1) { continue; } // the reference type filter can be an exact match or it can be for any subtype. if (reference.ReferenceTypeId != request.ReferenceTypeId) { if (!request.IncludeSubtypes) { continue; } if (!IsTypeOf(reference.ReferenceTypeId, request.ReferenceTypeId)) { continue; } } // need to look up the target to find the attributes. // note that the result filter mask is being ignored. production servers only need to // look up the attributes requested by the client. Node target = m_nodes.Find(reference.TargetId); if (target != null) { ReferenceDescription description = new ReferenceDescription(); description.NodeId = reference.TargetId; description.IsForward = !reference.IsInverse; description.ReferenceTypeId = reference.ReferenceTypeId; description.BrowseName = target.BrowseName; description.DisplayName = target.DisplayName; description.NodeClass = target.NodeClass; description.TypeDefinition = GetTypeDefinition(target); result.References.Add(description); } } } }
/// <summary> /// Fetches the children from the server. /// </summary> private List<AeBrowseElement> Browse(Session session, AeBrowseElement start, bool isArea) { // browse for notifiers and sources. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = start.NodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ResultMask = (uint)(BrowseResultMask.BrowseName); nodeToBrowse.NodeClassMask = (uint)0; if (isArea) { nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasNotifier; nodeToBrowse.IncludeSubtypes = true; } else { nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasEventSource; nodeToBrowse.IncludeSubtypes = true; } ReferenceDescriptionCollection references = ComAeUtils.Browse( session, nodeToBrowse, false); if (references == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } List<AeBrowseElement> hits = new List<AeBrowseElement>(); for (int ii = 0; ii < references.Count; ii++) { // ignore remote references. if (references[ii].NodeId.IsAbsolute) { continue; } // need to check if at the end of the tree. if (references[ii].ReferenceTypeId != ReferenceTypeIds.HasEventSource) { nodeToBrowse.NodeId = (NodeId)references[ii].NodeId; ReferenceDescriptionCollection children = ComAeUtils.Browse(session, nodeToBrowse, false); if (!isArea) { if (children != null && children.Count > 0) { continue; } } else { if (children == null || children.Count == 0) { continue; } } } string browseText = m_mapper.GetLocalBrowseName(references[ii].BrowseName); // check for duplicate browse names. for (int jj = 0; jj < hits.Count; jj++) { if (hits[jj].BrowseText == browseText) { hits[jj].Duplicated = true; browseText = null; break; } } // add new element. if (browseText != null) { AeBrowseElement element = new AeBrowseElement(); element.Parent = start; element.NodeId = (NodeId)references[ii].NodeId; element.BrowseText = m_mapper.GetLocalBrowseName(references[ii].BrowseName); element.IsArea = isArea; hits.Add(element); StringBuilder itemId = new StringBuilder(); itemId.Append(start.ItemId); itemId.Append('/'); itemId.Append(element.BrowseText); element.ItemId = itemId.ToString(); } } // remove any duplicates. for (int ii = 0; ii < hits.Count;) { if (hits[ii].Duplicated) { hits.RemoveAt(ii); continue; } ii++; } return hits; }
/// <summary> /// Verifies that the server does no ignore the BrowseResultMask. /// </summary> private bool DoBrowseResultMaskTest() { // follow tree from each starting node. bool success = true; double increment = MaxProgress/AvailableNodes.Count; double position = 0; Log("Starting BrowseResultMaskTest for {0} Nodes ({1}% Coverage)", AvailableNodes.Values.Count, Configuration.Coverage); int counter = 0; foreach (Node node in AvailableNodes.Values) { if (!CheckCoverage(ref counter)) { continue; } try { BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = node.NodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Both; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.References; nodeToBrowse.ResultMask = (uint)BrowseResultMask.None; ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); if (!Browse(node, nodeToBrowse, references)) { success = false; break; } } catch (Exception e) { success = false; Log(e, "BrowseResultMaskTest Failed for Node '{0}'. NodeId = {1}", node, node.NodeId); } position += increment; ReportProgress(position); } return success; }
/// <summary> /// Begins an asynchronous invocation of the Browse service. /// </summary> /// <param name="requestHeader">The request header.</param> /// <param name="view">The view to browse.</param> /// <param name="nodeToBrowse">The node to browse.</param> /// <param name="maxResultsToReturn">The maximum number of returned values..</param> /// <param name="browseDirection">The browse direction.</param> /// <param name="referenceTypeId">The reference type id.</param> /// <param name="includeSubtypes">If set to <c>true</c> the subtypes of the ReferenceType will be included in the browse.</param> /// <param name="nodeClassMask">The node class mask.</param> /// <param name="callback">The callback.</param> /// <param name="asyncState"></param> /// <returns></returns> public IAsyncResult BeginBrowse( RequestHeader requestHeader, ViewDescription view, NodeId nodeToBrowse, uint maxResultsToReturn, BrowseDirection browseDirection, NodeId referenceTypeId, bool includeSubtypes, uint nodeClassMask, AsyncCallback callback, object asyncState) { BrowseDescription description = new BrowseDescription(); description.NodeId = nodeToBrowse; description.BrowseDirection = browseDirection; description.ReferenceTypeId = referenceTypeId; description.IncludeSubtypes = includeSubtypes; description.NodeClassMask = nodeClassMask; description.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(description); return BeginBrowse( requestHeader, view, maxResultsToReturn, nodesToBrowse, callback, asyncState); }
/// <summary> /// Browses the node and returns the references found. /// </summary> protected virtual bool Browse( Node node, BrowseDescription nodeToBrowse, ReferenceDescriptionCollection references) { BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); BrowseResultCollection results; DiagnosticInfoCollection diagnosticInfos; RequestHeader requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.Browse( requestHeader, new ViewDescription(), 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array during Browse."); return false; } // process results. ByteStringCollection continuationPoints = new ByteStringCollection(); for (int ii = 0; ii < results.Count; ii++) { // check status code. if (StatusCode.IsBad(results[ii].StatusCode)) { Log( "Browse Failed for Node '{0}'. Status = {2}, NodeId = {1}", node, node.NodeId, results[ii].StatusCode); return false; } // save references. references.AddRange(results[ii].References); if (results[ii].ContinuationPoint != null) { continuationPoints.Add(results[ii].ContinuationPoint); } } // process continuation points. while (continuationPoints.Count > 0) { requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.BrowseNext( requestHeader, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array during BrowseNext."); return false; } continuationPoints.Clear(); // process results. for (int ii = 0; ii < results.Count; ii++) { // check status code. if (StatusCode.IsBad(results[ii].StatusCode)) { Log( "BrowseNext Failed for Node '{0}'. Status = {2}, NodeId = {1}", node, node.NodeId, results[ii].StatusCode); return false; } // save references. references.AddRange(results[ii].References); if (results[ii].ContinuationPoint != null) { // check max references. if (results[ii].References.Count == 0) { Log( "No references returned with a continuation point for Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } continuationPoints.Add(results[ii].ContinuationPoint); } } } return true; }
/// <summary> /// Browses the address space and returns all of the supertypes of the specified type node. /// </summary> /// <param name="session">The session.</param> /// <param name="typeId">The NodeId for a type node in the address space.</param> /// <param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param> /// <returns> /// The references found. Null if an error occurred. /// </returns> public static ReferenceDescriptionCollection BrowseSuperTypes(Session session, NodeId typeId, bool throwOnError) { ReferenceDescriptionCollection supertypes = new ReferenceDescriptionCollection(); try { // find all of the children of the field. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = typeId; nodeToBrowse.BrowseDirection = BrowseDirection.Inverse; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasSubtype; nodeToBrowse.IncludeSubtypes = false; // more efficient to use IncludeSubtypes=False when possible. nodeToBrowse.NodeClassMask = 0; // the HasSubtype reference already restricts the targets to Types. nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; ReferenceDescriptionCollection references = Browse(session, nodeToBrowse, throwOnError); while (references != null && references.Count > 0) { // should never be more than one supertype. supertypes.Add(references[0]); // only follow references within this server. if (references[0].NodeId.IsAbsolute) { break; } // get the references for the next level up. nodeToBrowse.NodeId = (NodeId)references[0].NodeId; references = Browse(session, nodeToBrowse, throwOnError); } // return complete list. return supertypes; } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return null; } }
/// <summary> /// Finds the targets for the specified reference. /// </summary> private static List<NodeId> FindTargetOfReference(Session session, List<NodeId> nodeIds, NodeId referenceTypeId, bool throwOnError) { try { // construct browse request. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); for (int ii = 0; ii < nodeIds.Count; ii++) { BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeIds[ii]; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = referenceTypeId; nodeToBrowse.IncludeSubtypes = false; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.None; nodesToBrowse.Add(nodeToBrowse); } // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, null, 1, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); List<NodeId> targetIds = new List<NodeId>(); ByteStringCollection continuationPoints = new ByteStringCollection(); for (int ii = 0; ii < nodeIds.Count; ii++) { targetIds.Add(null); // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { continue; } // check for continuation point. if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) { continuationPoints.Add(results[ii].ContinuationPoint); } // get the node id. if (results[ii].References.Count > 0) { if (NodeId.IsNull(results[ii].References[0].NodeId) || results[ii].References[0].NodeId.IsAbsolute) { continue; } targetIds[ii] = (NodeId)results[ii].References[0].NodeId; } } // release continuation points. if (continuationPoints.Count > 0) { session.BrowseNext( null, true, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); } //return complete list. return targetIds; } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return null; } }
/// <summary> /// Verifies the references returned for a node. /// </summary> private bool VerifyReferences( Node node, BrowseDescription description, ReferenceDescriptionCollection references) { bool success = true; for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; if (reference == null) { Log("Returned null ReferenceDescription when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); success = false; continue; } if (!VerifyTargetId(node, description, reference)) { success = false; continue; } if (!VerifyReferenceTypeId(node, description, reference)) { success = false; continue; } if (!VerifyIsForward(node, description, reference)) { success = false; continue; } } // read the attributes to verify the reference is correct. try { if (!VerifyTargetAttributes(node, description, references)) { return false; } } catch (Exception e) { Log(e, "Could not verify target attributes when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } // verify type definitions. try { if (!VerifyTypeDefinitions(node, description, references)) { return false; } } catch (Exception e) { Log(e, "Could not verify type definitions when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } return success; }
/// <summary> /// Verifies the target. /// </summary> private bool VerifyTargetId(Node node, BrowseDescription description, ReferenceDescription reference) { // check for null. if (NodeId.IsNull(reference.NodeId)) { Log("Returned unexpected null NodeId when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } // check for local id. if (reference.NodeId.ServerIndex == 0) { if (!String.IsNullOrEmpty(reference.NodeId.NamespaceUri)) { Log("Returned NamespaceUri for local node when Browsing Node '{0}'. NodeId = {1}, TargetId = {2}", node, node.NodeId, reference.NodeId); return false; } } return true; }
/// <summary> /// Creates a browse description for a node class test. /// </summary> private void AddReferenceTypeTest( Node node, NodeId referenceTypeId, bool isInverse, bool includeSubtypes, List<Node> nodes, BrowseDescriptionCollection nodesToBrowse, List<ReferenceDescriptionCollection> references, bool clearLists) { if (clearLists) { nodes.Clear(); nodesToBrowse.Clear(); references.Clear(); } nodes.Add(node); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = node.NodeId; nodeToBrowse.ReferenceTypeId = referenceTypeId; nodeToBrowse.IncludeSubtypes = includeSubtypes; nodeToBrowse.BrowseDirection = (isInverse)?BrowseDirection.Inverse:BrowseDirection.Forward; nodeToBrowse.NodeClassMask = (uint)NodeClass.Unspecified; nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.NodeClass | BrowseResultMask.ReferenceTypeId | BrowseResultMask.IsForward); nodesToBrowse.Add(nodeToBrowse); references.Add(new ReferenceDescriptionCollection()); }
/// <summary> /// Verifies the results of a browse filter. /// </summary> private bool VerifyFilterResults( Node node, BrowseDescription description, ReferenceDescriptionCollection actualList) { NodeId referenceTypeId = description.ReferenceTypeId; BrowseDirection browseDirection = description.BrowseDirection; bool includeSubtypes = description.IncludeSubtypes; NodeClass nodeClassMask = (NodeClass)description.NodeClassMask; // nothing to verify if no master list. ReferenceDescriptionCollection masterList = node.Handle as ReferenceDescriptionCollection; if (masterList == null) { return true; } // cannot verify filter if filter criteria not returned. BrowseResultMask requiredMask = (BrowseResultMask.ReferenceTypeId | BrowseResultMask.IsForward | BrowseResultMask.NodeClass); if ((description.ResultMask & (uint)requiredMask) != (uint)requiredMask) { return true; } bool success = true; // look for missing references. for (int ii = 0; ii < masterList.Count; ii++) { ReferenceDescription reference = masterList[ii]; if (nodeClassMask != NodeClass.Unspecified && (reference.NodeClass & nodeClassMask) == 0) { continue; } if ((browseDirection == BrowseDirection.Inverse && reference.IsForward) || (browseDirection == BrowseDirection.Forward && !reference.IsForward)) { continue; } if (reference.ReferenceTypeId != referenceTypeId) { if (!includeSubtypes) { continue; } if (!Session.TypeTree.IsTypeOf(reference.ReferenceTypeId, referenceTypeId)) { continue; } } bool found = false; for (int jj = 0; jj < actualList.Count; jj++) { if (actualList[jj].NodeId == reference.NodeId && actualList[jj].IsForward == reference.IsForward && actualList[jj].ReferenceTypeId == reference.ReferenceTypeId) { found = true; break; } } if (!found) { Log( "Did not return expected target when browsing Node '{0}'. NodeId = {1}, NodeClassMask = {2}, ReferenceFilter = {3}, TargetName = {4}, NodeClass = {5}, ReferenceType = {6}, TargetId = {7}.", node, node.NodeId, nodeClassMask, Session.TypeTree.FindReferenceTypeName(referenceTypeId), reference.DisplayName, reference.NodeClass, Session.TypeTree.FindReferenceTypeName(reference.ReferenceTypeId), reference.NodeId); success = false; } } // look for extra references. for (int ii = 0; ii < actualList.Count; ii++) { bool found = false; for (int jj = 0; jj < masterList.Count; jj++) { ReferenceDescription reference = masterList[jj]; if (nodeClassMask != NodeClass.Unspecified && (reference.NodeClass & nodeClassMask) == 0) { continue; } if (actualList[ii].NodeId != reference.NodeId || actualList[ii].IsForward != reference.IsForward || actualList[ii].ReferenceTypeId != reference.ReferenceTypeId) { continue; } if ((browseDirection != BrowseDirection.Inverse && reference.IsForward) || (browseDirection != BrowseDirection.Forward && !reference.IsForward)) { if (!includeSubtypes) { if (reference.ReferenceTypeId == referenceTypeId) { found = true; break; } } else { if (Session.TypeTree.IsTypeOf(reference.ReferenceTypeId, referenceTypeId)) { found = true; break; } } } Log( "Returned invalid target when browsing Node '{0}'. NodeId = {1}, NodeClassMask = {2}, ReferenceFilter = {3}, TargetName = {4}, NodeClass = {5}, ReferenceType = {6}, TargetId = {7}.", node, node.NodeId, nodeClassMask, Session.TypeTree.FindReferenceTypeName(referenceTypeId), reference.DisplayName, reference.NodeClass, Session.TypeTree.FindReferenceTypeName(reference.ReferenceTypeId), reference.NodeId); success = false; break; } if (!found) { Log( "Returned unexpected target when browsing Node '{0}'. NodeId = {1}, NodeClassMask = {2}, ReferenceFilter = {3}, TargetName = {4}, NodeClass = {5}, ReferenceType = {6}, TargetId = {7}.", node, node.NodeId, nodeClassMask, Session.TypeTree.FindReferenceTypeName(referenceTypeId), actualList[ii].DisplayName, actualList[ii].NodeClass, Session.TypeTree.FindReferenceTypeName(actualList[ii].ReferenceTypeId), actualList[ii].NodeId); success = false; continue; } } return success; }
/// <summary> /// Creates a browse description for a node class test. /// </summary> private void AddNodeClassTest( Node node, NodeClass nodeClassMask, List<Node> nodes, BrowseDescriptionCollection nodesToBrowse, List<ReferenceDescriptionCollection> references, bool clearLists) { if (clearLists) { nodes.Clear(); nodesToBrowse.Clear(); references.Clear(); } nodes.Add(node); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = node.NodeId; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.References; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.BrowseDirection = BrowseDirection.Both; nodeToBrowse.NodeClassMask = (uint)nodeClassMask; nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.NodeClass | BrowseResultMask.ReferenceTypeId | BrowseResultMask.IsForward); nodesToBrowse.Add(nodeToBrowse); references.Add(new ReferenceDescriptionCollection()); }
/// <summary> /// Browses the node and verifies the results. /// </summary> protected override bool Browse( Node node, BrowseDescription nodeToBrowse, ReferenceDescriptionCollection references) { List<Node> nodes = new List<Node>(); BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); List<ReferenceDescriptionCollection> referenceLists = new List<ReferenceDescriptionCollection>(); nodes.Add(node); nodesToBrowse.Add(nodeToBrowse); referenceLists.Add(references); return Browse(nodes, nodesToBrowse, referenceLists); }
/// <summary> /// Reads the attribute values in order to compare them to the returned results. /// </summary> private bool VerifyTypeDefinitions( Node node, BrowseDescription description, ReferenceDescriptionCollection references) { // check if nothing to do. if (references.Count == 0) { return true; } bool success = true; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; if ((description.ResultMask & (uint)BrowseResultMask.TypeDefinition) == 0) { if (!NodeId.IsNull(reference.TypeDefinition)) { success = false; Log( "Unexpected TypeDefinition returned for Node '{0}'. NodeId = {1}, TargetId = {2}, TypeDefinition = {3}", node, node.NodeId, reference.NodeId, reference.TypeDefinition); } continue; } // ignore invalid or external references. if (reference == null || reference.NodeId == null || reference.NodeId.IsAbsolute) { continue; } BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)reference.NodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.IncludeSubtypes = false; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasTypeDefinition; nodeToBrowse.ResultMask = (uint)BrowseResultMask.None; nodeToBrowse.Handle = references[ii]; nodesToBrowse.Add(nodeToBrowse); } // nothing more to do if no type definitions requested. if ((description.ResultMask & (uint)BrowseResultMask.TypeDefinition) == 0) { return success; } // browse. BrowseResultCollection results; DiagnosticInfoCollection diagnosticInfos; RequestHeader requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.Browse( null, m_view, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array when Browsing TypeDefinition while Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } bool error = false; for (int ii = 0; ii < nodesToBrowse.Count; ii++) { BrowseResult result = results[ii]; if (StatusCode.IsBad(result.StatusCode)) { error = true; Log( "Browse TypeDefinition Failed for Node '{0}'. NodeId = {1}, TargetId = {2}, Status = {3}", node, node.NodeId, nodesToBrowse[ii].NodeId, results[0].StatusCode); continue; } ReferenceDescription reference = (ReferenceDescription)nodesToBrowse[ii].Handle; if (result.References.Count == 0) { if (!NodeId.IsNull(reference.TypeDefinition)) { error = true; Log( "Unexpected TypeDefinition returned for Node '{0}'. NodeId = {1}, TargetId = {2}, TypeDefinition = {3}", node, node.NodeId, nodesToBrowse[ii].NodeId, reference.TypeDefinition); continue; } } else { if (result.References.Count != 1) { error = true; Log( "Too many TypeDefinitions returned for Node '{0}'. NodeId = {1}, TargetId = {2}, Count = {3}", node, node.NodeId, nodesToBrowse[ii].NodeId, result.References.Count); continue; } if (result.References[0].NodeId != reference.TypeDefinition) { error = true; Log( "Incorrect TypeDefinition returned for Node '{0}'. NodeId = {1}, TargetId = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, nodesToBrowse[ii].NodeId, result.References[0].NodeId, reference.TypeDefinition); continue; } } } return !error; }
/// <summary> /// Returns the set of references that meet the filter criteria. /// </summary> private ServiceResult Browse( OperationContext context, ViewDescription view, uint maxReferencesPerNode, bool assignContinuationPoint, BrowseDescription nodeToBrowse, BrowseResult result) { Debug.Assert(context != null); Debug.Assert(nodeToBrowse != null); Debug.Assert(result != null); // find node manager that owns the node. INodeManager nodeManager = null; object handle = GetManagerHandle(nodeToBrowse.NodeId, out nodeManager); if (handle == null) { return StatusCodes.BadNodeIdUnknown; } if (!NodeId.IsNull(nodeToBrowse.ReferenceTypeId) && !m_server.TypeTree.IsKnown(nodeToBrowse.ReferenceTypeId)) { return StatusCodes.BadReferenceTypeIdInvalid; } if (nodeToBrowse.BrowseDirection < BrowseDirection.Forward || nodeToBrowse.BrowseDirection > BrowseDirection.Both) { return StatusCodes.BadBrowseDirectionInvalid; } // create a continuation point. ContinuationPoint cp = new ContinuationPoint(); cp.Manager = nodeManager; cp.View = view; cp.NodeToBrowse = handle; cp.MaxResultsToReturn = maxReferencesPerNode; cp.BrowseDirection = nodeToBrowse.BrowseDirection; cp.ReferenceTypeId = nodeToBrowse.ReferenceTypeId; cp.IncludeSubtypes = nodeToBrowse.IncludeSubtypes; cp.NodeClassMask = nodeToBrowse.NodeClassMask; cp.ResultMask = (BrowseResultMask)nodeToBrowse.ResultMask; cp.Index = 0; cp.Data = null; // check if reference type left unspecified. if (NodeId.IsNull(cp.ReferenceTypeId)) { cp.ReferenceTypeId = ReferenceTypeIds.References; cp.IncludeSubtypes = true; } // loop until browse is complete or max results. ReferenceDescriptionCollection references = result.References; ServiceResult error = FetchReferences(context, assignContinuationPoint, ref cp, ref references); result.References = references; // save continuation point. if (cp != null) { result.StatusCode = StatusCodes.Good; result.ContinuationPoint = cp.Id.ToByteArray(); } // all is good. return error; }
/// <summary> /// 读取一个节点的所有属性 /// </summary> /// <param name="tag">节点值</param> /// <returns>所有的数据</returns> public DataValue[] ReadNoteDataValueAttributes(string tag) { NodeId sourceId = new NodeId(tag); ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); // attempt to read all possible attributes. // 尝试着去读取所有可能的特性 for (uint ii = Attributes.NodeId; ii <= Attributes.UserExecutable; ii++) { ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = sourceId; nodeToRead.AttributeId = ii; nodesToRead.Add(nodeToRead); } int startOfProperties = nodesToRead.Count; // find all of the pror of the node. BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.HasProperty; nodeToBrowse1.IncludeSubtypes = true; nodeToBrowse1.NodeClassMask = 0; nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse1); // fetch property references from the server. ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); if (references == null) { return(new DataValue[0]); } for (int ii = 0; ii < references.Count; ii++) { // ignore external references. if (references[ii].NodeId.IsAbsolute) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)references[ii].NodeId; nodeToRead.AttributeId = Attributes.Value; nodesToRead.Add(nodeToRead); } // read all values. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); return(results.ToArray()); }
/// <summary> /// Browses the address space and returns the references found. /// </summary> /// <param name="session">The session.</param> /// <param name="nodeToBrowse">The NodeId for the starting node.</param> /// <param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param> /// <returns> /// The references found. Null if an error occurred. /// </returns> public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError) { try { ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); // construct browse request. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); do { // check for error. if (StatusCode.IsBad(results[0].StatusCode)) { throw new ServiceResultException(results[0].StatusCode); } // process results. for (int ii = 0; ii < results[0].References.Count; ii++) { references.Add(results[0].References[ii]); } // check if all references have been fetched. if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) { break; } // continue browse operation. ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); session.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); } while (true); //return complete list. return references; } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return null; } }
/// <summary> /// Verifies the isforward flag. /// </summary> private bool VerifyIsForward(Node node, BrowseDescription description, ReferenceDescription reference) { // check if field was not requested. if ((description.ResultMask & (uint)BrowseResultMask.IsForward) == 0) { if (reference.IsForward) { Log("Returned unexpected IsForward=True when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } return true; } if (reference.IsForward) { if (description.BrowseDirection == BrowseDirection.Inverse) { Log("Returned unexpected IsForward=False when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } } else { if (description.BrowseDirection == BrowseDirection.Forward) { Log("Returned unexpected IsForward=True when Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } } return true; }
/// <summary> /// Collects instance declarations nodes from with a type. /// </summary> public static void CollectInstanceDeclarations( Session session, ComNamespaceMapper mapper, NodeId typeId, AeEventAttribute parent, List<AeEventAttribute> instances, IDictionary<string, AeEventAttribute> map) { // find the children. BrowseDescription nodeToBrowse = new BrowseDescription(); if (parent == null) { nodeToBrowse.NodeId = typeId; } else { nodeToBrowse.NodeId = parent.NodeId; } nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasChild; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; // ignore any browsing errors. ReferenceDescriptionCollection references = Browse(session, nodeToBrowse, false); if (references == null) { return; } // process the children. List<NodeId> nodeIds = new List<NodeId>(); List<AeEventAttribute> children = new List<AeEventAttribute>(); for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; if (reference.NodeId.IsAbsolute) { continue; } // create a new declaration. AeEventAttribute child = new AeEventAttribute(); child.RootTypeId = typeId; child.NodeId = (NodeId)reference.NodeId; child.BrowseName = reference.BrowseName; child.NodeClass = reference.NodeClass; if (!LocalizedText.IsNullOrEmpty(reference.DisplayName)) { child.DisplayName = reference.DisplayName.Text; } else { child.DisplayName = reference.BrowseName.Name; } if (parent != null) { child.BrowsePath = new QualifiedNameCollection(parent.BrowsePath); child.BrowsePathDisplayText = Utils.Format("{0}/{1}", parent.BrowsePathDisplayText, mapper.GetLocalBrowseName(reference.BrowseName)); child.DisplayPath = Utils.Format("{0}/{1}", parent.DisplayPath, reference.DisplayName); } else { child.BrowsePath = new QualifiedNameCollection(); child.BrowsePathDisplayText = Utils.Format("{0}", reference.BrowseName); child.DisplayPath = Utils.Format("{0}", reference.DisplayName); } child.BrowsePath.Add(reference.BrowseName); // check if reading an overridden declaration. AeEventAttribute overriden = null; if (map.TryGetValue(child.BrowsePathDisplayText, out overriden)) { child.OverriddenDeclaration = overriden; } map[child.BrowsePathDisplayText] = child; // add to list. children.Add(child); nodeIds.Add(child.NodeId); } // check if nothing more to do. if (children.Count == 0) { return; } // find the modelling rules. List<NodeId> modellingRules = FindTargetOfReference(session, nodeIds, Opc.Ua.ReferenceTypeIds.HasModellingRule, false); if (modellingRules != null) { for (int ii = 0; ii < nodeIds.Count; ii++) { children[ii].ModellingRule = modellingRules[ii]; // if the modelling rule is null then the instance is not part of the type declaration. if (NodeId.IsNull(modellingRules[ii])) { map.Remove(children[ii].BrowsePathDisplayText); } } } // update the descriptions. UpdateInstanceDescriptions(session, children, false); // recusively collect instance declarations for the tree below. for (int ii = 0; ii < children.Count; ii++) { if (!NodeId.IsNull(children[ii].ModellingRule)) { instances.Add(children[ii]); CollectInstanceDeclarations(session, mapper, typeId, children[ii], instances, map); } } }
/// <summary> /// Browses the children of the node and updates the tree. /// </summary> private bool BrowseChildren(TreeNode parent) { ReferenceDescription reference = parent.Tag as ReferenceDescription; if (reference == null) { return false; } parent.Nodes.Clear(); if (reference.NodeId.IsAbsolute) { return false; } BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)reference.NodeId; nodeToBrowse.BrowseDirection = m_browseDirection; nodeToBrowse.ReferenceTypeId = m_referenceTypeId; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)(int)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); ViewDescription view = null; if (NodeId.IsNull(m_viewId)) { view = new ViewDescription(); view.ViewId = m_viewId; view.Timestamp = DateTime.MinValue; view.ViewVersion = 0; } BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Browse( null, view, 0, nodesToBrowse, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return false; } UpdateNode(parent, results[0].References); while (results[0].ContinuationPoint != null && results[0].ContinuationPoint.Length > 0) { ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); m_session.BrowseNext( null, parent == null, continuationPoints, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return false; } UpdateNode(parent, results[0].References); } return true; }
/// <summary> /// Invokes the Browse service. /// </summary> /// <param name="requestHeader">The request header.</param> /// <param name="view">The view to browse.</param> /// <param name="nodeToBrowse">The node to browse.</param> /// <param name="maxResultsToReturn">The maximum number of returned values.</param> /// <param name="browseDirection">The browse direction.</param> /// <param name="referenceTypeId">The reference type id.</param> /// <param name="includeSubtypes">If set to <c>true</c> the subtypes of the ReferenceType will be included in the browse.</param> /// <param name="nodeClassMask">The node class mask.</param> /// <param name="continuationPoint">The continuation point.</param> /// <param name="references">The list of node references.</param> /// <returns></returns> public virtual ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, NodeId nodeToBrowse, uint maxResultsToReturn, BrowseDirection browseDirection, NodeId referenceTypeId, bool includeSubtypes, uint nodeClassMask, out byte[] continuationPoint, out ReferenceDescriptionCollection references) { BrowseDescription description = new BrowseDescription(); description.NodeId = nodeToBrowse; description.BrowseDirection = browseDirection; description.ReferenceTypeId = referenceTypeId; description.IncludeSubtypes = includeSubtypes; description.NodeClassMask = nodeClassMask; description.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(description); BrowseResultCollection results; DiagnosticInfoCollection diagnosticInfos; ResponseHeader responseHeader = Browse( requestHeader, view, maxResultsToReturn, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); if (StatusCode.IsBad(results[0].StatusCode)) { throw new ServiceResultException(new ServiceResult(results[0].StatusCode, 0, diagnosticInfos, responseHeader.StringTable)); } continuationPoint = results[0].ContinuationPoint; references = results[0].References; return responseHeader; }
/// <summary> /// Prepares a browse request for the children of a node. /// </summary> /// <param name="nodeId">The node id.</param> /// <param name="nodesToBrowse">The nodes to browse.</param> private int PrepareBrowseElementBrowseRequest( NodeId nodeId, BrowseDescriptionCollection nodesToBrowse) { int index = nodesToBrowse.Count; BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.Organizes; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.BrowseName | BrowseResultMask.NodeClass); nodesToBrowse.Add(nodeToBrowse); nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasChild; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); nodeToBrowse.ResultMask = (uint)(BrowseResultMask.DisplayName | BrowseResultMask.BrowseName | BrowseResultMask.NodeClass); nodesToBrowse.Add(nodeToBrowse); return index; }
/// <summary> /// Browses the specified node. /// </summary> public ReferenceDescriptionCollection Browse(NodeId nodeId) { if (m_session == null) { throw new ServiceResultException(StatusCodes.BadServerNotConnected, "Cannot browse if not connected to a server."); } try { m_browseInProgress = true; // construct request. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = m_browseDirection; nodeToBrowse.ReferenceTypeId = m_referenceTypeId; nodeToBrowse.IncludeSubtypes = m_includeSubtypes; nodeToBrowse.NodeClassMask = m_nodeClassMask; nodeToBrowse.ResultMask = m_resultMask; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // make the call to the server. BrowseResultCollection results; DiagnosticInfoCollection diagnosticInfos; ResponseHeader responseHeader = m_session.Browse( null, m_view, m_maxReferencesReturned, nodesToBrowse, out results, out diagnosticInfos); // ensure that the server returned valid results. Session.ValidateResponse(results, nodesToBrowse); Session.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); // check if valid. if (StatusCode.IsBad(results[0].StatusCode)) { throw ServiceResultException.Create(results[0].StatusCode, 0, diagnosticInfos, responseHeader.StringTable); } // fetch initial set of references. byte[] continuationPoint = results[0].ContinuationPoint; ReferenceDescriptionCollection references = results[0].References; // process any continuation point. while (continuationPoint != null) { ReferenceDescriptionCollection additionalReferences; if (!m_continueUntilDone && m_MoreReferences != null) { BrowserEventArgs args = new BrowserEventArgs(references); m_MoreReferences(this, args); // cancel browser and return the references fetched so far. if (args.Cancel) { BrowseNext(ref continuationPoint, true); return references; } m_continueUntilDone = args.ContinueUntilDone; } additionalReferences = BrowseNext(ref continuationPoint, false); references.AddRange(additionalReferences); } // return the results. return references; } finally { m_browseInProgress = false; } }
/// <summary> /// Gets the list of references to follow. /// </summary> private BrowseDescriptionCollection CreateNodesToBrowse() { BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); if (ReferenceTypeIds != null && ReferenceTypeIds.Length > 0) { for (int ii = 0; ii < ReferenceTypeIds.Length; ii++) { BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = NodeId; nodeToBrowse.BrowseDirection = BrowseDirection; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds[ii]; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; nodesToBrowse.Add(nodeToBrowse); } } else { BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = NodeId; nodeToBrowse.BrowseDirection = BrowseDirection; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.References; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; nodesToBrowse.Add(nodeToBrowse); } return nodesToBrowse; }
/// <summary> /// Browses the node and verifies the results. /// </summary> private bool Browse(Node node, double start, double range) { // watch for circular references. if (m_availableNodes.ContainsKey(node.NodeId)) { return true; } // get the master list of references. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = node.NodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Both; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.References; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); if (!Browse(node, nodeToBrowse, references)) { return false; } // save references. node.Handle = references; // add to dictionary. m_availableNodes.Add(node.NodeId, node); // build list of hierachial targets. List<Node> targets = new List<Node>(); for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; if (!reference.IsForward) { continue; } if (!Session.TypeTree.IsTypeOf(reference.ReferenceTypeId, ReferenceTypeIds.HierarchicalReferences)) { continue; } Node target = Node.Copy(new Node(reference)); targets.Add(target); } // recursively follow sub-tree. if (targets.Count > 0) { double increment = range/targets.Count; double position = start; for (int ii = 0; ii < targets.Count; ii++) { if (range == MaxProgress) { Log("Browsing children of '{0}'. NodeId = {1}", targets[ii], targets[ii].NodeId); } Browse(targets[ii], position, increment); position += increment; ReportProgress(position); } } return true; }
/// <summary> /// Follows hierarchial references from the current node and updates the tree. /// </summary> private void Browse(TreeNode parent) { parent.Nodes.Clear(); ReferenceDescription start = parent.Tag as ReferenceDescription; ListOfBrowseDescription nodesToBrowse = new ListOfBrowseDescription(); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = new NodeId(start.NodeId); nodeToBrowse.BrowseDirection = BrowseDirection.Forward_0; nodeToBrowse.ReferenceTypeId = new NodeId(ReferenceTypes.HierarchicalReferences); nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.ResultMask = (uint)DataTypes.EnumToMask(BrowseResultMask.All_63); nodeToBrowse.NodeClassMask = 0; nodesToBrowse.Add(nodeToBrowse); ListOfBrowseResult results; ListOfDiagnosticInfo diagnosticInfos; m_client.Browse( m_client.CreateRequestHeader(), null, 0, nodesToBrowse, out results, out diagnosticInfos); if (results != null && results.Count > 0) { BrowseResult result = results[0]; if (result.References != null) { foreach (ReferenceDescription reference in result.References) { TreeNode child = new TreeNode(reference.DisplayName.Text); child.Tag = reference; child.Nodes.Add(new TreeNode()); parent.Nodes.Add(child); } } } }
/// <summary> /// 读取一个节点的所有属性 /// </summary> /// <param name="tag">节点信息</param> /// <returns>节点的特性值</returns> public OpcNodeAttribute[] ReadNoteAttributes(string tag) { NodeId sourceId = new NodeId(tag); ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); // attempt to read all possible attributes. // 尝试着去读取所有可能的特性 for (uint ii = Attributes.NodeClass; ii <= Attributes.UserExecutable; ii++) { ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = sourceId; nodeToRead.AttributeId = ii; nodesToRead.Add(nodeToRead); } int startOfProperties = nodesToRead.Count; // find all of the pror of the node. BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.HasProperty; nodeToBrowse1.IncludeSubtypes = true; nodeToBrowse1.NodeClassMask = 0; nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse1); // fetch property references from the server. ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); if (references == null) { return(new OpcNodeAttribute[0]); } for (int ii = 0; ii < references.Count; ii++) { // ignore external references. if (references[ii].NodeId.IsAbsolute) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)references[ii].NodeId; nodeToRead.AttributeId = Attributes.Value; nodesToRead.Add(nodeToRead); } // read all values. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // process results. List <OpcNodeAttribute> nodeAttribute = new List <OpcNodeAttribute>(); for (int ii = 0; ii < results.Count; ii++) { OpcNodeAttribute item = new OpcNodeAttribute(); // process attribute value. if (ii < startOfProperties) { // ignore attributes which are invalid for the node. if (results[ii].StatusCode == StatusCodes.BadAttributeIdInvalid) { continue; } // get the name of the attribute. item.Name = Attributes.GetBrowseName(nodesToRead[ii].AttributeId); // display any unexpected error. if (StatusCode.IsBad(results[ii].StatusCode)) { item.Type = Utils.Format("{0}", Attributes.GetDataTypeId(nodesToRead[ii].AttributeId)); item.Value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); item.Type = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { item.Type += "[]"; } item.Value = results[ii].Value;//Utils.Format("{0}", results[ii].Value); } } // process property value. else { // ignore properties which are invalid for the node. if (results[ii].StatusCode == StatusCodes.BadNodeIdUnknown) { continue; } // get the name of the property. item.Name = Utils.Format("{0}", references[ii - startOfProperties]); // display any unexpected error. if (StatusCode.IsBad(results[ii].StatusCode)) { item.Type = String.Empty; item.Value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); item.Type = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { item.Type += "[]"; } item.Value = results[ii].Value; //Utils.Format("{0}", results[ii].Value); } } nodeAttribute.Add(item); } return(nodeAttribute.ToArray()); }
/// <summary> /// Reads the attribute values in order to compare them to the returned results. /// </summary> private bool VerifyTargetAttributes( Node node, BrowseDescription description, ReferenceDescriptionCollection references) { // check if nothing to do. if (references.Count == 0) { return true; } bool error = false; // build list of values to read. ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; // ignore invalid or external references. if (reference == null || reference.NodeId == null || reference.NodeId.IsAbsolute) { continue; } ReadValueId valueToRead = new ReadValueId(); valueToRead.NodeId = (NodeId)reference.NodeId; valueToRead.AttributeId = Attributes.NodeId; valueToRead.Handle = reference; valuesToRead.Add(valueToRead); if ((description.ResultMask & (uint)BrowseResultMask.NodeClass) != 0) { valueToRead = new ReadValueId(); valueToRead.NodeId = (NodeId)reference.NodeId; valueToRead.AttributeId = Attributes.NodeClass; valueToRead.Handle = reference; valuesToRead.Add(valueToRead); } else { if (reference.NodeClass != 0) { error = true; Log( "Unexpected NodeClass when Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, NodeClass = {3}", node, node.NodeId, reference.NodeId, reference.NodeClass); continue; } } if ((description.ResultMask & (uint)BrowseResultMask.BrowseName) != 0) { valueToRead = new ReadValueId(); valueToRead.NodeId = (NodeId)reference.NodeId; valueToRead.AttributeId = Attributes.BrowseName; valueToRead.Handle = reference; valuesToRead.Add(valueToRead); } else { if (!QualifiedName.IsNull(reference.BrowseName)) { error = true; Log( "Unexpected BrowseName when Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, BrowseName = {3}", node, node.NodeId, reference.NodeId, reference.BrowseName); continue; } } if ((description.ResultMask & (uint)BrowseResultMask.DisplayName) != 0) { valueToRead = new ReadValueId(); valueToRead.NodeId = (NodeId)reference.NodeId; valueToRead.AttributeId = Attributes.DisplayName; valueToRead.Handle = reference; valuesToRead.Add(valueToRead); } else { if (!LocalizedText.IsNullOrEmpty(reference.DisplayName)) { error = true; Log( "Unexpected DisplayName when Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, DisplayName = {3}", node, node.NodeId, reference.NodeId, reference.DisplayName); continue; } } } // halt if errors occured. if (error) { return false; } // read values from server. DataValueCollection results; DiagnosticInfoCollection diagnosticInfos; RequestHeader requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.Read( requestHeader, 0, TimestampsToReturn.Neither, valuesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, valuesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array when Reading Attributes while Browsing Node '{0}'. NodeId = {1}", node, node.NodeId); return false; } for (int ii = 0; ii < valuesToRead.Count; ii++) { if (results[ii].StatusCode != StatusCodes.Good) { error = true; Log( "Could not read {2} when Browsing Node '{0}'. NodeId = {1}, TargetId = {3}, Status = {4}", node, node.NodeId, Attributes.GetBrowseName(valuesToRead[ii].AttributeId), valuesToRead[ii].NodeId, results[ii].StatusCode); continue; } ReferenceDescription reference = (ReferenceDescription)valuesToRead[ii].Handle; if (valuesToRead[ii].AttributeId == Attributes.NodeId) { NodeId expectedId = results[ii].Value as NodeId; if (expectedId != reference.NodeId) { error = true; Log( "Incorrect NodeId Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, reference.NodeId, expectedId, reference.NodeId); } continue; } if (valuesToRead[ii].AttributeId == Attributes.NodeClass) { int? expectedClass = results[ii].Value as int?; if (expectedClass == null || expectedClass.Value != (int)reference.NodeClass) { error = true; Log( "Incorrect NodeClass Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, reference.NodeId, expectedClass, reference.NodeClass); } continue; } if (valuesToRead[ii].AttributeId == Attributes.BrowseName) { QualifiedName expectedName = results[ii].Value as QualifiedName; if (expectedName != reference.BrowseName) { error = true; Log( "Incorrect BrowseName Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, reference.NodeId, expectedName, reference.BrowseName); } continue; } if (valuesToRead[ii].AttributeId == Attributes.DisplayName) { LocalizedText expectedName = results[ii].Value as LocalizedText; if (expectedName != reference.DisplayName) { error = true; Log( "Incorrect DisplayName Browsing Node '{0}'. NodeId = {1}, TargetId = {2}, Expected = {3}, Actual = {4}", node, node.NodeId, reference.NodeId, expectedName, reference.DisplayName); } continue; } } return !error; }