# Counting Alarm Priorities in Power table according System Areas

**URL:** <https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042>\
**Category:** Ignition\
**Tags:** scripting, perspective\
**Created:** [August 16, 2022, 1:05pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042 "2022-08-16T13:05:13Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sandeep\_Narra](https://avatars.discourse-cdn.com/v4/letter/s/76d3ee/32.png) [@Sandeep\_Narra](https://forum.inductiveautomation.com/u/Sandeep_Narra)\
**Post date:** [August 16, 2022, 1:05pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/1 "2022-08-16T13:05:13Z")

</div>

Hello All,  
I have a power table which displays the Alarms of Different Systems of a site and each system has four different alarm priorities. I want to count Each total number of alarms of each system according to priorities and move it to another power table. is there any script to do this?

 ![MicrosoftTeams-image (12)](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/9/a9472de93a3811a8756aafb3bd14584b24d00a9e.png)  
 ![MicrosoftTeams-image (13)](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/d/0d49a1db2915a5c5e1edfd646f33d5509ca37b59.png)

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [August 16, 2022, 1:27pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/2 "2022-08-16T13:27:45Z")

</div>

This is how we currently handle alarm summaries.

Call this from a gateway timer script:

```auto
def getAlarmSummaryAll():
		
	global alarmSummaryGlobal
	alarmSummary = {}
		
	state = ["ActiveUnacked", "ActiveAcked", "ClearUnacked"]
	alarms = system.alarm.queryStatus(state=state)
		
	for alarm in alarms:
			
		source = str(alarm.source)
		tagPath = str(alarm.source).split(':')[3]
		name = str(alarm.name)
		state = alarm.state.name()
		priority = alarm.priority.name()
		
		alarmSummary[source] = {'tagPath':tagPath, 'name':name, 'state':state, 'priority':priority}
			
	alarmSummaryGlobal = alarmSummary

```

I recommend placing this script in the project script as the one above. This script will get called from the UDT instance (which I describe below).

```auto
def getAlarmInstances(alarmPath):
		
	global alarmSummaryGlobal
	
	#Removes the tag provider is present
	if alarmPath.find(']') != -1:
		alarmPath = alarmPath.split(']')[1]
	
	alarmPriorities = {'Diagnostic':0, 'Low':1, 'Medium':2, 'High':3, 'Critical':4}
	statePriorities = {'ClearAcked':0, 'ClearUnacked':1, 'ActiveAcked':2, 'ActiveUnacked':3}
	alarmStates = {'ActiveUnacked':'flash', 'ActiveAcked':'static', 'ClearUnacked':'flash', 'ClearAcked':'static'}
	priorityCounts = {'Diagnostic': 0, 'Low': 0, 'Medium': 0, 'High': 0, 'Critical': 0}
	priority = None
	state = None
	styleClass = None
	hasUnackAlarm = 0
	resultDict = {'counts': priorityCounts, 'priority':	'', 'state': '', 'class': '', 'hasUnackAlarm': ''}	
	alarmPrioritiesList = []
	
	for alarm in alarmSummaryGlobal:
		
		#If alarm found within the summary then get counts and priorities
		# The tagPath must match exactly starting from the left, this prevents partial matches
		tagPath = alarmSummaryGlobal[alarm]['tagPath']
		if tagPath.startswith(alarmPath, 0, len(alarmPath)):
			
			#Create a list of alarm priorities, so we can later find the highest priority and state for that priority
			alarmPriority = alarmSummaryGlobal[alarm]['priority']
			alarmState = alarmSummaryGlobal[alarm]['state']
			alarmPrioritiesList.append([alarmPriorities[alarmPriority], statePriorities[alarmState]])
			
			if alarmState == 'ClearedUnacked' or alarmState == 'ActiveUnacked':
				hasUnackAlarm = 1
			
			if alarmPriority == 'Diagnostic':
				priorityCounts['Diagnostic'] += 1
			if alarmPriority == 'Low':
				priorityCounts['Low'] += 1
			if alarmPriority == 'Medium':
				priorityCounts['Medium'] += 1
			if alarmPriority == 'High':
				priorityCounts['High'] += 1
			if alarmPriority == 'Critical':
				priorityCounts['Critical'] += 1
	
	if alarmPrioritiesList:		
		alarmListMax = max(alarmPrioritiesList, key=lambda item: (item[0], item[1]))
		priority = alarmPriorities.keys()[alarmPriorities.values().index(alarmListMax[0])]
		state = statePriorities.keys()[statePriorities.values().index(alarmListMax[1])]
		styleClass = alarmStates.get(str(state))
	
	#Take the results and place in a dictionary		
	resultDict = {
					'counts': priorityCounts, #A dicionary holding counts for each priority
					'priority':	str(priority), #The highest priority
					'state': str(state), #The most important state
					'class': styleClass, #The style class for indication purposes
					'hasUnackAlarm': hasUnackAlarm #At lease one unacknowledged alarm exists
					}	
	
	json = system.util.jsonEncode(resultDict)	
	return json	

```

Attached is the alarm UDT (tagAlarms.json). You will need to set the correct path within the element `summary` - replace question marks with your actual path to the script:

```auto
runScript('?????.getAlarmInstances',0,left({PathToParentFolder},lastIndexOf({PathToTag},{InstanceName})))

```

Now you can insert an instance of this UDT anywhere you want to get alarm summary information. You could use these instances for your table.

It should be noted that I’m not the best with Python, so any pointers/tips are welcome. I have tested with 100s of alarms and 100s UDT instances and the gateway didn’t break a sweat. There are some elements that probably won’t be needed for your application, but I left those in. You can remove them or simply ignore them.

[tagAlarms.json](https://forum.inductiveautomation.com/uploads/short-url/aqYQ0Pa4aPbVPDnUOmLzyMt2Wdn.json) (2.3 KB)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 16, 2022, 3:54pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/3 "2022-08-16T15:54:40Z")

</div>

You will probably want to try to refactor to minimize excess queries to the alarming system. Currently that code will run 5 \* the number of open clients you have, which will rapidly dramatically impact the gateway.  
I would put a single `queryStatus` in a gateway timer or scheduled script at a given rate, and write out the results into separate tags accordingly, so that each client just has to read those tags to get the updated count.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [August 17, 2022, 12:18am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/4 "2022-08-17T00:18:43Z")

</div>

@paul-griffith made a great point. I updated my original post with something that may be more useful for you. Calling `system.alarm.queryStatus` a bunch can get expensive. The method I posted seems to be very lightweight. I haven’t seen any issues so far.

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 17, 2022, 10:53am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/5 "2022-08-17T10:53:02Z")

</div>

Just for information, has the component “Alarm Status Table” the same performance impact of calling queryStatus at the “Refresh Rate” of the component, or is the “Alarm Status Table” optimized in some way?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [August 17, 2022, 11:15am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/6 "2022-08-17T11:15:59Z")

</div>

There was a performance issue with the ast in earlier version which was fixed, then came back again, and is now fixed in 8.1.19 I believe and now the ast should be good with performance

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [August 17, 2022, 11:18am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/7 "2022-08-17T11:18:58Z")

</div>

> [@jlandwerlen](#):
>
> It should be noted that I’m not the best with Python, so any pointers/tips are welcome.

Since you asked... 😉

```python
			if alarmPriority == 'Diagnostic':
				priorityCounts['Diagnostic'] += 1
			if alarmPriority == 'Low':
				priorityCounts['Low'] += 1
			if alarmPriority == 'Medium':
				priorityCounts['Medium'] += 1
			if alarmPriority == 'High':
				priorityCounts['High'] += 1
			if alarmPriority == 'Critical':
				priorityCounts['Critical'] += 1

```

Can be reduced to:

```python
			priorityCounts[alarmPriority] += 1

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [August 17, 2022, 1:24pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/8 "2022-08-17T13:24:01Z")

</div>

> [@jlandwerlen](#):
>
> `tagPath = str(alarm.source).split(':')[3]`

`alarm.source` has a `getPathComponent` method that you can use to get the tag path:

```python
alarm.source.getPathComponent('tag')

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 17, 2022, 2:46pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/9 "2022-08-17T14:46:19Z")

</div>

> [@taglias](#):
>
> Just for information, has the component “Alarm Status Table” the same performance impact of calling queryStatus at the “Refresh Rate” of the component, or is the “Alarm Status Table” optimized in some way?

The impact on the gateway is effectively the same, but the alarm status table component has the advantage of automatically fetching the data in a background thread. Any scripting or expressions you create in Vision are going to run on the main Swing GUI thread (the EDT), making your application 'feel' less responsive if there are long running scripts. You have to jump through some hoops to move stuff to background threads in scripting, or otherwise take advantage of async mechanisms like bindings to make things more reactive.

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 19, 2022, 9:14am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/11 "2022-08-19T09:14:53Z")

</div>

Thank you for the reply.  
I noticed that calling `system.alarm.queryStatus` from 10-15 clients requires a lot of resources of the gateway.

What do you think about creating a gateway script that writes a dataset memory tag with the status of the active/unacknwoledged alarms, and than subscribe that tag from the clients?  
Do you think that this solution would require less resources on the gateway?  
How big can be a dataset memory tag before becoming too expensive for the gateway/client?

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [August 19, 2022, 10:41am UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/12 "2022-08-19T10:41:42Z")

</div>

I think he aleady said that .😉

> [@paul-griffith](#):
>
> I would put a single `queryStatus` in a gateway timer or scheduled script at a given rate, and write out the results into separate tags accordingly, so that each client just has to read those tags to get the updated count.

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 19, 2022, 12:17pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/13 "2022-08-19T12:17:57Z")

</div>

Almost…  
The question was about writing the alarm count for each area, so just few tags.

My question is:  
instead of using queryStatus (or the Alarm Table) in each client, could it be less resource expensive on the gateway to use queryStatus only on the gateway, and transfer the information about each active/unacknowledged alarm (possibly hundreds/thousands of alarms) using a dataset memory tag (and then use a Table component to show the alarms on the client)?

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [August 19, 2022, 12:19pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/14 "2022-08-19T12:19:17Z")

</div>

Still applies, regardless of the post processing.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 19, 2022, 3:29pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/15 "2022-08-19T15:29:27Z")

