private void LoadConditionEvent(ComAeClient client, int eventTypeId, int categoryId, string description, List<EventAttribute> attributes) { string[] conditionNames = null; try { client.GetConditionNames(categoryId, out conditionNames); } catch (Exception e) { Utils.Trace(e, "Unexpected error fetching condition names."); conditionNames = null; } if (conditionNames != null) { // create a condition class for the category. EventType eventType = new EventType(); eventType.EventTypeId = eventTypeId; eventType.CategoryId = categoryId; eventType.Description = description; eventType.ConditionName = null; eventType.SubConditionNames = null; eventType.Attributes = new List<EventAttribute>(); DetermineMapping(eventType); EventTypes.Add(eventType); // create event types for each condition name. for (int ii = 0; ii < conditionNames.Length; ii++) { eventType = new EventType(); eventType.EventTypeId = eventTypeId; eventType.CategoryId = categoryId; eventType.Description = description; eventType.ConditionName = conditionNames[ii]; eventType.SubConditionNames = null; eventType.Attributes = attributes; DetermineMapping(eventType); string[] subConditionNames = null; try { client.GetSubConditionNames(eventType.ConditionName, out subConditionNames); } catch (Exception e) { Utils.Trace(e, "Unexpected error fetching sub-condition names."); subConditionNames = null; } if (subConditionNames != null) { eventType.SubConditionNames = new List<string>(subConditionNames); } EventTypes.Add(eventType); } } }
/// <summary> /// Fetches the event categories for the specified event type. /// </summary> public void LoadEventType(ComAeClient client, int eventTypeId) { int[] ids = null; string[] descriptions = null; try { client.GetEventCategories(eventTypeId, out ids, out descriptions); } catch (Exception e) { Utils.Trace(e, "Unexpected error fetching event categories."); } if (ids != null) { for (int ii = 0; ii < ids.Length; ii++) { List<EventAttribute> attributes = LoadEventAttributes(client, eventTypeId, ids[ii]); if (eventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) { LoadConditionEvent(client, eventTypeId, ids[ii], descriptions[ii], attributes); continue; } EventType eventType = new EventType(); eventType.EventTypeId = eventTypeId; eventType.CategoryId = ids[ii]; eventType.Description = descriptions[ii]; eventType.ConditionName = null; eventType.SubConditionNames = null; eventType.Attributes = attributes; DetermineMapping(eventType); EventTypes.Add(eventType); } } }
/// <summary> /// Uses the recommended names in the AE specification to map to predefined UA event types. /// </summary> private void DetermineMapping(EventType eventType) { for (int ii = 0; ii < eventType.Attributes.Count; ii++) { if (AeTypeCache.IsKnownName(eventType.Attributes[ii].Description, "ACK COMMENT")) { eventType.AckComment = eventType.Attributes[ii]; break; } } eventType.EventTypeMapping = EventTypeMapping.BaseEventType; if (eventType.EventTypeId == OpcRcw.Ae.Constants.SIMPLE_EVENT) { if (AeTypeCache.IsKnownName(eventType.Description, "Device Failure")) { eventType.EventTypeMapping = EventTypeMapping.DeviceFailureEventType; return; } if (AeTypeCache.IsKnownName(eventType.Description, "System Message")) { eventType.EventTypeMapping = EventTypeMapping.SystemEventType; return; } eventType.EventTypeMapping = EventTypeMapping.BaseEventType; return; } if (eventType.EventTypeId == OpcRcw.Ae.Constants.TRACKING_EVENT) { eventType.EventTypeMapping = EventTypeMapping.AuditEventType; return; } if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) { if (eventType.ConditionName == null) { eventType.EventTypeMapping = EventTypeMapping.ConditionClassType; return; } eventType.EventTypeMapping = EventTypeMapping.AlarmConditionType; if (AeTypeCache.IsKnownName(eventType.Description, "Level")) { if (AeTypeCache.IsKnownName(eventType.ConditionName, "PVLEVEL")) { eventType.EventTypeMapping = EventTypeMapping.ExclusiveLevelAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "SPLEVEL")) { eventType.EventTypeMapping = EventTypeMapping.ExclusiveLevelAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "HI HI")) { eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "HI")) { eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "LO")) { eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "LO LO")) { eventType.EventTypeMapping = EventTypeMapping.NonExclusiveLevelAlarmType; return; } eventType.EventTypeMapping = EventTypeMapping.LimitAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.Description, "Deviation")) { eventType.EventTypeMapping = EventTypeMapping.NonExclusiveDeviationAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.Description, "Discrete")) { if (AeTypeCache.IsKnownName(eventType.ConditionName, "CFN")) { eventType.EventTypeMapping = EventTypeMapping.OffNormalAlarmType; return; } if (AeTypeCache.IsKnownName(eventType.ConditionName, "TRIP")) { eventType.EventTypeMapping = EventTypeMapping.TripAlarmType; return; } eventType.EventTypeMapping = EventTypeMapping.DiscreteAlarmType; return; } } }
/// <summary> /// Updates the non-exclusive limit event. /// </summary> private void UpdateNonExclusiveLimitAlarm(NonExclusiveLimitAlarmState instance, EventType eventType, ONEVENTSTRUCT e) { bool active = (e.wNewState & Constants.CONDITION_ACTIVE) != 0; TwoStateVariableState state = null; if (AeTypeCache.IsKnownName(e.szConditionName, "HI HI")) { instance.HighHighState = state = new TwoStateVariableState(instance); instance.HighHighState.BrowseName = Opc.Ua.BrowseNames.HighHighState; } else if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI") || AeTypeCache.IsKnownName(e.szSubconditionName, "DV HI")) { instance.HighState = state = new TwoStateVariableState(instance); instance.HighState.BrowseName = Opc.Ua.BrowseNames.HighState; } else if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO") || AeTypeCache.IsKnownName(e.szSubconditionName, "DV LO")) { instance.LowState = state = new TwoStateVariableState(instance); instance.LowState.BrowseName = Opc.Ua.BrowseNames.LowState; } else if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO LO")) { instance.LowLowState = state = new TwoStateVariableState(instance); instance.LowLowState.BrowseName = Opc.Ua.BrowseNames.LowLowState; } if (state != null) { state.Value = new LocalizedText((active) ? ConditionStateNames.Active : ConditionStateNames.Inactive); state.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, active, false); } }
/// <summary> /// Constructs the NodeId for the specified event type node. /// </summary> internal static NodeId Construct(EventType eventType, string componentPath, ushort namespaceIndex) { StringBuilder buffer = new StringBuilder(); buffer.Append(Utils.ToUInt32(eventType.CategoryId)); if (!String.IsNullOrEmpty(eventType.ConditionName)) { buffer.Append(':'); buffer.Append(eventType.ConditionName); } return Construct(eventType.EventTypeId, buffer.ToString(), componentPath, namespaceIndex); }
/// <summary> /// Updates the exclusive limit alarm event. /// </summary> private void UpdateExclusiveLimitAlarm(ExclusiveLimitAlarmState instance, EventType eventType, ONEVENTSTRUCT e) { NodeId state = null; string text = null; if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI HI")) { state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_HighHigh; text = ConditionStateNames.HighHighActive; } if (AeTypeCache.IsKnownName(e.szSubconditionName, "HI")) { state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_High; text = ConditionStateNames.HighActive; } if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO")) { state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_Low; text = ConditionStateNames.LowActive; } if (AeTypeCache.IsKnownName(e.szSubconditionName, "LO LO")) { state = Opc.Ua.ObjectIds.ExclusiveLimitStateMachineType_LowLow; text = ConditionStateNames.LowLowActive; } instance.LimitState = new ExclusiveLimitStateMachineState(instance); instance.LimitState.BrowseName = Opc.Ua.BrowseNames.LimitState; instance.LimitState.CurrentState = new FiniteStateVariableState(instance.LimitState); instance.LimitState.CurrentState.BrowseName = Opc.Ua.BrowseNames.CurrentState; instance.LimitState.CurrentState.Value = text; instance.LimitState.CurrentState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, state, false); }
/// <summary> /// Updates the condition event. /// </summary> private void UpdateAlarm(AlarmConditionState instance, EventType eventType, ONEVENTSTRUCT e) { instance.NodeId = AeParsedNodeId.ConstructIdForCondition(e.szSource, e.dwEventCategory, e.szConditionName, m_namespaceIndex); // find the condition class. NodeId classId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, null, m_namespaceIndex); AeEventTypeState conditionClassType = m_cache.FindType(m_defaultContext, classId); if (conditionClassType != null) { instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassId, classId, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassName, conditionClassType.EventType.Description, false); } else { instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassId, Opc.Ua.ObjectTypeIds.BaseConditionClassType, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionClassName, "BaseConditionClass", false); } instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ConditionName, e.szConditionName, false); ; instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ClientUserId, e.szActorID, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Quality, ComUtils.GetQualityCode(e.wQuality), false); bool acknowledged = (e.wNewState & Constants.CONDITION_ACKED) != 0; bool active = (e.wNewState & Constants.CONDITION_ACTIVE) != 0; bool enabled = (e.wNewState & Constants.CONDITION_ENABLED) != 0; bool retain = enabled & (active || !acknowledged); LocalizedText effectiveDisplayName = ConditionStateNames.Inactive; if (!enabled) { effectiveDisplayName = ConditionStateNames.Disabled; } else if (!acknowledged) { effectiveDisplayName = ConditionStateNames.Unacknowledged; } else if (active) { effectiveDisplayName = ConditionStateNames.Active; } instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Retain, true, false); instance.EnabledState = new TwoStateVariableState(instance); instance.EnabledState.BrowseName = Opc.Ua.BrowseNames.EnabledState; instance.EnabledState.Value = new LocalizedText((enabled) ? ConditionStateNames.Enabled : ConditionStateNames.Disabled); instance.EnabledState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, enabled, false); instance.EnabledState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EffectiveDisplayName, effectiveDisplayName, false); instance.AckedState = new TwoStateVariableState(instance); instance.AckedState.BrowseName = Opc.Ua.BrowseNames.AckedState; instance.AckedState.Value = new LocalizedText((acknowledged) ? ConditionStateNames.Acknowledged : ConditionStateNames.Unacknowledged); instance.AckedState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, acknowledged, false); instance.ActiveState = new TwoStateVariableState(instance); instance.ActiveState.BrowseName = Opc.Ua.BrowseNames.ActiveState; instance.ActiveState.Value = new LocalizedText((active) ? ConditionStateNames.Active : ConditionStateNames.Inactive); instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Id, active, false); instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.TransitionTime, ComUtils.GetDateTime(e.ftActiveTime), false); if (!String.IsNullOrEmpty(e.szSubconditionName)) { instance.ActiveState.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EffectiveDisplayName, e.szSubconditionName, false); } }
/// <summary> /// Updates the audit event. /// </summary> private void UpdateAuditEvent(AuditEventState instance, EventType eventType, ONEVENTSTRUCT e) { instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ActionTimeStamp, instance.Time.Value, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Status, true, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ServerId, m_defaultContext.NamespaceUris.GetString(m_namespaceIndex), false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ClientUserId, e.szActorID, false); }
/// <summary> /// Updates the base event. /// </summary> private void UpdateBaseEvent(BaseEventState instance, EventType eventType, ONEVENTSTRUCT e) { BinaryEncoder encoder = new BinaryEncoder(ServiceMessageContext.GlobalContext); encoder.WriteString(null, e.szSource); encoder.WriteString(null, e.szConditionName); encoder.WriteInt32(null, e.ftActiveTime.dwHighDateTime); encoder.WriteInt32(null, e.ftActiveTime.dwLowDateTime); encoder.WriteInt32(null, e.dwCookie); byte[] eventId = encoder.CloseAndReturnBuffer(); NodeId eventTypeId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, e.szConditionName, m_namespaceIndex); NodeId sourceNode = AeModelUtils.ConstructIdForSource(e.szSource, null, m_namespaceIndex); string sourceName = e.szSource; DateTime time = ComUtils.GetDateTime(e.ftTime); DateTime receiveTime = DateTime.UtcNow; LocalizedText message = e.szMessage; ushort severity = (ushort)e.dwSeverity; instance.TypeDefinitionId = eventTypeId; instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EventId, eventId, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.EventType, eventTypeId, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.SourceNode, sourceNode, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.SourceName, sourceName, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Time, time, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.ReceiveTime, receiveTime, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Message, message, false); instance.SetChildValue(m_defaultContext, Opc.Ua.BrowseNames.Severity, severity, false); }
/// <summary> /// Initializes a new instance of the <see cref="AeEventTypeState"/> class. /// </summary> public AeEventTypeState(EventType eventType, ushort namespaceIndex) { m_eventType = eventType; // create the name for the event type. string name = eventType.Description; if (!String.IsNullOrEmpty(eventType.ConditionName)) { name = eventType.ConditionName; } if (!name.EndsWith("Type")) { if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) { name += "AlarmType"; } else { name += "EventType"; } } // the attributes. this.NodeId = AeParsedNodeId.Construct(eventType, null, namespaceIndex); this.BrowseName = new QualifiedName(name, namespaceIndex); this.DisplayName = eventType.Description; this.IsAbstract = false; this.SuperTypeId = AeParsedNodeId.Construct(eventType.EventTypeMapping, namespaceIndex); // add the attributes as properties. if (eventType.Attributes != null) { for (int ii = 0; ii < eventType.Attributes.Count; ii++) { string propertyName = eventType.Attributes[ii].Description; if (AeTypeCache.IsKnownName(propertyName, "ACK COMMENT")) { continue; } PropertyState property = new PropertyState(this); property.SymbolicName = propertyName; property.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; property.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; property.ModellingRuleId = Opc.Ua.ObjectIds.ModellingRule_Optional; property.NodeId = AeParsedNodeId.Construct(eventType, propertyName, namespaceIndex); property.BrowseName = new QualifiedName(propertyName, namespaceIndex); property.DisplayName = property.BrowseName.Name; property.AccessLevel = AccessLevels.None; property.UserAccessLevel = AccessLevels.None; property.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; property.Historizing = false; bool isArray = false; property.DataType = ComUtils.GetDataTypeId(eventType.Attributes[ii].VarType, out isArray); property.ValueRank = (isArray) ? ValueRanks.OneDimension : ValueRanks.Scalar; this.AddChild(property); } } }