/// <summary> /// Updates the type cache. /// </summary> private void DoMetadataUpdate(object state) { try { if (!Server.IsRunning) { return; } ComAeClientManager system = (ComAeClientManager)SystemContext.SystemHandle; ComAeClient client = (ComAeClient)system.SelectClient(SystemContext, true); AeTypeCache cache = new AeTypeCache(); cache.LoadEventTypes(client); lock (Lock) { if (m_typeCache == null) { m_typeCache = cache; } m_typeCache.EventTypes = cache.EventTypes; m_typeCache.UpdateCache(SystemContext, NamespaceIndex); } } catch (Exception e) { Utils.Trace(e, "Unexpected error updating event type cache."); } }
/// <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> /// Initializes a new instance of the <see cref="ComAeSubscriptionClient"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="configuration">The configuration.</param> /// <param name="cache">The cache for known types.</param> /// <param name="namespaceIndex">The namespace index for the event types.</param> /// <param name="manager">The manager.</param> /// <param name="monitoredItem">The monitored item.</param> public ComAeSubscriptionClient( ServerSystemContext context, ComAeClientConfiguration configuration, AeTypeCache cache, ushort namespaceIndex, ComAeClientManager manager, MonitoredItem monitoredItem) { m_defaultContext = context; m_separators = configuration.SeperatorChars; m_cache = cache; m_namespaceIndex = namespaceIndex; m_manager = manager; m_refreshComplete = new ManualResetEvent(false); m_monitoredItems = new List <MonitoredItem>(); m_monitoredItems.Add(monitoredItem); m_qualifiedName = null; m_isSource = false; NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; AeAreaState area = handle.Node as AeAreaState; if (area != null) { m_qualifiedName = area.QualifiedName; m_isSource = false; } else { AeSourceState source = handle.Node as AeSourceState; if (source != null) { m_qualifiedName = source.QualifiedName; m_isSource = true; } } }
/// <summary> /// Initializes a new instance of the <see cref="ComAeSubscriptionClient"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="configuration">The configuration.</param> /// <param name="cache">The cache for known types.</param> /// <param name="namespaceIndex">The namespace index for the event types.</param> /// <param name="manager">The manager.</param> /// <param name="monitoredItem">The monitored item.</param> public ComAeSubscriptionClient( ServerSystemContext context, ComAeClientConfiguration configuration, AeTypeCache cache, ushort namespaceIndex, ComAeClientManager manager, MonitoredItem monitoredItem) { m_defaultContext = context; m_separators = configuration.SeperatorChars; m_cache = cache; m_namespaceIndex = namespaceIndex; m_manager = manager; m_refreshComplete = new ManualResetEvent(false); m_monitoredItems = new List<MonitoredItem>(); m_monitoredItems.Add(monitoredItem); m_qualifiedName = null; m_isSource = false; NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; AeAreaState area = handle.Node as AeAreaState; if (area != null) { m_qualifiedName = area.QualifiedName; m_isSource = false; } else { AeSourceState source = handle.Node as AeSourceState; if (source != null) { m_qualifiedName = source.QualifiedName; m_isSource = true; } } }
/// <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> /// 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); } } }
/// <summary> /// Dispatches the event. /// </summary> private BaseEventState DispatchEvent(ONEVENTSTRUCT e) { NodeId typeId = AeParsedNodeId.Construct(e.dwEventType, e.dwEventCategory, e.szConditionName, m_namespaceIndex); // find the type. AeEventTypeState eventType = m_cache.FindType(m_defaultContext, typeId); if (eventType == null) { return(null); } // create a new instance. BaseEventState instance = m_cache.CreateInstance(m_defaultContext, eventType); if (instance == null) { return(null); } // fill in fields. UpdateBaseEvent(instance, eventType.EventType, e); if (instance is AuditEventState) { UpdateAuditEvent((AuditEventState)instance, eventType.EventType, e); } if (instance is AlarmConditionState) { UpdateAlarm((AlarmConditionState)instance, eventType.EventType, e); } if (instance is ExclusiveLimitAlarmState) { UpdateExclusiveLimitAlarm((ExclusiveLimitAlarmState)instance, eventType.EventType, e); } else if (instance is NonExclusiveLimitAlarmState) { UpdateNonExclusiveLimitAlarm((NonExclusiveLimitAlarmState)instance, eventType.EventType, e); } // process attributes. bool ackCommentFound = false; object[] values = ComUtils.GetVARIANTs(ref e.pEventAttributes, e.dwNumEventAttrs, false); for (int ii = 0; ii < eventType.EventType.Attributes.Count; ii++) { EventAttribute attribute = eventType.EventType.Attributes[ii]; if (ii >= e.dwNumEventAttrs) { continue; } if (!ackCommentFound && AeTypeCache.IsKnownName(attribute.Description, "ACK COMMENT")) { ConditionState condition = instance as ConditionState; if (condition != null) { condition.Comment = new ConditionVariableState <LocalizedText>(condition); condition.Comment.BrowseName = Opc.Ua.BrowseNames.Comment; condition.Comment.Value = new LocalizedText(values[ii] as string); } ackCommentFound = true; continue; } PropertyState property = new PropertyState(instance); property.SymbolicName = attribute.Description; property.BrowseName = new QualifiedName(property.SymbolicName, m_namespaceIndex); property.Value = values[ii]; instance.AddChild(property); } return(instance); }
/// <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; } } }