Stores an event received from the UA server.
        /// <summary>
        /// Finds the category for the event.
        /// </summary>
        private AeEventCategory FindCategory(Session session, AeEvent e)
        {
            AeEventCategory category = m_mapper.GetCategory(e.EventType);

            NodeId subTypeId   = e.EventType;
            NodeId superTypeId = null;

            // follow the type tree if type not recognized.
            while (category == null)
            {
                superTypeId = session.NodeCache.FindSuperType(subTypeId);

                if (!NodeId.IsNull(superTypeId))
                {
                    category = m_mapper.GetCategory(superTypeId);

                    if (category != null)
                    {
                        return(category);
                    }
                }

                subTypeId = superTypeId;
            }

            // default to base event type.
            if (category == null)
            {
                category = m_mapper.GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType);
            }

            return(category);
        }
        /// <summary>
        /// Processes an event (assigns a cookie if acknowledgment is required).
        /// </summary>
        public void ProcessEvent(AeEvent e)
        {
            if (NodeId.IsNull(e.ConditionId))
            {
                return;
            }

            lock (m_lock)
            {
                string conditionId = GetConditionId(e);

                // assign a cookie to the condition/branch.
                int cookie = 0;

                if (!m_cookies.TryGetValue(conditionId, out cookie))
                {
                    cookie = ++m_counter;
                    m_cookies[conditionId] = cookie;
                }

                // remove acked events.
                if (e.AckedState)
                {
                    m_events.Remove(cookie);
                    m_cookies.Remove(conditionId);
                }

                // save event for acking.
                else
                {
                    m_events[cookie] = e;
                    e.Cookie         = cookie;
                }
            }
        }
        /// <summary>
        /// Processes an event (assigns a cookie if acknowledgment is required).
        /// </summary>
        public void ProcessEvent(AeEvent e)
        {
            if (NodeId.IsNull(e.ConditionId))
            {
                return;
            }

            lock (m_lock)
            {
                string conditionId = GetConditionId(e);

                // assign a cookie to the condition/branch.
                int cookie = 0;

                if (!m_cookies.TryGetValue(conditionId, out cookie))
                {
                    cookie = ++m_counter;
                    m_cookies[conditionId] = cookie;
                }

                // remove acked events.
                if (e.AckedState)
                {
                    m_events.Remove(cookie);
                    m_cookies.Remove(conditionId);
                }

                // save event for acking.
                else
                {
                    m_events[cookie] = e;
                    e.Cookie = cookie;
                }
            }
        }
        /// <summary>
        /// Combines the condition id/branch id in a unique identifier.
        /// </summary>
        private string GetConditionId(AeEvent e)
        {
            StringBuilder buffer = new StringBuilder();

            buffer.Append(e.ConditionId);

            if (NodeId.IsNull(e.BranchId))
            {
                buffer.Append(e.BranchId);
            }

            return(buffer.ToString());
        }
        /// <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>
        /// Acknowledges one or more events.
        /// </summary>
        public int[] AcknowledgeEvents(
            Session session,
            string comment,
            string acknowledgerId,
            AeAcknowledgeRequest[] requests)
        {
            if (session == null || !session.Connected)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            StringBuilder buffer = new StringBuilder();

            buffer.Append('[');
            buffer.Append(acknowledgerId);
            buffer.Append(']');

            if (!String.IsNullOrEmpty(comment))
            {
                buffer.Append(comment);
            }

            // wrap the comment once.
            Variant commentToWrite = new Variant(new LocalizedText(buffer.ToString()));

            int[] errors = new int[requests.Length];
            CallMethodRequestCollection methodsToCall = new CallMethodRequestCollection();

            for (int ii = 0; ii < requests.Length; ii++)
            {
                int cookie = requests[ii].Cookie;

                AeEvent e = null;

                lock (m_lock)
                {
                    // look up the event.
                    if (!m_events.TryGetValue(cookie, out e))
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;

                        if (cookie < m_counter)
                        {
                            errors[ii] = ResultIds.S_ALREADYACKED;
                        }

                        continue;
                    }

                    if (e.SourceName != requests[ii].SourceName)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    if (e.ConditionName != requests[ii].ConditionName)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    if (e.ActiveTime != requests[ii].ActiveTime)
                    {
                        errors[ii] = ResultIds.E_INVALIDTIME;
                        continue;
                    }

                    // check that the cookie is still valid.
                    string conditionId    = GetConditionId(e);
                    int    expectedCookie = 0;

                    if (!m_cookies.TryGetValue(conditionId, out expectedCookie))
                    {
                        errors[ii] = ResultIds.S_ALREADYACKED;
                        continue;
                    }

                    // check cookie.
                    if (expectedCookie != cookie)
                    {
                        errors[ii] = ResultIds.E_INVALIDARG;
                        continue;
                    }

                    m_events.Remove(cookie);
                }

                CallMethodRequest request = new CallMethodRequest();
                request.MethodId = Opc.Ua.MethodIds.AcknowledgeableConditionType_Acknowledge;
                request.ObjectId = e.ConditionId;
                request.InputArguments.Add(new Variant(e.EventId));
                request.InputArguments.Add(commentToWrite);
                request.Handle = ii;
                methodsToCall.Add(request);
            }

            if (methodsToCall.Count > 0)
            {
                try
                {
                    // call the server.
                    CallMethodResultCollection results         = null;
                    DiagnosticInfoCollection   diagnosticInfos = null;

                    session.Call(
                        null,
                        methodsToCall,
                        out results,
                        out diagnosticInfos);

                    // verify that the server returned the correct number of results.
                    ClientBase.ValidateResponse(results, methodsToCall);
                    ClientBase.ValidateDiagnosticInfos(diagnosticInfos, methodsToCall);

                    // process results.
                    for (int ii = 0; ii < methodsToCall.Count; ii++)
                    {
                        int index = (int)methodsToCall[ii].Handle;

                        if (StatusCode.IsBad(results[ii].StatusCode))
                        {
                            errors[ii] = ResultIds.E_FAIL;
                            continue;
                        }
                    }
                }
                catch (Exception)
                {
                    // report error.
                    for (int ii = 0; ii < methodsToCall.Count; ii++)
                    {
                        int index = (int)methodsToCall[ii].Handle;
                        errors[ii] = ResultIds.E_FAIL;
                    }
                }
            }

            return(errors);
        }
        /// <summary>
        /// Translates an event notification in an AE event.
        /// </summary>
        public AeEvent TranslateNotification(Session session, EventFieldList e)
        {
            AeEvent e2 = new AeEvent();

            // extract the required event fields.
            int index = 0;

            e2.EventId    = ExtractField <byte[]>(e, index++, null);
            e2.EventType  = ExtractField <NodeId>(e, index++, null);
            e2.SourceName = ExtractField <string>(e, index++, null);
            e2.Time       = ExtractField <DateTime>(e, index++, DateTime.MinValue);
            e2.Message    = ExtractField <LocalizedText>(e, index++, null);
            e2.Severity   = ExtractField <ushort>(e, index++, 0);

            if ((EventTypes & OpcRcw.Ae.Constants.TRACKING_EVENT) != 0)
            {
                e2.AuditUserId = ExtractField <string>(e, index++, null);
            }

            if ((EventTypes & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0)
            {
                e2.BranchId      = ExtractField <byte[]>(e, index++, null);
                e2.ConditionName = ExtractField <string>(e, index++, null);
                e2.Quality       = ExtractField <StatusCode>(e, index++, StatusCodes.Good);
                e2.Comment       = ExtractField <LocalizedText>(e, index++, null);
                e2.CommentUserId = ExtractField <string>(e, index++, null);
                e2.EnabledState  = ExtractField <bool>(e, index++, false);
                e2.AckedState    = ExtractField <bool>(e, index++, false);
                e2.ActiveState   = ExtractField <bool>(e, index++, false);
                e2.ActiveTime    = ExtractField <DateTime>(e, index++, DateTime.MinValue);
                e2.LimitState    = ExtractField <LocalizedText>(e, index++, null);
                e2.HighHighState = ExtractField <LocalizedText>(e, index++, null);
                e2.HighState     = ExtractField <LocalizedText>(e, index++, null);
                e2.LowState      = ExtractField <LocalizedText>(e, index++, null);
                e2.LowLowState   = ExtractField <LocalizedText>(e, index++, null);

                // condition id is always last.
                e2.ConditionId = ExtractField <NodeId>(e, e.EventFields.Count - 1, null);
            }

            // find the category for the event.
            e2.Category = FindCategory(session, e2);

            // extract any additional attributes.
            if (RequestedAttributeIds != null)
            {
                uint[] attributeIds = null;

                if (!RequestedAttributeIds.TryGetValue(e2.Category.LocalId, out attributeIds))
                {
                    return(e2);
                }

                // nothing more to do.
                if (attributeIds == null || attributeIds.Length == 0)
                {
                    return(e2);
                }

                // search for the requested attributes.
                object[] values = new object[attributeIds.Length];

                for (int ii = 0; ii < attributeIds.Length; ii++)
                {
                    // look for matching attribute.
                    for (int jj = 0; jj < SelectedAttributes.Count; jj++)
                    {
                        if (jj >= e.EventFields.Count)
                        {
                            break;
                        }

                        AeEventAttribute attribute = SelectedAttributes[jj];

                        if (attribute == null || attribute.LocalId != attributeIds[ii])
                        {
                            continue;
                        }

                        values[ii] = GetLocalAttributeValue(e.EventFields[jj], attribute);
                    }
                }

                e2.AttributeValues = values;
            }

            return(e2);
        }
        /// <summary>
        /// Combines the condition id/branch id in a unique identifier.
        /// </summary>
        private string GetConditionId(AeEvent e)
        {
            StringBuilder buffer = new StringBuilder();
            buffer.Append(e.ConditionId);

            if (NodeId.IsNull(e.BranchId))
            {
                buffer.Append(e.BranchId);
            }

            return buffer.ToString();
        }
Exemple #9
0
        private void OnEventNotification(Subscription subscription, EventNotificationList notification, IList <string> stringTable)
        {
            try
            {
                // check if disposed.
                if (m_disposed)
                {
                    return;
                }

                // check if session still active.
                Session session = m_server.Session;

                if (session == null || !session.Connected)
                {
                    return;
                }

                // check if events are being reported.
                if (m_callback == null)
                {
                    return;
                }

                lock (m_lock)
                {
                    foreach (EventFieldList e in notification.Events)
                    {
                        // translate the notification and send the response.
                        AeEvent e2 = m_filter.TranslateNotification(m_server.Session, e);

                        if (e2 != null)
                        {
                            // check if refresh has started.
                            if (e2.EventType == Opc.Ua.ObjectTypeIds.RefreshStartEventType)
                            {
                                m_refreshInProgress = true;
                                continue;
                            }

                            // check if refresh has ended.
                            if (e2.EventType == Opc.Ua.ObjectTypeIds.RefreshEndEventType)
                            {
                                m_refreshInProgress = false;

                                // turn off publishing if the subscription is not active,
                                if (!Active)
                                {
                                    m_subscription.SetPublishingMode(false);
                                    List <MonitoredItem> itemsToUpdate = new List <MonitoredItem>(m_notifiers.Values);
                                    m_subscription.SetMonitoringMode(MonitoringMode.Disabled, itemsToUpdate);
                                }

                                if (m_refreshQueue != null)
                                {
                                    ThreadPool.QueueUserWorkItem(DoRefresh, m_refreshQueue);
                                }

                                continue;
                            }

                            // cache any conditions requiring acknowledgement.
                            m_conditionManager.ProcessEvent(e2);

                            // queue on refresh.
                            if (m_refreshInProgress)
                            {
                                if (m_refreshQueue != null)
                                {
                                    m_refreshQueue.Enqueue(e2);
                                }

                                continue;
                            }

                            // queue the event.
                            if (Active)
                            {
                                lock (m_queue)
                                {
                                    m_queue.Enqueue(e2);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Utils.Trace(exception, "Error processing event callback.");
            }
        }
Exemple #10
0
        /// <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);
        }