[POSSIBLE] How to filter history-only tags in the Tag Browse Tree

Like the title says, I’d like to get the Perspective Tag Browse Tree component to display only tags that have history enabled. It looks like it can be done (reading the javadocs) but I’m not exactly sure how to implement it.

Here is a link to the page I’m looking at with two relevant passages:

It seems like includeRealtimeWithHistory is the field I want to set to True, but how do I do that on the component’s filterBrowseNode extension function?

disclaimer newb so take what I say with a grain of salt. But I don’t think you’d be able to do this in the designers browser tree. I think you would need to design your own or build some sort of module.

The Tag Browse Tree does not allow for filtering the tags that are displayed, other than specifying a path under which you would like to see tags.

Well, ya learn something new every day…

After examining your link more closely, it looks like we do filter the nodes, but only the nodes at the level you specify.

I, for example, have multiple alarms in a directory: [default]_Symulation_/sine. To display those alarms, I had to specify that exact directory. Now, I needed to modify the filterBrowseNode component extension function. After enabling the extension function, I used this code:

	return len(node.attributes) > 0  # make sure your indentation is correct

I don’t know how safe this is becuase I don’t know what other potential attributes a tag could have, but this code worked perfectly in my setup at various levels, returning only tags which had an alarm, as it’s stored as an attribute of the tag (see the attributes entry below).

23:16:13.414 [Browser Thread: 51234] INFO Perspective.Designer.Workspace - TagDescription [name=Sine1, dataType=Float8, currentValue=[9.99984011283477, Bad_TrialExpired, Sun Jul 17 23:16:12 PDT 2022 (1658124972776)], objectType=AtomicTag, subTypeId=opc, attributes=[NodeAttribute[history]], hasChildren=false, displayFormat=#,##0.##, tooltip=null]

Unfortunately, that attribute is a HashSet - so I was unable to directly reference the value and identify the attribute as being related to History. Perhaps someone else could provide pointers for how to do that?

1 Like

C’mon guys, I was just messing around when I said this was impossible!

As you said, the return len(node.attributes) > 0 method doesn’t work in a real-world scenario, because many tags have alarms AND history (and most likely other attributes). I wouldn’t be able to tell if a tag has alarming or history turned on, only if it has one or the other or both.

EDIT: I looked at your answer again and can see that you CAN see that a tag has a history attribute - we just don’t know how to check against this value. This gives me some direction on what to research next!

It feels natural for this feature to already be included in the Tag Browse Tree because of the includeRealtimeWithHistory param.

You can just check the Id.

def filterBrowseNode(self, node):

	history = False
	for att in node.getAttributes():
		
		if att.getId() == "history":
			history = True
	return history
3 Likes
def filterBrowseNode(self, node):
	if node.attributes is not None:
		for attribute in node.getAttributes():
			if attribute.getId() == "history":
				return True
	return False
3 Likes
from com.inductiveautomation.ignition.common.tags.browsing import NodeAttribute
return node.attributes.contains(NodeAttribute("history"))
4 Likes

I think this might work… The thing I’m running into now is that my Tag Provider is nicely structured (based on a location model) with folders and such. If I add the above filter script to the Tag Browse Tree component, I get No results found because none of the top level folders (or any folder for that matter) have a history attribute even though they contain tags that do have history enabled that I would like to display.

@jpark @victordcq

So instead of returning False, also return nodes which are directories.

def filterBrowseNode(self, node):
	system.perspective.print(str(node))
	if node.attributes is not None:
		for attribute in node.getAttributes():
			if attribute.getId() == "history":
				return True
	return node.hasChildren()

OR

from com.inductiveautomation.ignition.common.tags.browsing import NodeAttribute
return node.attributes.contains(NodeAttribute("history")) or node.hasChildren()
8 Likes

After a simple test, I think this works! I’ll do a more extensive test later and report back if I find any other issues. Thank you @jpark, @victordcq and @cmallonee.

2 Likes

I'd like to piggyback on this thread if possible. I'm looking to do a similar filter on the tag browse tree, but allow users to filter by tag type and name. I'm able to filter parent nodes by name using the following script:

 def filterBrowseNode(self, node):
 	nameFilter = str.lower(str(self.parent.getChild("FlexContainer").getChild("TextField").props.text))
 	typeFilter = self.parent.getChild("FlexContainer").getChild("Dropdown").props.value
 	if nameFilter != "":
 		if node.objectType == "Folder":
 			return True
 		else:
 			if nameFilter in str.lower(str(node.fullPath)):
 				return True
			else:
 				return False
	else:
		return True

However, if you only type the name of a child node, since that string doesn't exist in the fullPath of the parent, no tags are returned. Is there a different way of approaching the filtering I could try?

Any chance you explain what this 2 lines are all about and where to place them to execute? Are they solving the filtering as well ?

They're an alternative way to get to the same results. Based on your question, the reasoning against using these lines instead is a bit more clear: they're more difficult to digest and understand. Both sets of code should get you the same result, but one of them is easier to read and understand.

I'm trying to utilize this exact filter, however I've found that if the tag has security enabled on it, the history attribute doesn't exist, even though the tag does have history enabled. The result being that any tag with security is filtered out...

Does anyone know why this might be the case and perhaps if there is a solution?