Counting Ignition Active Alarms with queryStatus()

Daniel Price4 min read
HMI / SCADAOther ManufacturerTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

A call to system.alarm.queryStatus returns a list of alarm event objects, so the count of active alarms is len() of that list. No method on the alarm event object is needed. If you want a gateway-wide total with no script at all, add two gateway system tags instead.

Which method returns the active alarm count?

Two approaches produce the number. They differ in scope, filtering, and where the work runs.

Criterion len() on queryStatus() result Gateway system tags
Source of the number Length of the list the call returns Tags under System/Gateway/Alarming/
Scope Whatever the filters select (state, source, display path) Whole gateway only
Active count Query with state = ["ActiveAcked", "ActiveUnacked"] Sum of the Active and Acked tag and the Active and Unacked tag
Script required Yes No; bind directly
Also gives alarm detail Yes, each list item is one alarm event No, counts only
Extra states available Any state you pass in the filter Clear and Acked, Clear and Unacked

Recommendation: use the tags when the requirement is a gateway-wide active total on a display or in an expression. Use len() on queryStatus when the count must be scoped to a source or display path, or when the script also needs the alarm details.

Why does queryStatus show rows in a table but give no count?

The table component renders the query result for display. It never hands the script a number. The script-side return value is a plain list with one element per alarm event, and Jython's built-in len() reports the element count of any list. The methods on the alarm event object describe a single alarm (its properties and state), not the collection, so searching them for a count method finds nothing. The object's methods are thinly documented, which is why the count is easy to miss.

How does each count travel from the alarm engine to your script?

Both paths originate at the gateway alarm journal and status engine. They differ in what crosses the client-to-gateway link.

Hop queryStatus + len() System tags
1. Origin Gateway alarm status for the current alarm events Gateway alarm counters exposed as system tags
2. Selection State, source, and display path filters in the call decide which events are returned No selection; counters are per state, gateway-wide
3. Transfer Every matching alarm event object is returned to the caller A single numeric tag value per state
4. Count len(alarms) in the script Add the two Active tags in an expression or script

The consequence: a broad queryStatus call moves one object per alarm just to produce a single integer. With a large active-alarm population, the tag path carries the same answer as one value per state.

How do I count active alarms in a script?

  1. Decide the scope. Whole gateway: skip to the tag method below. Subset: build the source and/or display path filter for the call. Check the function's signature in the scripting reference for the exact filter argument names.
  2. Query with both active states so acknowledged and unacknowledged alarms are both included:
    alarms = system.alarm.queryStatus(state = ["ActiveAcked", "ActiveUnacked"])
    print len(alarms)
  3. Add the source or display path filter arguments to the same call when the count must be limited to one area.
  4. Use len(alarms) wherever the number is needed (label text, tag write, conditional logic).

Tag method for the gateway-wide total: browse System/Gateway/Alarming/ in the tag browser and read the four state counters: Active and Acked, Active and Unacked, Clear and Acked, Clear and Unacked. Active alarms on the gateway equal the first two added together. Confirm the exact tag names in your tag browser before writing expressions against them.

What makes the count wrong?

  • No state filter. A query without the two active states returns alarms in other states as well, so len() overstates the active total. Pass state explicitly.
  • Summing all four tags. The four counters cover active and clear alarms. Only the two Active counters give the active total.
  • Comparing different scopes. A filtered queryStatus count is a subset. It matches the gateway tags only when no source or display path filter is applied.
  • Snapshot timing. The list is the alarm state at call time. An alarm that changes state after the call is not reflected until the next query.
  • Python 2 syntax. The example uses Jython, where print len(alarms) is valid. Use print(len(alarms)) if you prefer the parenthesized form.

How do I verify the count is correct?

  1. Run the unfiltered active query and print len(alarms) in the script console.
  2. Read Active and Acked and Active and Unacked under System/Gateway/Alarming/ and add them. The sum must equal len(alarms).
  3. Acknowledge one active alarm. Active and Unacked must drop by one and Active and Acked must rise by one, while the sum and a re-run len(alarms) stay unchanged.
  4. Add your source or display path filter and confirm the filtered len() matches the number of rows the same query shows in the table.

How do I get the number of active alarms from system.alarm.queryStatus?

Pass both active states and take the length of the returned list: alarms = system.alarm.queryStatus(state = ["ActiveAcked", "ActiveUnacked"]) then len(alarms).

How do I get a gateway-wide active alarm count without scripting?

Add the Active and Acked tag and the Active and Unacked tag under System/Gateway/Alarming/. Their sum is every active alarm on the gateway.

How do I count active alarms for one area only?

Use queryStatus with the active states plus a source or display path filter, then apply len(). The gateway system tags cannot be scoped, so they cannot do this.

How do I check that len() and the gateway tags agree?

Run the unfiltered active query and compare len(alarms) to the sum of the two Active tags. Acknowledge one alarm and confirm the sum does not change while the Acked/Unacked split moves by one.

Back to blog