Hi everybody. I would like to get your advice on the best practice for getting the highest priority alarm (priority and current state) for each UDT to visualise it on the embedded view (template).
I already accomplished it by a function that uses system.alarm.queryStatus()
, but I found out in the forum that it's not recommended to be used a lot because it's expensive and doesn't scale well.
I also thought of making use of System Alarming tags (ActiveUnackCount, etc.), and querying all provider alarms on change, then save the result somewhere in the Gateway variable or Memory tag, that can be available for the UDT instances or the embedded views. Not sure how I would filter, bind, write to tag in the UDT or send messages somehow to the embedded views or in Gateway scope, and I'm not sure if this approach would be better performance wise or not.
I know there are properties in each tag with alarms configured that directly get highest priority (HighestUnackedPriority, HighestActivePriority etc.), but I need something generic for the UDT not each tag, because I have many nested UDTs and not sure which tags will have alarms configuration.
I would appreciate any suggestions. Thanks in advance.
I call the system.alarm.queryStatus
function once without filters in a regular periodic (2s) Gateway Timer event. I transform this into a dict that I can filter more easily for a given tagPath, and store this into a global variable.
Then I have another function which writes to all of my Alarm Summary UDT instance tags which hold the various summary info (total alarm count, counts for each priority, counts of active/ackd/cleared, etc.). Then my graphics just bind to the tags.
I've also heard this feature will be added with 8.3 though I'm eager to confirm and curious to know how it will work. Based on that rumor alone, I'm holding off on this feature enhancement for our product in the meantime.
2 Likes
@nminchin This is pretty much what I was thinking of. But what do you think of creating an expression tag that is driven from Alarming System Tags, and run the script on change instead of periodic (2s).
@msteele 8.3 will be full of surprises, I would hold off on the feature, but it will be eventual to rebuild many features once upgrading anyway.
That would make a lot of sense I think; I forgot those tags even existed tbh. In that case I would call it from a Gateway Tag Change event (not on a Tag's Value Change event). That would eliminate a lot of the calls and only update the alarm tags when there's been a change in alarm states.
I would create an expression tag and use this expression below and trigger on this:
toStr({[System]Gateway/Alarming/Active and Acked}) + '|' +
toStr({[System]Gateway/Alarming/Active and Unacked})+ '|' +
toStr({[System]Gateway/Alarming/Clear and Unacked})
@jlandwerlen
1 Like
I tried doing something on demand, however, I was using an alarm listener vs the native system tags and what I found were times when it would trigger a few times in quick succession (from a few active at once and a reset ) and I never found an elegant way to prevent multiple triggers in a row.
From my testing, even running once per second continuously, I saw less CPU usage (none really) using writeBlocking compared to using the runScript (which was OK until I had a bunch of instances). If you only have a handful of instances IMO you should be fine no matter which you choose.
3 Likes
I think the system tags only update at a maximum rate (1s??) so this would prevent multiple calls in quick succession, (this isn't capped at all from testing) while also avoiding writing to tags that haven't changed. My biggest issue is that all those tag writes end up in the audit log and pollute it
Thinking aloud:
- you want a maximum execution rate, say 2s
- if any alarm states change, they set a single flag
- the script to update tag paths is only executed if the flag is on
So maybe this can be accomplished with a memory tag as the flag. An on-Value change script on the [System]Gateway/Alarming/* tags writes the memory tag to True. Then a timer script reads the memory tag and writes it to False immediately after reading. If it was True, run the script to update the alarm summary tags. Edit: Set the execution rate of this Timer script to 2s
Instead of adding the change scripts into the System provider tags, I would add an expression tag into your tag provider binding to the concatenation of the alarm tags and put the value change script on this tag so that you can organise it somewhere useful.
2 Likes
Thanks all for the great tips.
@nminchin I found your flagging idea is brilliant. But can't I just configure the expression tag that is bound to System Alarms tags to execute with fixed rate each 2s, and still have the Gateway tag change script on the expression tag. I didn't test it yet.
You don't care about the execution rate of the expression tag, you want it to update whenever the underlying tags change value. A value change of this tag will write True to the flag as many times as it changes and it will have negligent effect on the performance. The only thing that should run every 2s is the gw timer event that writes to the alarm summary tags, since you only care about updating these summary tags at a maximum rate of 2s, but only if the alarm counts have actually changed (ie new alarms have come or existing have gone)
(I edited my post above in bold)
Yes I totally understand your method. We both get the same result that the alarm summery will be queried at a maximum rate of 2s and only if the alarm counts have actually changed.
Instead of using a middleware tag as a flag, I just adjusted the expression tag to execute with fixed rate 2s and put the alarm query script in a tag change Gateway script that triggers only if the value or quality of the expression tag changes (Not timestamp). So the expression will run every 2s but the alarm summery script will not unless the alarm counts really change.