</div>

Yeah, it’s still generally going to be more efficient.

My arbitrary, seat of the pants number is that I wouldn’t put more than about 10,000 rows in a dataset tag. In this application, you’d be mostly _reading_, and care a lot less about the writing behavior, but just keep in mind that a memory tag will save _all_ of its data into the internal database (so that it’s there when you restart the gateway) which can ‘clog’ your internal database.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 19, 2022, 3:31pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/16 "2022-08-19T15:31:27Z")

</div>

This is the kind of thing that should be cached in a jython variable created at the top level of a script module.

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 19, 2022, 8:09pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/17 "2022-08-19T20:09:47Z")

</div>

Thank you for the reply, I hadn’t thought about the effect on the internal database of using a memory tag. Maybe I could post an idea in `ideas.inductiveautomation.com` to have non retentive memory tags, so as not to use the internal database.

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 19, 2022, 8:15pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/18 "2022-08-19T20:15:02Z")

</div>

But if I cache the result in a jython variable on the gateway, is there an efficient way to access it from the clients?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 19, 2022, 8:38pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/19 "2022-08-19T20:38:32Z")

</div>

Use runScript or my `objectScript` to call the function that looks up and/or populates the cache.

```auto
objectScript("path.to.script.getThroughCache(args[0])", {path.to.cache.key})

```

This has become common enough for me lately that I’ll probably create an expression function that optimizes this pattern. (Cache hit check in java only, invoke jython only on misses. Something like that.)

---

<div class="post-metadata">

**Author:** ![taglias](https://avatars.discourse-cdn.com/v4/letter/t/54ee81/32.png) [@taglias](https://forum.inductiveautomation.com/u/taglias)\
**Post date:** [August 19, 2022, 9:52pm UTC](https://forum.inductiveautomation.com/t/counting-alarm-priorities-in-power-table-according-system-areas/63042/20 "2022-08-19T21:52:42Z")

</div>

And if I use an expression tag, using a `runScript` call, is the internal database still used or is an expression tag non retentive?
