/// <summary> /// Compare method based off the BrowseName /// </summary> /// <param name="x"></param> /// <param name="y"></param> private static int EventCategoryBrowseNameCompare(EventCategory x, EventCategory y) //TODO: should this be a case insensitive compare? { return x.BrowseName.ToLower().CompareTo(y.BrowseName.ToLower()); }
/// <summary> /// Additional new event processing when the received event maps to a (COM AE) condition event type. We need to extract /// the condition name, subcondition name, changeMask, newState, Quality, AckRequired, ActiveTime and cookie. /// </summary> /// <param name="monitoredItem"></param> /// <param name="eventFields"></param> /// <param name="ev"></param> /// <param name="cat"></param> void SetConditionEventFields(MonitoredItem monitoredItem, EventFieldList eventFields, EventNotification ev, EventCategory cat) { LocalizedText localText; String ConditionName; StatusCode? Status; DateTime? TimeOfLastTransition; try { NodeId eventType = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType) as NodeId; // UA events are categorized into three subsets. The first of these subsets consists of types and subtypes of ConditionType // which yields the event condition name, quality and enable/disable status. if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.ConditionType)) { ConditionName = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, Opc.Ua.BrowseNames.ConditionName) as String; if (ConditionName != null) ev.ConditionName = ConditionName; else ev.ConditionName = cat.BrowseName; // Set the subcondition name as conditionname for now. If the event of of type AlarmconditionType and a subcondition (UA substate) // exists then this field will be set accordingly. ev.SubConditionName = ev.ConditionName; bool? enabled = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, "/EnabledState/Id", Attributes.Value) as bool?; Status = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, "/Quality", Attributes.Value) as StatusCode?; ev.Quality = MapStatusToQuality(Status); if (enabled == true) ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED; else ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ENABLED; } // The second of the three UA event subsets consists of types and subtypes of AcknowledgeableconditionType. // This categorization yields events which support acknowledgement in addition to enable/disable state if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AcknowledgeableConditionType)) { bool? acked = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "/AckedState/Id", Attributes.Value) as bool?; // Extract the "ConditionId" (nodeId of the condition instance) ev.ConditionId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "", Attributes.NodeId) as NodeId; ev.AcknowledgeMethod = Opc.Ua.Methods.AcknowledgeableConditionType_Acknowledge; if (acked == true) { ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACKED; ev.AckRequired = false; } else { ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ACKED; ev.AckRequired = true; } } // the third of the three UA event subsets consists of types and subtypes of AlarmConditionType. This // categorization yields events which support the notion of Active/Inactive and also may support substates // (subconditions). if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AlarmConditionType)) { bool? active = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/Id", Attributes.Value) as bool?; TimeOfLastTransition = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/TransitionTime", Attributes.Value) as DateTime?; if (active == true) { ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; ev.ActiveTime = TimeOfLastTransition ?? DateTime.MinValue; } // Active subconditon. localText = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/EffectiveDisplayName", Attributes.Value) as LocalizedText; if (localText != null && localText.ToString() != "") ev.SubConditionName = localText.ToString(); } else // If this is not an AlarmConditionType (thus no UA active/inactive states apply) default to Active ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; } catch (Exception e) { Utils.Trace(e, "Unexpected error in SetConditionEventFields"); } }
/// <summary> /// If this node is not abstract, add it as a category to the EventCategories list /// and process all nodes beneath it as categories. /// Also, add all of its atrributes to the EventAttributes list /// </summary> /// <param name="nodeId">The node being processed</param> /// <param name="CategoryType">The category type id this node will be added as </param> private void ProcessNodeAsCategory(NodeId nodeId, int CategoryType) { try { Node node = m_session.ReadNode(nodeId); EventCategory cat = new EventCategory(); DataValue value = new DataValue(); cat.CategoryID = m_catID++; cat.strNodeId = node.NodeId.ToString(); cat.BrowseName = node.BrowseName.ToString(); cat.EventDesc = node.DisplayName.Text; cat.EventType = CategoryType; m_EventCategories.Add(cat); Browser browse = new Browser(m_session); ReferenceDescriptionCollection references = null; references = browse.Browse(nodeId); foreach (ReferenceDescription reference in references) { if (reference.NodeClass == NodeClass.ObjectType) { ProcessNodeAsCategory((NodeId)reference.NodeId, CategoryType); } else if ((reference.NodeClass == NodeClass.Variable) && (reference.ReferenceTypeId == Opc.Ua.ReferenceTypes.HasProperty)) { ProcessNodeAsAttribute(nodeId, reference); } } } catch (Exception e) { Utils.Trace(e, "Unexpected error in ProcessNodesAsCategory"); } }
/// <summary> /// Compare method based off the BrowseName /// </summary> /// <param name="x"></param> /// <param name="y"></param> private static int EventCategoryDescriptionCompare(EventCategory x, EventCategory y) //TODO: should this be a case insensitive compare? { return x.EventDesc.ToLower().CompareTo(y.EventDesc.ToLower()); }