/// <summary>
        /// Called during incoming event processing and as a result of a client-initiated Refresh.
        /// Forwards to each server instance for further processing.
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="Condition"></param>
        /// <param name="cond"></param>
        public void NotifyClients(string Source, string Condition, OPCCondition cond)
        {
            OnEventClass OEClass = new OnEventClass(Source, Condition, cond);

            foreach (ComAeProxy s in m_EvServerSet)
            {
                s.ProcessNewEvent(OEClass);
            }
        }
        /// <summary>
        /// Force a refresh for all active conditions and inactive, unacknowledged conditions whose event notifications match the filter of the event subscription.
        /// </summary>
        /// <param name="dwConnection">The OLE Connection number returned from IConnectionPoint::Advise. This is passed to help the server determine which OPC event sink to call when the request completes.</param>
        public void Refresh(int dwConnection)
        {
            try
            {
                if (m_RefreshID != 0 || m_RefreshQ.Count != 0)
                {
                    throw ComUtils.CreateComException("Refresh", ResultIds.E_BUSY);
                }

                m_RefreshID = dwConnection;

                // Foe each source walk through all associated conditions. If the condition is "refreshable", i.e. Active or
                // inactive/unacknowledged, then create an event and push it on to the subscription's refresh queue
                SourceMap sourceMap = SourceMap.TheSourceMap;
                foreach (KeyValuePair <string, ConditionMap> kvp in sourceMap)
                {
                    string       sourceName   = kvp.Key;
                    ConditionMap conditionMap = kvp.Value;
                    foreach (KeyValuePair <string, OPCCondition> kvpCond in conditionMap)
                    {
                        string       conditionName = kvpCond.Key;
                        OPCCondition cond          = kvpCond.Value;

                        if (cond.IsEnabled() && (cond.IsActive() || !cond.IsAcked()))
                        {
                            OnEventClass OEClass = new OnEventClass(sourceName, conditionName, cond);
                            if (MatchesFilter(OEClass))
                            {
                                m_RefreshQ.Enqueue(OEClass);
                            }
                        }
                    }
                }

                if (m_RefreshQ.Count > 0)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null);
                }
                else
                {
                    CancelRefresh(dwConnection);
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in Refresh");
                throw ComUtils.CreateComException(e);
            }
        }
        /// <summary>
        /// If the event type is CONDITION_EVENT then update any existing record of the condition and adjust
        /// state and change mask.
        /// </summary>
        /// <param name="EventNotification"></param>
        /// <param name="areas"></param>
        public void ProcessEventNotificationList(EventNotification EventNotification, string[] areas)
        {
            SourceMap sourceMap = SourceMap.TheSourceMap;

            try
            {
                lock (sourceMap)
                {
                    OPCCondition cond;
                    if (EventNotification.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT)
                    {
                        ConditionMap conditionMap;
                        if (sourceMap.TryGetValue(EventNotification.SourceID, out conditionMap) == false)
                        {
                            conditionMap = new ConditionMap();
                            sourceMap.Add(EventNotification.SourceID, conditionMap);
                        }

                        if (conditionMap.TryGetValue(EventNotification.ConditionName, out cond) == false)
                        {
                            cond           = new OPCCondition();
                            cond.EventType = EventNotification.EventType;
                            conditionMap.Add(EventNotification.ConditionName, cond);
                        }

                        ProcessCondition(EventNotification, areas, cond);

                        // When the condition has transitioned to Acked (if ack required) and inactive or disabled
                        // then remove it from the condition source/condition database
                        if ((!cond.IsActive() || !cond.IsEnabled()) && (cond.IsAcked() || !cond.AckRequired))
                        {
                            conditionMap.Remove(EventNotification.ConditionName);
                        }
                    }
                    else  // a tracking or simple event
                    {
                        cond           = new OPCCondition();
                        cond.EventType = EventNotification.EventType;
                        ProcessCondition(EventNotification, areas, cond);
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in ProcessEventNotificationList");
            }
        }
Exemple #4
0
        /// <summary>
        /// Constructor -- initializes all members
        /// </summary>
        /// <param name="wszSource"></param>
        /// <param name="wszCondition"></param>
        /// <param name="cond"></param>
        public OnEventClass(string wszSource, string wszCondition, OPCCondition cond)
        {
            m_oes.pEventAttributes   = IntPtr.Zero;
            m_oes.dwNumEventAttrs    = 0;
            m_oes.wChangeMask        = cond.ChangeMask;
            m_oes.wNewState          = cond.NewState;
            m_oes.szSource           = wszSource;
            m_oes.ftTime             = ComUtils.GetFILETIME(cond.Time);
            m_oes.szMessage          = cond.Message;
            m_oes.dwEventType        = cond.EventType;
            m_oes.dwEventCategory    = cond.EventCategory;
            m_oes.dwSeverity         = cond.Severity;
            m_oes.szConditionName    = wszCondition;
            m_oes.szSubconditionName = cond.SubconditionName;
            m_oes.wQuality           = cond.Quality;
            m_oes.bAckRequired       = cond.AckRequired ?1:0;
            m_oes.ftActiveTime       = ComUtils.GetFILETIME(cond.SubconditionTime);
            m_oes.dwCookie           = cond.Cookie;
            m_oes.szActorID          = cond.ActorID;

            m_EventAttributes = (Dictionary <int, object>)DeepCopy(cond.EventAttributes);
        }
        /// <summary>
        /// Values of existing CONDITION events are updated the forwarded to TheGlobal for further processing
        /// per subscription per server instance
        /// </summary>
        /// <param name="EventNotification"></param>
        /// <param name="areas"></param>
        /// <param name="newCond"></param>
        private void ProcessCondition(EventNotification EventNotification, string[] areas, OPCCondition newCond)
        {
            try
            {
                newCond.ClearChangeMask();
                newCond.SetMessage(EventNotification.Message);
                newCond.SetSeverity(EventNotification.Severity);
                newCond.SetSubconditionName(EventNotification.SubConditionName);
                newCond.SetActive((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ACTIVE) != 0);

                // The UA server generates unique identifiers in the form of guids.  how to map these to COM-style cookies?
                // For now, just increment a static DWORD counter from the OPCCondition constructor and assign
                //newCond.Cookie = EventNotification.Cookie;

                newCond.SetTime(EventNotification.ActiveTime);
                newCond.EventId       = EventNotification.EventId;
                newCond.EventCategory = EventNotification.EventCategory;
                newCond.SetQuality((short)EventNotification.Quality);
                newCond.ActorID = EventNotification.EventType == OpcRcw.Ae.Constants.TRACKING_EVENT ? EventNotification.ActorID : "";
                newCond.SetEnable((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ENABLED) != 0);
                newCond.SetIsAcked((EventNotification.NewState & OpcRcw.Ae.Constants.CONDITION_ACKED) != 0);
                newCond.SetAckRequired(EventNotification.AckRequired);
                newCond.ConditionId       = EventNotification.ConditionId;
                newCond.AcknowledgeMethod = EventNotification.AcknowledgeMethod;

                OPCSubcondition subCond = new OPCSubcondition(newCond.SubconditionName, newCond.Message, "", newCond.Severity);
                newCond.push_back_subcondition(subCond);

                for (int i = 0; i < areas.Length; i++)
                {
                    newCond.push_back_area(areas[i]);
                }

                // Insert standard attribute "AckComment"
                newCond.push_back_attrval(Global.TheGlobal.StdAttrIds[0], newCond.AckComment);
                // Insert standard attribute "Areas"
                newCond.push_back_attrval(Global.TheGlobal.StdAttrIds[1], areas);

                foreach (KeyValuePair <int, object> kvp in EventNotification.EventAttributes)
                {
                    newCond.push_back_attrval(kvp.Key, kvp.Value);
                }

                if (newCond.IsEnabled())
                {
                    lock (Global.TheGlobal)
                    {
                        Global.TheGlobal.NotifyClients(EventNotification.SourceID, EventNotification.ConditionName, newCond);
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in ProcessCondition");
            }

            // Utils.Trace("ProcessCondition - END Source: {0}, condition: {1}, conditionstate: {2}",
            // EventNotification.SourceID, EventNotification.ConditionName, newCond.NewState);
        }