Editing historian tag data

First of all, please don’t think I am saying that your are doing it wrong, IMO if it works then it isn’t really “wrong”. However, there are often more ‘reliable’, ‘performant’ and/or ‘more readable’ ways of doing things. That is what makes best practices, best practices.

You can read each tag individually, it will work, it is not the most performant way to do it.

This is the way I do it, it is not the only way to do it, nor is it probably the “best” way to do it.

So, here is how I do this. At the beginning of any script were I will be working with more than a few tags I build what I call a valueDictionary, if I will be modifying any tags I change them in the in the dictionary and then use that to write them all at the end of the script.

I keep these functions in the global scripting project.

I provide the functions with a list of tag paths and then if they happen to all share a common parent path I also provide that, the end result is a dictioary of values whose key is the tagName/path. If a parentPath is not provided then the full path will be used as the key.

Here is the script for creating the dictionary, I have mine in a shared project script called tagUtils

def createTagValueDict(tagPaths,parentPath):
	'''
	Called to read the current tag values of tagPaths provided in tagPaths, and 
	generate a dictionary where key is the tag name and the value is the read
	tag value.
	
	Arguments:
		tagPaths: List of tag paths to read tag values of
		parentPath: path to a folder containing all of the tags
	'''
	values = system.tag.readBlocking(tagPaths)
	tagValues = {}

	for valueIndex, qualifiedValue in enumerate(values):
		tagValues[tagPaths[valueIndex][len(parentPath):]] = qualifiedValue.value
		
	return tagValues

Here is the script for writing the values out of the dictionary

def writeTagValueDict(values,parentPath):
	'''
	Called to write values in a dictionary to the tags at path "parentPath" + key.
	
	Arguments:
		values: dictionary of values with tagNames as the key
		parentPath: path to the folder containing all of the tags.
	'''
	writePaths = []
	writeValues = []
	
	#if the given parenPath does not end with / then add it.
	parentPath = parentPath if parentPath[-1:] == '/' else parentPath + '/'
	
	for tag,value in values.items():
		writePaths.append(parentPath + tag)
		writeValues.append(value)
	
	system.tag.writeBlocking(writePaths,writeValues)

Usage would look something like the following:

tagPaths = ['parentPath/Tag1','parentPath/Tag2','parentPath/Tag3']
values = shared.tagUtils.createTagValueDict(tagPaths,'parentPath/')

if values['Tag1'] == values['Tag2']:
    values['Tag3'] += 1

shared.tagUtils.writeTagValueDict(values,'parentPath')

That is a very simplified example but hopefully you can see how much more readable values['Tag1'] is than values[0].value

If you would like a more detailed explanation of how this code works I would be happy to DM it to you.

1 Like