Professional OPC
Development Tools

logos

Online Forums

Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.

Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.

Do not use the Contact page for technical issues.

Display active alarms in a grid or similar control

More
More
28 Mar 2014 16:31 #1795 by support
I have no objections - it all appears fine!

Please Log in or Create an account to join the conversation.

More
28 Mar 2014 14:42 #1794 by syamak
I've changed my code according to your advices. It's working nice right now.
I'm not handling errors yet, because this is a test demo.
And I'm subscribing only one server.

I'm open to any advice. Thanks for your support.

These are my codes:
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private int _handle;
        private readonly DataTable _alarms = new DataTable("Alarms");
 
        public Form1()
        {
            InitializeComponent();
 
            _alarms.Columns.Add("Time");
            _alarms.Columns.Add("Condition");
            _alarms.Columns.Add("Source");
            _alarms.Columns.Add("Message");
 
            dataGridView1.DataSource = _alarms;
        }
 
        private void Form1_Shown(object sender, EventArgs e)
        {
            easyAEClient1.Notification += OnNotification;
            _handle = easyAEClient1.SubscribeEvents("", "OPC.SimotionAlarms", 100);
        }
 
        private void OnNotification(object sender, EasyAENotificationEventArgs args)
        {
            if (args.Exception != null || args.Event == null) return;
 
            if (args.Event.Active)
            {
                var row = _alarms.NewRow();
 
                row["Time"] = args.Event.Time;
                row["Condition"] = args.Event.ConditionName;
                row["Source"] = args.Event.QualifiedSourceName;
                row["Message"] = args.Event.Message;
 
                _alarms.Rows.Add(row);
            }
            else
            {
                var result = _alarms.Rows
                                    .Cast<DataRow>()
                                    .Where(row => row["Condition"].Equals(args.Event.ConditionName) && row["Source"].Equals(args.Event.QualifiedSourceName))
                                    .ToList();
 
                foreach (var row in result)
                {
                    _alarms.Rows.Remove(row);
                }
            }
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            easyAEClient1.UnsubscribeAllEvents();
        }
 
        private void btnRefreshAlarms_Click(object sender, EventArgs e)
        {
            _alarms.Rows.Clear();
            easyAEClient1.RefreshEventSubscription(_handle);
        }
 
        private void btnExit_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}

Please Log in or Create an account to join the conversation.

More
28 Mar 2014 12:51 #1793 by support
Hello,

I think that the general approach is OK. My concerns would not be about the effectiveness (in terms of performance), but rather about a full correctness. I can see a number of small issues in the code:
  1. You are not doing anything in case of exception. It depends on the requirements, but normally you'd like to indicate somehow that there is a problem.
  2. It is not clear to me why you do not remove existing rows when a Refresh indicates that the alarm is not active.
  3. If you were subscribed to multiple servers, you will also need to assure that messages from different servers do not get mixed up - by storing and comparing the args.ServerDescriptor members.
  4. In a general case, there can be multiple independent conditions on each event source. You should therefore not compare only the args.Event.QualifiedSourceName, but also the args.Event.ConditionName.
  5. On the other hand, there is no gurantee that the message is the same when the alarm is being inactivated. Do not compare args.Event.Message.
  6. The test for result.Any() does seem unnecessary.

I hope this helps.
The following user(s) said Thank You: syamak

Please Log in or Create an account to join the conversation.

More
28 Mar 2014 11:55 #1792 by support
From: S.
Sent: Friday, March 28, 2014 10:49 AM
Subject: RE: EasyAE Client - Alarms example

Yes, we are dealing with condition events.

In my application, I’m using a DataTable to keep the alarms.
When the Notification event fires, I’m looking for the args.Event.Active property.
If args.Event.Active is true, I’m adding Time, QualifiedSourceName and Message properties to the DataTable.
If args.Event.Active is false, I’m searching the DataTable for QualifiedSourceName and Message which are equal to new coming event , if any DataRow exists by these properties, I delete them.


        private void OnNotification(object sender, EasyAENotificationEventArgs args)
        {
            if (args.Exception != null) return;
 
            if (args.RefreshComplete)
            {
                _refresh = false;
            }
            else if (args.Event != null)
            {
                if (args.Event.Active)
                {
                    var row = _alarms.NewRow();
 
                    row["Time"] = args.Event.Time;
                    row["Source"] = args.Event.QualifiedSourceName;
                    row["Message"] = args.Event.Message;
 
                    _alarms.Rows.Add(row);
                }
                else if(!_refresh)
                {
                    var result = _alarms.Rows
                                        .Cast<DataRow>()
                                        .Where(row => row["Source"].Equals(args.Event.QualifiedSourceName) && row["Message"].Equals(args.Event.Message))
                                        .ToList();
 
                    if (result.Any())
                    {
                        foreach (var row in result)
                        {
                            _alarms.Rows.Remove(row);
                        }
                    }
                }
            }
        }


This is my logic about events. Is there any more effective approach to achieve this.

Thank you for your support.

Please Log in or Create an account to join the conversation.

More
28 Mar 2014 11:54 #1791 by support
In OPC Alarms&Events, only the so-called condition events can be active or inactive. Other events (so-called simple events or tracking events) are single-shot occurrences that do not have active/inactive status. So for the rest of this discussion, I will assume that we are dealing with condition events.

In general, you need to instantiate the EasyAEClient object, hook the event handler, and then call the SubscribeEvents method with the right parameters. You will then receive notifications about the initial state of the conditions, and also about any changes in their state.

I would be happy to provide more information; please just let me know which part you need to help with.

Zbynek Zahradnik

Please Log in or Create an account to join the conversation.

More
28 Mar 2014 11:53 #1790 by support
From: S.
Sent: Friday, March 28, 2014 10:22 AM
Subject: EasyAE Client - Alarms example

....
In my application, I need to show all active alarms in a grid, listview or anything else. I use my algorithm to achieve this.

My question is that, what is the best approach to view all active alarms and keep track of them. (Alarms are conditional)

Sorry to contact you by this mail address but I only have this mail adress.

İyi çalışmalar/ Best Regards,
S.

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.068 seconds