/// <summary> /// Called when refresh events arrive from the server. /// </summary> /// <param name="events">The events.</param> /// <param name="lastRefresh">if set to <c>true</c> if the refresh is complete.</param> public void OnRefresh(ONEVENTSTRUCT[] events, bool lastRefresh) { lock (m_callbackLock) { // check if refresh was abandoned. if (m_refreshEvents == null) { return; } // dispatch events. for (int ii = 0; ii < events.Length; ii++) { BaseEventState e = DispatchEvent(events[ii]); if (e != null) { m_refreshEvents.Add(e); } } // signal end of refresh. if (lastRefresh) { m_refreshComplete.Set(); } } }
/// <summary> /// Marshals an event for return to the client. /// </summary> private OpcRcw.Ae.ONEVENTSTRUCT Translate(AeEvent e) { OpcRcw.Ae.ONEVENTSTRUCT e2 = new ONEVENTSTRUCT(); e2.wNewState = 0; e2.wChangeMask = 0xFF; e2.szSource = e.SourceName; e2.wQuality = ComUtils.GetQualityCode(e.Quality); e2.dwEventType = e.Category.EventType; e2.dwEventCategory = (int)e.Category.LocalId; e2.bAckRequired = 0; e2.dwSeverity = e.Severity; e2.ftTime = ComUtils.GetFILETIME(e.Time); e2.szMessage = (e.Message != null) ? e.Message.Text : null; e2.szActorID = e.AuditUserId; e2.dwCookie = e.Cookie; if (e.AttributeValues != null && e.AttributeValues.Length > 0) { e2.dwNumEventAttrs = e.AttributeValues.Length; e2.pEventAttributes = ComUtils.GetVARIANTs(e.AttributeValues, true); } if ((e2.dwEventType & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0) { e2.szConditionName = e.ConditionName; e2.ftActiveTime = ComUtils.GetFILETIME(e.ActiveTime); e2.bAckRequired = (e.AckedState)?0:1; // set the condition state. e2.wNewState = 0; if (e.EnabledState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED; } if (e.AckedState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACKED; } if (e.ActiveState) { e2.wNewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE; } // set the subcondition if available. if (!LocalizedText.IsNullOrEmpty(e.LowState)) { e2.szSubconditionName = e.LowState.Text; } if (!LocalizedText.IsNullOrEmpty(e.HighState)) { e2.szSubconditionName = e.HighState.Text; } if (!LocalizedText.IsNullOrEmpty(e.LowLowState)) { e2.szSubconditionName = e.LowLowState.Text; } if (!LocalizedText.IsNullOrEmpty(e.HighHighState)) { e2.szSubconditionName = e.HighHighState.Text; } if (!LocalizedText.IsNullOrEmpty(e.LimitState)) { e2.szSubconditionName = e.LimitState.Text; } } if (e2.szMessage == null) e2.szMessage = String.Empty; if (e2.szSource == null) e2.szSource = String.Empty; if (e2.szConditionName == null) e2.szConditionName = String.Empty; if (e2.szSubconditionName == null) e2.szSubconditionName = String.Empty; if (e2.szActorID == null) e2.szActorID = String.Empty; return e2; }
/// <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 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> /// 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 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 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> /// 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> /// Called when events arrive from the server. /// </summary> /// <param name="events">The events.</param> public void OnEvent(ONEVENTSTRUCT[] events) { for (int ii = 0; ii < events.Length; ii++) { BaseEventState e = DispatchEvent(events[ii]); if (e != null) { lock (m_monitoredItems) { for (int jj = 0; jj < m_monitoredItems.Count; jj++) { m_monitoredItems[jj].QueueEvent(e); } } } } }
/// <summary> /// Called when one or events are produce by the server. /// </summary> public void OnEvent( int hClientSubscription, int bRefresh, int bLastRefresh, int dwCount, ONEVENTSTRUCT[] pEvents) { try { if (bRefresh == 0) { m_subscription.OnEvent(pEvents); } else { m_subscription.OnRefresh(pEvents, bLastRefresh != 0); } } catch (Exception e) { Utils.Trace(e, "Unexpected error processing OnEvent callback."); } }
BaseEventState ConstructEvent(ONEVENTSTRUCT e) { return null; }