Parameter not updating after using system.tag.writeBlocking() to replace values on a custom property

Was given a CSV file with two columns. 1st column is a list of tag paths where a custom property is to be changed. 2nd column is what we need to change that custom property's value too.
example:
col1(key): folder1/folder2/folder3/tag.customPropertyName
col2(Value): {site}.{service}::{another parameter}

I got the value in the customer property to change. The issue is ignition does not automatically update the parameters.

Here is what we found out so far:

  1. if we go into the customer parameter and add any char, like a space, apply. then go back in delete that char. apply again. The parameter will then take effect.
  2. when we exported the tags. We noticed that the tags we changed manually had a bindType: "parameter" part in the dictionary output but the rest we did not manually change did not have this.

I used the dictionary scrip below to change the values.
Is there a better way to do this, like should I use system.tag.configure instead?

> import csv
> 	#    file path TODO: make dynamic
> 	path = r"C:\Users\UpdateTags_tagEdit.csv"
>     
> 	# Variables
> 	path_ig = {}
> 	
> 	# Read in CSV file : 
> 	with open(path, mode='r') as tags:
> 	    readin = csv.reader(tags, delimiter=",")

> 	    for cols in readin:
> 	        path_ig[cols [1]] = cols [2]

> 	for key,value in path_ig.items():

> 	    # Update .customProperty description for each tag
> 	    system.tag.writeBlocking(path_ig.keys(),path_ig.values())

Writing to custom properties writes the simple value, no binding. I think you need to use system.tag.configure to get more sophisticated than that.

1 Like

Thanks for the quick reply! Thank you so much, I am new to ignition. I was thinking the same thing, and starting to try out some other things now.

I have a follow up question. IT seems the system.tag.configure has this param for its first argument:

String basePath - The starting point where the new Tags will be created. When making changes to existing Tags with this function, you want to set the path to the parent folder of the existing Tag(s), not the Tag(s) themselves.

I need to update specific tags inside of the folders and not all of the folder's tags themselves. Is this still the best option to accomplish this task?

I was able to successfully update our custome property using system.tag.getconfigure
but when I try to use system.tag.configure it does not update the tag itself.

Here is the new code:

def runAction(self, event):
	
	import csv
	
	path = r"C:\Users\YourCsvFile.csv"
	
	with open(path, mode='r') as tags:
		readIn = csv.reader(tags, delimiter=",")
        # ignores headers
		next(readIn,None)
		
		for tag in readIn:
			# get first column in csv file(paths to each tags that needs updating)
			parentPath = tag[0]
			 
			# Get the current configurations recursively, which is useful when targeting
			configs = system.tag.getConfiguration(parentPath, True)

			# updates tag customProperty with the 2nd column in our CSV file. 
			configs[0]['customProperty'] = tag[1]
			
		    # updates current tag path with the current updated custom property the configs
			system.tag.configure(parentPath, configs, "o")

Others have more experience with the corner cases, but when trying to manipulate one property of each tag, you probably do not want to use system.tag.getConfiguration, but generate the changes dictionary(ies) yourself.

Numerous related topics.

closest I got was the following code. Issue is this doesn't not update the config info in the background. When we export the tags to check the data we get the following(two ways)
Config back ground should be the follow using the system.tag.configue:

{
"CustomProperty": { bindType='parameter', binding='{param1}.{param2}::{param3}_RandomLetters'}
}

The outcome we get is this:

{
"CustomProperty ": "{bindType\u003dparameter, binding\u003d'{param1}.{param2}::{param3}_RandomLetters'"}",
}

vs
Using system.tag.writeBlocking we get the following:

"CustomProperty": "{param1}.{param2}::{param3}_RandomLetters"

system.tag.writeBlocking would be perfect but unfortunately this takes out two import aspects
"CustomProperty": { bindingType = , binding= }

bindingType = should say 'parameter'

binding= Should have he parameters ignition will know to look for in the UDTs.

If someone can figure out how to access the binding value please tag me in the solution if you are reading this.

Code for system.tag.configure:

def runAction(self, event):
	
	import csv
	
	path = r"Your csv File Path.csv"
	
	with open(path, mode='r') as tags:
		readIn = csv.reader(tags, delimiter=",")
	# ignores headers 
		next(readIn,None)
	
		for rows in readIn:
			parentPath = rows[0]
	
	        # gets the configurations of folders
			configs = system.tag.getConfiguration(parentPath, True)

	
	        # check each tag in folders: has random print checks
			for tag in configs[0]['tags']:
                # check for correct tag name
				if str(tag['name']) == rows[1]:
					system.perspective.print("Check Tage name: " + str(tag['name']))
					system.perspective.print("Check csv col name: " + str(rows[1]))
				
					try:
						system.perspective.print("BEFORE CustomProperty update: " + str(tag['CustomProperty']))
						tag['CustomProperty'] = '{bindType=parameter, binding='+ str(rows[3]) + '}'

                        # updates CustomProperty value
						system.tag.configure(parentPath, tag, "o")

						system.perspective.print("AFTER CustomPropertyupdate: " + str(tag['CustomProperty']))
						system.perspective.print(tag)
					except KeyError:
						pass

You're literally setting the custom property to a string which is why it's a string when you export it out again. You need to set it to a python dict.

E.g.

tag['CustomProperty'] = {'bindType': 'parameter', 'binding': 'str(rows[3])'}
1 Like

Nick you are the Bomb Dot Com! I had done something similar to that but I used equal signs instead of colons after "bindingType" and "binding" which gave me an error and I do not know why my brain thought to do it that way. Thank you so much!

Final code if anyone needs(I had to add an additional try except to skip over tags that do not need updating):

def runAction(self, event):
	"""Grabs Tag paths, updates CustomProperty description with new value.  
	
	• Currently grabs the 2nd column as the key (tag Path, but not including tag name)
	• Currently grabs 3rd columns as the tag path(based on the getconfig function u' path)
	• Currently grabs 4th column as the value to be replaced
	
	""" 
	
	import csv
	
	path = r"C:yourfile path"
	
	with open(path, mode='r') as tags:
		readIn = csv.reader(tags, delimiter=",")
	# ignores headers 
		next(readIn,None)
	
		for rows in readIn:
			# path of folders and main Tag E.G: [Tag Provider]folder1/folder2/folder3/folder4
			parentPath = rows[1]
	
	#            gets the  configurations of folders
			configs = system.tag.getConfiguration(parentPath, True)
				
#	# check each tag in folders
			try:
				# checks for each tag if not there it will skip over that tag and go to the next
				for tag in configs[0]['tags']:
					# tag name is just the name of tag E.G.: u'path': tagName
					if str(tag['name']) == rows[2]:
	#					system.perspective.print("Check Tage name: " + str(tag['name']))
	#					system.perspective.print("Check csv col name: " + str(rows[1]))
					
						try:
	#						system.perspective.print("BEFORE CustomProperty update: " + str(tag['CustomProperty ']))
	
							# change our custom property using a dictionary
							tag['CustomProperty '] = {'bindType': 'parameter', 'binding': str(rows[3])}
							#updates the configs for the tag property
							system.tag.configure(parentPath, tag, "o")
							
							
	#						system.perspective.print("AFTER CustomProperty update: " + str(tag['CustomProperty ']))
							system.perspective.print(tag)
						except KeyError:
							pass
			except KeyError:
				pass