isAlarmActive with polling rate

I feel like maybe I am missing something here, but when I try to use the isAlarmActive expression with a polling rate as a binding in perspective, I cant give it a polling rate without it failing. Unfortunately the documentation only shows it with multiple tags, not with a polling rate.

Here is what I have:

isAlarmActive("[MyProvider]MyFolder/MyTagWithAnAlarm", "MyAlarmName", 5000)

Here is the error:
image

I can force it to poll by doing this, but Its kind of a cheeky workaround

if(now(5000) != "", isAlarmActive("[MyProvider]MyFolder/MyTagWithAnAlarm"), "")
1 Like

From a glance at the code, I think there’s no ability to specify a poll rate on the gateway because it shouldn’t be necessary. On the gateway we should be able to directly hook into the tags with listeners, and get triggered value changes.

So then as a clarification, I am not seeing the binding auto-reevaluate when the alarm is triggered

However it does auto-reevaluate by binding directly to the alarm isActive tag path

so is this part of the user manual a typo then?

isAlarmActive(tagPath, [alarmName], [pollRate])

  • Parameters

String tagPath - The Tag path to search for active alarms. Supports the wildcard ā€˜*’.

String alarmName - The name of the alarm to search for. Supports the wildcard ā€˜*’. [optional]

Integer pollRate - The poll rate in milliseconds. Only applicable in the Client scope. [optional]

  • Returns

Boolean - True if an alarm is active; False if no active alarms were found.

Which part?

The part about being able to set a poll rate?

The user manual already states it’s only applicable in Client scope.

Perspective is not ā€œClientā€ scope. We’ve been making an effort to say ā€œVision Clientā€ where applicable in the user manual to try to make that more clear, looks like we missed a spot.

ah ok, that makes sense. I didn’t realize the distinction. Is there anyway to add that to perspective? My binding seems to respond when an alarm goes from in-active to active, but when the alarm clears it doesn’t change.

I think Paul’s original point here is that polling isn’t necessary in the gateway. If the binding isn’t behaving properly then it might be a bug.

Is your execution mode currently set to Event Driven?

edit: assuming this is on an Expression Tag

I’m using it on a property binding to set a style class when an alarm is active

I think we already have an issue for this… I’m going to update it and put it in the backlog, hopefully for next sprint.

1 Like

JD, I’m having the same issue. The function works as long as I click apply in the ā€˜Edit Binding’ window after an alarm state change so there seems to be no automatic polling.

I’m having the same problem. I want to highlight certain urgent alarms by making a slow-flashing style class on the root of the view. One of them is if our main database goes unavailable. It works fine if I bind directly to the tag, but I have a 30 second active delay on it. The transition doesn’t get caught.

Thanks

I'm back. Is there any progress on this? Example, I have two tags, [default]Temp/Alarm Test and
[default]Temp/Alarm Test 3

I am using
isAlarmActive("[default]Temp/Alarm*")

bound to a label. That label doesn't change live. However, if I bind either one of the alarms to the label
isAlarmActive("[default]Temp/Alarm Test")
, those labels will change. Also, I can do:

isAlarmActive("[default]Temp/Alarm Test") ||
isAlarmActive("[default]Temp/Alarm Test 3")

And that will change live, which is fine here, but I will soon be implementing 30+ tags into a folder that I want to check to see if any of them go active, and I don't want to have to type them all out and maintain the list if a tag changes.

Thanks

This is how I do it:

New script in Scripting -> Project Library -> "templates" (or whatever you want to call it) with the following code:

def getActiveChildrenAlarms(tagPath):
	
	# Check if tag path is not empty
	if tagPath!='':
		# Split the tag path to get the tag name
		splitPath = tagPath.split(']')
		# Create a filter to get all alarms that have the tag name in their path
		filter = ['*%s*' % splitPath[-1]]
		# Get all active alarms for the filter
		states = ['ActiveUnacked','ActiveAcked']
		activeAlarms = system.alarm.queryStatus(Path = filter,state = states)
		# Create a list of alarms and their states
		ret = []
		for alarm in activeAlarms:
			item = {
				'name': str(alarm.getName()),
				'state': str(alarm.getState())
			}
			ret.append(item)
	else:
		# Return an empty list if tag path is empty
		ret = []
	
	return ret

Create a view prop called "rootTagPath" which holds the tag path, i.e. [default]SBR/Basin1/Basin1Mixer

Then I have a custom prop object called motorAlarms with an expression + script transform binding:

This lets you bind something such as a style class like so:

Can't promise this is the most efficient method, but it works. I'm sure @pturmel will tell me I'm doing something stupid.

This is an absurdly expensive system call, especially with wildcards. Don't call it from a UI. Call it from a timer event, with parameters that will satisfy all users. Divvy up the results into project script top-level dictionaries (or dataset or document tags, perhaps) that UI consumers can hit with near-zero latency.

1 Like

Haha. I figured there would be something

1 Like

That particular function, called in a Vision runScript binding, will bring a high-latency (VPN, WAN) client to screeching halt. Perspective is a bit more tolerant, but still not a good idea.

Here is what I have done. I made a tag that calls isAlarmActive, Made it Fixed Rate Execution mode and set the poll rate to 1,000. Seems to work. I don't know if the poll rate is too fast? I would like for it to react relatively quickly, but don't want to suck down all the resources doing it.
image