/// <summary>
        /// Initializes a COM-patible ONEVENTSTRUCT ready to be sent to subscribing clients
        /// </summary>
        /// <param name="oes"></param>
        /// <param name="pOnEventClass"></param>
        private void CopyToOnEventStruct(ref ONEVENTSTRUCT oes, OnEventClass pOnEventClass)
        {
            try
            {
                oes = pOnEventClass.InternalOES;

                ReturnedAttributeList attrIds;
                if (m_ReturnedAttributes.TryGetValue(oes.dwEventCategory, out attrIds) == true)
                {
                    int      retAttrCount = attrIds.Count;
                    int      i            = 0;
                    object[] attrVals     = new object[retAttrCount];

                    foreach (int attrId in attrIds)
                    {
                        attrVals[i++] = pOnEventClass.EventAttributes[attrId];
                    }

                    oes.dwNumEventAttrs  = retAttrCount;
                    oes.pEventAttributes = ComUtils.GetVARIANTs(attrVals, false);
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in CopyToOnEventStruct");
            }
        }
Example #2
0
        /// <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>
        /// Determines whether the newly received event matches the filter applied to this
        /// subscription.
        /// </summary>
        /// <param name="pOnEventClass"></param>
        /// <returns></returns>
        private bool MatchesFilter(OnEventClass pOnEventClass)
        {
            bool FilterMatches = true;

            try
            {
                if (System.Convert.ToBoolean(m_dwEventType & pOnEventClass.InternalOES.dwEventType) == false)
                {
                    FilterMatches = false;
                }

                if (m_EventCategoryVector.Count != 0)
                {
                    if (m_EventCategoryVector.Contains(pOnEventClass.InternalOES.dwEventCategory) == false)
                    {
                        FilterMatches = false;
                    }
                }

                if (pOnEventClass.InternalOES.dwSeverity <m_dwLowSeverity | pOnEventClass.InternalOES.dwSeverity> m_dwHighSeverity)
                {
                    FilterMatches = false;
                }

                if (m_AreaVector.Count != 0)
                {
                    if (pOnEventClass.EventAttributes.Count > 0)
                    {
                        string[] areas = (string[])pOnEventClass.EventAttributes[1];
                        foreach (string area in areas)
                        {
                            if (m_AreaVector.Contains(area) == true)
                            {
                                FilterMatches = true;
                                break;
                            }
                            FilterMatches = false;
                        }
                    }
                }

                if (m_SourceVector.Count != 0)
                {
                    if (m_SourceVector.Contains(pOnEventClass.InternalOES.szSource) == false)
                    {
                        FilterMatches = false;
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in MatchesFilter");
                FilterMatches = false;
            }
            return(FilterMatches);
        }
        /// <summary>
        /// If the subscription filter allows the event then enqueue the event
        /// and assign a threadpool worker to handle the subscription callback
        /// </summary>
        /// <param name="pOnEventClass"></param>
        public void ProcessNewEvent(OnEventClass pOnEventClass)
        {
            lock (m_csData)
            {
                try
                {
                    if (m_bActive == true)
                    {
                        // compare to my filter, if it matches
                        if (MatchesFilter(pOnEventClass))
                        {
                            m_OnEventQ.Enqueue(pOnEventClass);
                        }

                        // Just a keep-alive event?
                        else if ((pOnEventClass.InternalOES.szSource == null) && (pOnEventClass.InternalOES.szConditionName == null))
                        {
                            m_KeepAliveQ.EnqueueIfEmpty(pOnEventClass);
                        }

                        // Even if this event was filtered out, check to see if it
                        // is time to send anything that is already in my queue.
                        if (m_OnEventQ.Count > 0)
                        {
                            TimeSpan bufferTime = TimeSpan.FromMilliseconds(m_dwBufferTime);
                            DateTime lastUpdate = m_LastUpdateTime;
                            DateTime nextUpdate = lastUpdate + bufferTime;

                            if (m_OnEventQ.Count >= m_dwMaxSize || nextUpdate <= DateTime.Now)
                            {
                                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null);
                            }
                        }

                        // No "real events" to send ... is it time to send a keep alive (keepalive of 0 means disabled) ?
                        else if ((m_KeepAliveQ.Count > 0) && (m_KeepAliveTime != 0))
                        {
                            TimeSpan bufferTime = TimeSpan.FromMilliseconds(m_KeepAliveTime);
                            DateTime lastUpdate = m_LastUpdateTime;
                            if (DateTime.Now >= (lastUpdate + bufferTime))
                            {
                                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), null);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error in ProcessNewEvent");
                }
            }
        }
        /// <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);
            }
        }