But what can be done when trying to show individual alarm counters?
alarm_events table can be queried and a COUNT() can be done on the source in a date range. But from there, Iâm not sure how to get the property âLabelâ of the alarm based on the source.
That made me wonder, what is the best approach for statistics using a variety of filters?
SELECT FORMAT(eventtime, 'dd/MM/yyyy HH:mm:ss') AS "Event Time",source
FROM alarm_events
WHERE eventtype = 0 AND
eventtime >= :startDate AND eventtime <= :endDate
ORDER BY eventtime DESC
Querying the table directly only works if you have an database alarm journal configured, and you would have to jump through some not insignificant hoops to get the label. You would need to parse the tag path out of the alarm source, then use system.tag.getConfiguration to get the label. You also cant query active alarms at all that way.
Edit:
That was poorly worded, you cant query the info you see in the alarm status table might be a better way to say it.
I think an alarm journal is necessary to get statistics information. Because it's not about the current state, but looking up at past alarms to count them based on some filters.
After playing around with system.alarm.queryJournal(), I went back to SQL to finish the query that gets the label. I'm not sure it's right but at least I get some results.
SELECT COUNT(ae.eventtime) AS "Trigger count",aed.strvalue
FROM alarm_events AS ae
INNER JOIN alarm_event_data AS aed
ON ae.id = aed.id
WHERE
ae.eventtype = 0 AND ae.eventtime >= :startDate AND eventtime <= :endDate
AND aed.propname = 'label'
GROUP BY aed.strvalue
ORDER BY COUNT(eventtime) DESC
I will give system.tag.getConfiguration a quick test.
I donât think the report module would necessarily be easier, but with it you could create an alarm journal query data source then use a script data source to go through the dataset and perform your calculations. One benefit to this approach is that you can use any type of alarm journal.
Edit:
Are you sure that sql query is doing what you want? I tried it on a testing alarm journal and it yielded zero results. I modified it to see what i was getting.
SELECT COUNT(ae.eventtime) AS "Trigger count",aed.strvalue, aed.propname as propname
FROM alarm_events AS ae
INNER JOIN alarm_event_data AS aed
ON ae.id = aed.id
GROUP BY aed.strvalue
ORDER BY COUNT(eventtime) DESC
I do get results and it looks good but I have to recheck. How come you got zero results?
In your query you left out the "where" statement, that's ok for the dates. But you would need "propname = label" as there is the alarm text. "eventtype = 0" would be just the activation event.
I'm not sure, I think event type values are from this table:
I'm not sure what "dtype" refers to.
Therese are the tablets from the alarm journal.
Edit:
I get an error when showing my named query on a perspective table.
I caution you if youâre calling system.alarm.queryStatus from the client. In Vision, these can easily kill client performance. In Perspective, these can easily kill your gateway. Calling this function is expensive and doesnât scale well.
Consider calling this function once periodically in a script library to pull in all alarms and store the results in a library variable. Then filter that variable and summarise your alarms per area based on this instead.
Not sure, i left out the where clause entirely to try to find out. There are absolutely no labels in my data, despite having labels configured in my alarms.
That's weird. Try posting some screenshots. Maybe your new labels are not logged or you need to reset your trial for them to be logged.
How people mostly use alarms?
"Name" property is not useful for a dynamic message because it's fixed.
"Display Path" has the default path. I guess a dynamic message can built here but you would miss the path.
"Label" seems appropriate to contain a dynamic message.
Default setup for Alarm Status Table shows Display Path and Source. I don't know what's the intention for it.
Default setup for Alarm Journal Table shows Event ID and Source. Again, I don't know the intention for it.
Out of my head, Dataset is different from Array of Objects. As an example, today I used the Pie Chart binding its "Data" Property. Even though it should accept an Array List, it was able to use a Dataset without any issues.
Anyway, providing some type of statistics is the main topic. I will give it another round of tests tomorrow.
Well in 8.1.5 at least (I think maybe you can display custom alarm fields in the ast now), I use:
Name: the name of the alarm, e.g. Failed to Start
Label: the device description and equip id, e.g. Agitator [T2334_M01]
Display path: the area and parent device if relevant, e.g. Red TF T2334
The alarm source will always contain the path to the tag, so you don't need to worry about replacing display path.
Using this methodology, you can display alarms anywhere with all the info you need.
For example on a device popup, just show name
On a tank detail page, show label and name
On the main alarm page, show all 3
Event id is useless to operators but lets you group different events attached to the same alarm event, e.g. Active, acked, cleared events for a single alarm event
What i would really like to see is all of the alarm info for an alarm event on the one row, so you know when it activated, when it was ackd, and cleared without having to go searching. At least have it an option as sometimes you actually might want to show it more as a timeline as it is now
Fully licensed, and i did try changing the labels and names and saving to see if that made a difference. My previous screen shot is the sum total of every alarm and there is not one instance of a 'label' property.
I am able to get the labels with system.alarm.queryJournal(journalName="AlarmJournal")[0].getLabel() which is why i suggested using that instead of querying directly.
I will give it a try tomorrow. I think it's a good idea.
I have to think about this one. Maybe it's something I would like but I'm not aware of yet.
Are your tables the same as mine?
I actually got some errors out of it. Using a for loop I got an error message... something like "index out of range".
So, I did some debugging with system.perspective.print() and I found that some results were [].
I'm not sure if a should call them Null, None, or empty list.
Edit:
I'll run the code tomorrow and post the error.
They should be the same, default settings on for an external database alarm journal.
And my use of system.alarm.queryJournal was a simple proof of concept I tested in the script console, The manual says the return results are a list of PyAlarmEvent objects for what its worth.
I call the function to populate the library variable with alarm info from an expression tag using runScript. You can only access the value of the variable within the scope from which you call it. For example, you canât call the function in the tag scope and read the value from the client scope.
Calling from a tag gives access to the value from the tag scope so then I can have other expression tags in various folders that filter and summarise the alarms stored in the library variable based on the tag path theyâre located in. Filtering the dictionary is super quick compared with calling the queryStatus function 50 times
Where do you get that version number from?
At this date I can see the latest release is 8.1.16
I'm using 8.1.15
I've notice that the source path saved in the database has a different format than the one Ignition's use.
From the database: prov:default:/tag: path here /H:/alm:High Alarm
I was used to the path you get when you right click on a tag: [default] path here /H/Alarms/High Alarm
I tested some functions with the path from the database:
But I get not result from them. So I was thinking that some string manipulation have to be done to get the path from the database look like the "normal" one.
Breaking it down into steps:
Create a script in the Project Library.
Pick a scope and call it. For example, tag scope.
Other tags will filter on the tag that is calling the function.
Show those results in some Views and filter more if needed.