/// <summary> /// Finds the category for the event. /// </summary> private AeEventCategory FindCategory(Session session, AeEvent e) { AeEventCategory category = m_mapper.GetCategory(e.EventType); NodeId subTypeId = e.EventType; NodeId superTypeId = null; // follow the type tree if type not recognized. while (category == null) { superTypeId = session.NodeCache.FindSuperType(subTypeId); if (!NodeId.IsNull(superTypeId)) { category = m_mapper.GetCategory(superTypeId); if (category != null) { return(category); } } subTypeId = superTypeId; } // default to base event type. if (category == null) { category = m_mapper.GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); } return(category); }
/// <summary> /// Checks if a supertype was already selected. /// </summary> private bool IsSuperTypeSelected(AeEventCategory category, uint[] categoryIds) { AeEventCategory subType = category; AeEventCategory superType = null; while (subType != null) { superType = m_mapper.GetCategory(subType.SuperTypeId); if (superType == null) { return(false); } for (int ii = 0; ii < categoryIds.Length; ii++) { if (categoryIds[ii] == superType.LocalId) { return(true); } } subType = superType; } return(false); }
/// <summary> /// Returns the category with the specified event type id. /// </summary> public AeEventCategory GetCategory(NodeId typeId) { AeEventCategory category = null; if (!this.m_eventTypes.TryGetValue(typeId, out category)) { return(null); } return(category); }
/// <summary> /// Returns the category with the specified category id. /// </summary> public AeEventCategory GetCategory(uint categoryId) { AeEventCategory category = null; if (!m_categories.TryGetValue(categoryId, out category)) { return(null); } return(category); }
/// <summary> /// Uses the description to compare two categories. /// </summary> private static int CompareCategories(AeEventCategory x, AeEventCategory y) { if (Object.ReferenceEquals(x, y)) { return(0); } if (Object.ReferenceEquals(x, null)) { return((Object.ReferenceEquals(y, null))?0:-1); } return(x.Description.CompareTo(y.Description)); }
/// <summary> /// Sets the categories. /// </summary> public void SetFilter(int eventTypes, ushort lowSeverity, ushort highSeverity, uint[] categoryIds, List <NodeId> sources) { RevisedCategories = new List <AeEventCategory>(); // update list of sources. SelectedSources = new List <NodeId>(); if (sources != null) { SelectedSources.AddRange(sources); } for (int ii = 0; categoryIds != null && ii < categoryIds.Length; ii++) { AeEventCategory category = m_mapper.GetCategory(categoryIds[ii]); // ignore unknown categories. if (category == null) { continue; } // ignore categories if the event types mask filters them out. if ((category.EventType & eventTypes) == 0) { continue; } // add category. RevisedCategories.Add(category); } // save the original ids. EventTypes = eventTypes; LowSeverity = lowSeverity; HighSeverity = highSeverity; RequestedCategoryIds = categoryIds; // update selected attributes. UpdatedSelectAttributes(); }
/// <summary> /// Gets the list of categories for the specified event types. /// </summary> public List <AeEventAttribute> GetAttributes(uint categoryId) { AeEventCategory category = null; if (!m_categories.TryGetValue(categoryId, out category)) { return(null); } List <AeEventAttribute> attributes = new List <AeEventAttribute>(); AeEventCategory subType = category; while (subType != null) { for (int ii = 0; ii < subType.Attributes.Count; ii++) { AeEventAttribute attribute = subType.Attributes[ii]; if (attribute.OverriddenDeclaration == null) { if (!attribute.Hidden) { attributes.Add(attribute); } } } AeEventCategory superType = null; if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType)) { break; } subType = superType; } attributes.Sort(CompareAttributes); return(attributes); }
/// <summary> /// Returns the attribute with the specified event type id and browse path. /// </summary> public AeEventAttribute GetAttribute(NodeId typeId, params string[] browseNames) { AeEventCategory category = null; if (!this.m_eventTypes.TryGetValue(typeId, out category)) { return(null); } StringBuilder buffer = new StringBuilder(); if (browseNames != null) { for (int ii = 0; ii < browseNames.Length; ii++) { if (buffer.Length > 0) { buffer.Append('/'); } buffer.Append(browseNames[ii]); } } string targetPath = buffer.ToString(); if (!String.IsNullOrEmpty(targetPath)) { for (int ii = 0; ii < category.Attributes.Count; ii++) { if (category.Attributes[ii].BrowsePathDisplayText == targetPath) { return(category.Attributes[ii]); } } } return(null); }
/// <summary> /// Assigns a locally unique numeric id to each event type. /// </summary> private void UpdateEventAttributeMappings(NodeIdMappingSet mappingSet) { NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); // collect all unique declarations. List <AeEventAttribute> list = new List <AeEventAttribute>(); foreach (AeEventCategory type in m_eventTypes.Values) { for (int ii = 0; ii < type.Attributes.Count; ii++) { AeEventAttribute declaration = type.Attributes[ii]; // only variables can be attributes. if (declaration.NodeClass != NodeClass.Variable) { continue; } // need to link attributes to any attributes that they override. AeEventCategory subType = type; AeEventCategory superType = null; while (subType != null) { if (NodeId.IsNull(subType.SuperTypeId) || subType.TypeId == subType.SuperTypeId || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseObjectType) { list.Add(declaration); break; } if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType)) { break; } for (int jj = 0; jj < superType.Attributes.Count; jj++) { if (superType.Attributes[jj].BrowsePathDisplayText == declaration.BrowsePathDisplayText) { declaration.OverriddenDeclaration = superType.Attributes[jj]; declaration = declaration.OverriddenDeclaration; break; } } subType = superType; } } } // look up ids for all attributes in master list. Dictionary <uint, AeEventAttribute> attributes = new Dictionary <uint, AeEventAttribute>(); for (int ii = 0; ii < list.Count; ii++) { AeEventAttribute declaration = list[ii]; for (int jj = 0; jj < mappingSet.Mappings.Count; jj++) { NodeIdMapping mapping = mappingSet.Mappings[jj]; try { // browse display paths always use local namespa indexes. if (declaration.BrowsePathDisplayText != mapping.BrowePath) { continue; } // need to convert the cached type id to a remote id. NodeId localId = NodeId.Parse(mapping.NodeId); NodeId remoteId = this.GetRemoteNodeId(localId); if (declaration.RootTypeId != remoteId) { continue; } // must update the saved integer id. if (!attributes.ContainsKey(mapping.IntegerId)) { declaration.LocalId = mapping.IntegerId; attributes[declaration.LocalId] = declaration; mappingsToKeep.Add(mapping); } // must assign a new one if a duplicate found. else { declaration.LocalId = 0; } } catch (Exception) { // ignore invalid mappings. } } } // assign new ids. uint nextId = 1; for (int ii = 0; ii < list.Count; ii++) { AeEventAttribute declaration = list[ii]; if (declaration.LocalId == 0) { // find a unique id. while (attributes.ContainsKey(nextId)) { nextId++; } // assign the id. declaration.LocalId = nextId; attributes[declaration.LocalId] = declaration; // save the mapping. NodeIdMapping mapping = new NodeIdMapping(); mapping.IntegerId = nextId; mapping.NodeId = this.GetLocalNodeId(declaration.RootTypeId).ToString(); mapping.BrowePath = declaration.BrowsePathDisplayText; mappingsToKeep.Add(mapping); } } // update mapping set. mappingSet.Mappings = mappingsToKeep; m_attributes = attributes; }
/// <summary> /// Assigns a locally unique numeric id to each event type. /// </summary> private void UpdateEventTypeMappings(NodeIdMappingSet mappingSet) { NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); Dictionary <uint, AeEventCategory> categories = new Dictionary <uint, AeEventCategory>(); for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) { NodeIdMapping mapping = mappingSet.Mappings[ii]; try { // need to convert the cached type id to a remote id. NodeId localId = NodeId.Parse(mapping.NodeId); NodeId remoteId = this.GetRemoteNodeId(localId); AeEventCategory eventType = null; if (m_eventTypes.TryGetValue(remoteId, out eventType)) { // check if the event already has an id. if (eventType.LocalId == 0) { // must update the saved integer id. if (!categories.ContainsKey(mapping.IntegerId)) { eventType.LocalId = mapping.IntegerId; categories[eventType.LocalId] = eventType; mappingsToKeep.Add(mapping); } // must assign a new one if a duplicate found. else { eventType.LocalId = 0; } } } } catch (Exception) { // discard invalid mappings. } } // assign ids to any types which do not have mappings. uint nextId = 1; foreach (AeEventCategory eventType in m_eventTypes.Values) { if (eventType.LocalId == 0) { // find a unique id. while (categories.ContainsKey(nextId)) { nextId++; } // assign the id. eventType.LocalId = nextId; categories[eventType.LocalId] = eventType; // save the mapping. NodeIdMapping mapping = new NodeIdMapping(); mapping.IntegerId = nextId; mapping.NodeId = this.GetLocalNodeId(eventType.TypeId).ToString(); mappingsToKeep.Add(mapping); } } // update mappings. mappingSet.Mappings = mappingsToKeep; m_categories = categories; }
/// <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> /// 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; } } } } }
/// <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> /// 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; } } } } }
/// <summary> /// Uses the description to compare two categories. /// </summary> private static int CompareCategories(AeEventCategory x, AeEventCategory y) { if (Object.ReferenceEquals(x, y)) { return 0; } if (Object.ReferenceEquals(x, null)) { return (Object.ReferenceEquals(y, null))?0:-1; } return x.Description.CompareTo(y.Description); }