Been years since I've touched Ignition. Working on big Perspective project. I need to know if there is an "easy" way to determine if any tag within a tag folder is in an alarm state. Example is a structure like "Filters/Filter1/INF_VLV". In that folder there may be a UDT with several possible alarms, as well as individual tags that could be alarmed. Is there any sort of script/function that would return a boolean if any of the alarm states are active for just that folder? Reasoning is I want a yellow border around my screen badge, but want it to be universal to fit folders with any number of alarms rather than scripting a bunch of "or this or that or..." that has to be changed for multiple items. Any assistance greatly appreciated.
Tags do have an HasActive
boolean in the Alarms
property:
But I'm not sure you can reach it through scripting.
Another solution would be to pass the results of a tag browse to system.alarm.queryStatus
You can filter system.alarm.queryStatus()
based on source and state. Unless I am missing something I think the it should work in your case. The following returns a list of all active alarm within the folder Pumps.
system.alarm.queryStatus(state = [2,3], source = "prov:default:/tag:Pumps/*")
You could then perform a check to see if it returns anything and use that to determine whether or not to show the border and badge.
I think you could do one better with expression.
isAlarmActive("[default]Pumps/*")
Seems to do the same thing.
There are some exchange resources that may be helpful, here is one:
Thank you so much! I will give that a try.
I've tested this function successfully. Problem now is how do I make it "Dynamic". Have fullscreen view which calculates parameter "TagPath" based in a filter number (i.e. [default]Filters/Filt1). In that filter are UDT's for valves, say INF_VLV. Have smaller view with badge for each valve that looks for parameters based on "TagPath" and appends "/INF_VLV". Can I pass a calculated strings into the isAlarmActive script function to dynamically change the style of the badge view (like draw a red border around it). Just can't seem to figure out how to "parameterize" this without creating a new "tag" within each UDT (which would be a big hassle).
Again, any assistance greatly appreciated.
You should definitely be able to accomplish this. You should be able to bind to the TagPath parameter on the subviews isAlarmActive({this.params.TagPath})
within the smaller valve view. You will probably have to add a /*
to the end of the path that way you are checking all tags within the valve UDT for an alarm. isAlarmActive({this.custom.TagPath+'/*'})
Thank you. I have been trying that. Ignition is giving me grief! I am testing with a memory tag. Created a label and bound the text to "isAlarmActive({view.custom.AlarmPath})". [created custome property of AlarmPath which is TagPath " "/*"]. If I toggle an alarm bit, the Binding Preview updates correctly (true or false). However the View label does not update until I check the binding. Toggling the bit does not change the label, but if I toggle the bit, check the binding preview and close it, the label updates.
However, if I create a memory discrete tag bound to the isAlarmActive expression it updates in realtime.
I've experienced difficulties doing what I wanted with isAlarmActive() a while ago, though I can't recall exactly what they were.
If you do decide to go the Python route, this post contains a great example of how to get more mileage out of system.alarm.queryStatus().
I think the issue you are facing is that isAlarmActive()
does not poll in perspective and if you use /*
it does not detect the tag change.
I am not sure if this is the most elegant solution but you could spoof polling.
if(now(1000)>0,isAlarmActive({this.view.AlarmPath}),isAlarmActive({this.view.AlarmPath}))
If the alarm paths are consistent it may be easier to try and avoid using /*
that way it refreshes on tag change.
Thank you. I figured it had something to do with polling. I may just add an expression tag to each UDT that uses the isAlarmActive([.]/* and reference that, since that is a polled tag.
Thanks again for your assistance!
I don't think that works.
I just tried with now(3000)
and it still triggers more than every 3 seconds.
edit: I'm a bit surprised at what I'm seeing, using now(poll_rate)
in a binding...
I'm kinda sure I've used now(x)
to trigger something every x seconds before, but I can't get that to work anymore...
You can vote on this feature:
The poll rate to now()
is milliseconds, but only works in an event-driven context. Expression tags have many execution modes, and event driven is just one of them. (Same is true for the poll rate argument to runScript()
.)
I did my tests on a component custom properties, not on tags.
But that would explain why I got different results than what I thought I'd get.
It appeared to be working correctly for me. Maybe you had another event causing it to execute. If you leave off the /*
it will reevaluate on tag change.