/// <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> /// 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> /// 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> /// Indexes the well known subtypes. /// </summary> private void IndexWellKnownTypes() { SystemContext context = new SystemContext(); context.EncodeableFactory = m_session.MessageContext.Factory; context.NamespaceUris = m_session.NamespaceUris; context.ServerUris = m_session.ServerUris; NodeStateCollection predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Stack.Generated.Opc.Ua.PredefinedNodes.uanodes", typeof(NodeState).Assembly, true); NodeIdDictionary <BaseTypeState> types = new NodeIdDictionary <BaseTypeState>(); // collect the instance declarations for all types. for (int ii = 0; ii < predefinedNodes.Count; ii++) { BaseTypeState type = predefinedNodes[ii] as BaseTypeState; if (type != null) { types.Add(type.NodeId, type); } } // index only those types which are subtypes of BaseEventType. foreach (BaseTypeState type in types.Values) { BaseTypeState subType = type; BaseTypeState superType = null; int eventType = 0; while (subType != null) { if (subType.NodeId == Opc.Ua.ObjectTypeIds.ConditionType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.ConditionType) { eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.AuditEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) { eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.BaseEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) { eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; } // found an event, collect the attribute and index it. if (eventType != 0) { List <AeEventAttribute> declarations = new List <AeEventAttribute>(); Dictionary <string, AeEventAttribute> map = new Dictionary <string, AeEventAttribute>(); ComAeUtils.CollectInstanceDeclarations( m_session, this, type, null, declarations, map); AeEventCategory declaration = new AeEventCategory(); declaration.TypeId = type.NodeId; declaration.SuperTypeId = type.SuperTypeId; declaration.EventType = eventType; declaration.Description = (LocalizedText.IsNullOrEmpty(type.DisplayName))?type.BrowseName.Name:type.DisplayName.Text; declaration.Attributes = declarations; m_eventTypes[declaration.TypeId] = declaration; break; } // follow the tree to the parent. if (!types.TryGetValue(subType.SuperTypeId, out superType)) { break; } subType = superType; } } // hide the built in attributes. AeEventCategory category = GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); if (category != null) { for (int ii = 0; ii < category.Attributes.Count; ii++) { switch (category.Attributes[ii].BrowsePathDisplayText) { case Opc.Ua.BrowseNames.Message: case Opc.Ua.BrowseNames.Severity: case Opc.Ua.BrowseNames.SourceName: case Opc.Ua.BrowseNames.Time: case Opc.Ua.BrowseNames.ReceiveTime: case Opc.Ua.BrowseNames.LocalTime: { category.Attributes[ii].Hidden = true; break; } } } } }