Alarm Status Table - Dynamic filtering

Fairly new to using Ignition Vision, but is there a way to dynamically link an alarm status table to reference only the alarms for a specific tag?

For example on an HMI I have a pressure sensor, and when I click the sensor it will open a popup that has data related to that sensor only (PV, alarm values, etc), and on that popup I want to have an alarm status table for only that sensors alarms.

This post should help you figure it out:

I appreciate the link, however I am looking to somehow, for lack of a better term "universally" link the table without having to type anything into the filters. I am looking to bind them to a tag of some sort.

You'll just need to bind the source filter (note don't use the display path since this is configurable and may not be the tag path) to an expression that manipulates the tag path by adding the prefix and suffix parts, and removes the tag provider if you supply that. Best to add the tag provider into the filter too.

e.g.
if you're passing into the popup the tagpath to the device:
deviceTagPath = '[default]Area A/Sub B/Pump 1'

Then you could generate the alarm source filter using a combination of the following custom properties added to the root container:
RootContainer.tagProvider [expression binding]: split(split({RootContainer.deviceTagPath}, ']')[0,0], '[')[1,0]
RootContainer.tagPath [expression binding]: split({RootContainer.deviceTagPath}, ']')[1,0]

Then the source filter would be:
source filter = 'prov:/' + {RootContainer.tagProvider} + ':/tag:' + {RootContainer.tagPath} + ':*'

** Completely untested, so it might need some tweaks **

3 Likes

We do something very similar with our popups... We have an alarm table (in a template) on the popup, and using the tagPath passed to the popup we create a source filter for that alarm table template.

Do you have an example of what that looks like?

Sure.

Basically we have been working on making out popups as responsive to the client as possible so we do this from a timer on the popup rather than an expression. Any how...

On the popup there is a custom property named "AlarmSourceFilter" that the Alarm table SourceFilter property is bound.

The code that generates a comma separated list of sourceFilters is:

def __setupAlarmFilter(event,rootContainer,**kwargs):
	'''
	Setups the alarm filter for a device
	
	Args:
		event: The event that triggered this check. Usually from a timer
		rootContainer: The root container for the window
	
	Return:
		Nothing
	'''
	logger = kwargs.get('logger',system.util.getLogger(__baseLogger))
	try:
		tagList = [rootContainer.Tag]
		
		alarmSource = ESP.Standards.Common.Alarming.Util.createSourceFilter(tagList)
		
		def updateGUI():
			rootContainer.AlarmSourceFilter = alarmSource
			
		system.util.invokeLater(updateGUI)
		
	except Throwable, t:
		ESP.exceptions.handleException(ex=t,logger=logger)
	except Exception, e:
		ESP.exceptions.handleException(ex=e,logger=logger)

Where the Root Container has a property called "Tag" which is the base tag for the popup.

The function called to generate the sourceFilter depends on a list of tag Paths and it looks like this:

@funcLogging(__baseLogger)		
def createSourceFilter(tagList,**kwargs):
	"""Creates a comma seperated string of alarm source filter tags for the list of tags provided"""
	logger = kwargs.get('logger',system.util.getLogger(__baseLogger))
	alarmList = [__alarmTag(x) for x in tagList]
	if len(alarmList) == 1:
		return '{}/*'.format(alarmList[0])
	else:
		return '/*,'.join(alarmList)

def __alarmTag(tagPath,**kwargs):
	'''
	returns the alarm tag in the prov:PROVIDER:/tag:TAG format
	If no tag is provided only the provider then the TAG is empty
	
	Example:
	__alarmTag([Development]Motors/C100/MTR)
		returns prov:Development:/tag:Motors/C100/MTR
	__alarmTag([Development])
		returns prov:Development:/tag:
	'''	
	logger = kwargs.get('logger',system.util.getLogger(__baseLogger))
	retData = 'prov:{}:/tag:{}'
	provSearch = re.search(r"(?<=\[).+?(?=\])",str(tagPath))
	prov = 'default' if provSearch is None else provSearch.group() #If no provider was provided, make the default the provider
	tag = re.sub(r"\[[^()]*\]", "", str(tagPath))
	
	return retData.format(prov,tag)		

This works well... I'm sure there are places we can optimize but it fits our needs at the moment and is pretty responsive for our vision clients.

Here's an alternative approach that scripts the conversation without a regular expression:

#tagPath = ... #custom prop value here
def getSourcePath(tagPath):
	sourcePath = tagPath.replace('[', 'prov:').replace(']', ':/tag:').replace('/Alarms/', ':/alm:', 1) + '*'
	return sourcePath
sourcePath = getSourcePath(tagPath)
1 Like

Where exactly are you putting this expression/script?

My apologies; I copied that conversion script from a post I made here without putting it into context. Using a parameterized popup window, I imagine that this would need to be adapted for the alarm status table's filterAlarm extension function. The script would look like this:

#def filterAlarm(self, alarmEvent):
	tagPath = self.parent.yourCustomProp #custom prop value here
	def getSourcePath(tagPath):
		sourcePath = tagPath.replace('[', 'prov:').replace(']', ':/tag:').replace('/Alarms/', ':/alm:', 1)
		return sourcePath
	if getSourcePath(tagPath) in str(alarmEvent.source):
		return True
	else:
		return False

...or perhaps even simpler:

#def filterAlarm(self, alarmEvent):
	tagPath = self.parent.yourCustomProperty #custom prop value here
	sourcePath = tagPath.replace('[', 'prov:').replace(']', ':/tag:').replace('/Alarms/', ':/alm:', 1)
	if sourcePath in str(alarmEvent.source):
		return True
	else:
		return False