Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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");
            }
        }
Esempio n. 3
0
        /// <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");
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Somewhat simplistic logic to extract the containing area associated with a received event.  Just parse the
        /// source path and assume the final token is the unqualified source while the remainder of the string is the area
        /// path.
        /// </summary>
        /// <param name="ev"></param>
        /// <returns></returns>
        string[] FindEventAreas(EventNotification ev)
        {
            try
            {
                QualifiedNameCollection browseNames = SimpleAttributeOperand.Parse(ev.SourceID);
                String areaString = "/";

                if (browseNames.Count > 0)
                {
                    for (int i = 0; i < browseNames.Count - 1; i++)
                    {
                        areaString += browseNames[i];
                        areaString += "/";
                    }
                }
                return new string[] { areaString };
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in FindEventAreas");
                return null;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Additional new event processing when the received event maps to a (COM AE) condition event type.  We need to extract
        /// the condition name, subcondition name, changeMask, newState, Quality, AckRequired, ActiveTime and cookie.
        /// </summary>
        /// <param name="monitoredItem"></param>
        /// <param name="eventFields"></param>
        /// <param name="ev"></param>
        /// <param name="cat"></param>
        void SetConditionEventFields(MonitoredItem monitoredItem, EventFieldList eventFields, EventNotification ev, EventCategory cat)
        {
            LocalizedText localText;
            String ConditionName;
            StatusCode? Status;
            DateTime? TimeOfLastTransition;

            try
            {
                NodeId eventType = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType) as NodeId;

                // UA events are categorized into three subsets.  The first of these subsets consists of types and subtypes of ConditionType
                // which yields the event condition name, quality and enable/disable status.
                if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.ConditionType))
                {
                    ConditionName = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, Opc.Ua.BrowseNames.ConditionName) as String;
                    if (ConditionName != null)
                        ev.ConditionName = ConditionName;
                    else
                        ev.ConditionName = cat.BrowseName;

                    // Set the subcondition name as conditionname for now.  If the event of of type AlarmconditionType and a subcondition (UA substate)
                    // exists then this field will be set accordingly.
                    ev.SubConditionName = ev.ConditionName;

                    bool? enabled = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType,
                        "/EnabledState/Id", Attributes.Value) as bool?;

                    Status = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType,
                        "/Quality", Attributes.Value) as StatusCode?;

                    ev.Quality = MapStatusToQuality(Status);

                    if (enabled == true)
                        ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ENABLED;
                    else
                        ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ENABLED;
                }

                // The second of the three UA event subsets consists of types and subtypes of AcknowledgeableconditionType.
                // This categorization yields events which support acknowledgement in addition to enable/disable state
                if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AcknowledgeableConditionType))
                {
                    bool? acked = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType,
                        "/AckedState/Id", Attributes.Value) as bool?;

                    // Extract the "ConditionId" (nodeId of the condition instance)
                    ev.ConditionId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AcknowledgeableConditionType,
                        "", Attributes.NodeId) as NodeId;

                    ev.AcknowledgeMethod = Opc.Ua.Methods.AcknowledgeableConditionType_Acknowledge;
                    
                    if (acked == true)
                    {
                        ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACKED;
                        ev.AckRequired = false;
                    }
                    else
                    {
                        ev.NewState &= ~OpcRcw.Ae.Constants.CONDITION_ACKED;
                        ev.AckRequired = true;
                    }

                }

                // the third of the three UA event subsets consists of types and subtypes of AlarmConditionType.  This
                // categorization yields events which support the notion of Active/Inactive and also may support substates
                // (subconditions).
                if (m_session.TypeTree.IsTypeOf(eventType, Opc.Ua.ObjectTypes.AlarmConditionType))
                {
                    bool? active = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType,
                        "/ActiveState/Id", Attributes.Value) as bool?;

                    TimeOfLastTransition = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType,
                        "/ActiveState/TransitionTime", Attributes.Value) as DateTime?;

                    if (active == true)
                    {
                        ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE;
                        ev.ActiveTime = TimeOfLastTransition ?? DateTime.MinValue;
                    }

                    // Active subconditon. 
                    localText = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.AlarmConditionType,
                        "/ActiveState/EffectiveDisplayName", Attributes.Value) as LocalizedText;
                    if (localText != null && localText.ToString() != "")
                        ev.SubConditionName = localText.ToString();
                }
                else // If this is not an AlarmConditionType (thus no UA active/inactive states apply) default to Active
                    ev.NewState |= OpcRcw.Ae.Constants.CONDITION_ACTIVE;
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error in SetConditionEventFields");
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Processes a Publish response from the UA server.
        /// </summary>
        /// <param name="monitoredItem"></param>
        /// <param name="e"></param>
        void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
        {
            try
            {
                EventFieldList eventFields = e.NotificationValue as EventFieldList;

                if (eventFields == null)
                {
                    return;
                }
                if (monitoredItem != null)
                {
                    if (monitoredItem.ClientHandle != eventFields.ClientHandle)
                    {
                        return;
                    }
                }
                INode eventUA = monitoredItem.GetEventType(eventFields);
                EventCategory cat = FindEventCatInfo(eventUA.BrowseName.ToString());

                if (cat == null) return; // The event is not of a category that we recognize.
           
                if (cat.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT)
                {
                    NodeId branchId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.ConditionType, Opc.Ua.BrowseNames.BranchId) as NodeId;
                    if (!NodeId.IsNull(branchId)) return; // We don't support condition branches in the COM Proxy
                }

                EventNotification ev = new EventNotification();

                ev.EventId = monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.EventId)) as byte[];
                ev.SourceID = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.SourceName)));
                ev.Time = System.Convert.ToDateTime(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Time)));
                ev.Message = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Message)));
                ev.EventType = cat.EventType;
                ev.EventCategory = cat.CategoryID;
                ev.Severity = System.Convert.ToInt32(monitoredItem.GetFieldValue(eventFields, Opc.Ua.ObjectTypes.BaseEventType, new QualifiedName(Opc.Ua.BrowseNames.Severity)));

                List<EventAttribute> Attrs = GetEventAttributes(cat.CategoryID);
                UniqueList<string> strEventNodeIds = new UniqueList<string>();
                foreach (EventAttribute attr in Attrs)
                    if (attr.strEventNodeId != "")
                        strEventNodeIds.AddUnique(attr.strEventNodeId);

                ev.EventAttributes = new Dictionary<int, object>();
                foreach (EventAttribute attr in m_configFile.Attributes)
                {
                    foreach (string strEventNodeId in strEventNodeIds)
                    {
                        if (attr.strEventNodeId == strEventNodeId)
                        {
                            object value = monitoredItem.GetFieldValue(eventFields, (NodeId)attr.strEventNodeId, new QualifiedName(attr.BrowseName, attr.BrowseNameNSIndex));
                            if (value == null)
                            {
                                ev.EventAttributes.Add(attr.AttributeID, "");
                            }
                            else if ((value.GetType() != null) & (short)ComUtils.GetVarType(value) != 0)
                            {
                                ev.EventAttributes.Add(attr.AttributeID, value);
                            }
                            else
                            {
                                // any value with a UA type that does not have a corresponding COM type will be returned as a string 
                                ev.EventAttributes.Add(attr.AttributeID, value.ToString());
                            }
                        }
                    }
                }

                //Condition-Related Event properties
                ev.ConditionName = "";
                ev.SubConditionName = "";
                ev.ChangeMask = 0;
                ev.NewState = OpcRcw.Ae.Constants.CONDITION_ENABLED | OpcRcw.Ae.Constants.CONDITION_ACKED;
                ev.Quality = OpcRcw.Da.Qualities.OPC_QUALITY_GOOD;
                ev.AckRequired = false;
                ev.ActiveTime = DateTime.Now;
                ev.Cookie = 0;

                if (ev.EventType == OpcRcw.Ae.Constants.CONDITION_EVENT)
                    SetConditionEventFields(monitoredItem, eventFields, ev, cat);

                //Tracking Events and for Condition-Related Events which are acknowledgment notifications
                if (cat.EventType == OpcRcw.Ae.Constants.TRACKING_EVENT)
                    ev.ActorID = System.Convert.ToString(monitoredItem.GetFieldValue(eventFields, (NodeId)eventUA.NodeId, new QualifiedName(Opc.Ua.BrowseNames.ClientUserId)));

                IncomingEventHandler eventHandler = new IncomingEventHandler();
                
                //extract the area associated with this event.
                AreaNode areaNode;
                string[] areas = null;
                if (m_notifiers.TryGetValue(monitoredItem.ClientHandle, out areaNode))
                {
                    areas = new string[] { areaNode.AreaName };
                }
                eventHandler.ProcessEventNotificationList(ev, areas);
            }
            catch (Exception ex)
            {
                Utils.Trace(ex, "Unexpected error in MonitoredItem_Notification");
            }
        }
Esempio n. 7
0
        /// <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);
        }