[IGN-15470]Is it possible to reset a tag property to default in scripting?

I am making a platform for a client, in which tag values get displayed in certain views, based on each tag’s Function, a custom property I added. Users are able to configure each tag’s function in a designated screen.

However, when a property’s value is changed and changed back to default, it is shown as “Overrides Parent Properties”, despite being the same value as default. While testing this new functionality, I used different tags that now all show as ‘Overriden’, while the values are original.

As the title reads; Is it possible to reset the tag property to default, in scripting?

image

Have you tried writing a jython None to that property?

1 Like

I had not tried that, but I have now. It still shows the Override symbol in the tag browser, and the green circle in the tag editor.

image

image

You should be able to read the default value from the UDT definition and then write it? Otherwise, can you read the JSON to find the override, remove it, and then write it back? I haven’t done much with the JSON tag stuff but I know the override information is in there somewhere.

You may have to use system.tag.configure() to write the None.

I’m sorry, I wasn’t really giving an insight into what I was doing.

config = system.tag.getConfiguration(inputPath, True)
config[0]["_Function"] = 2
system.tag.configure(parentPath, config, 'm')

inputPath is the path to the tag containing the _Function property.

parentpath is inputPath’s parent.

Whenever you feed the output of system.tag.getConfiguration() back into system.tag.configure(), you get lots of unexpected overrides.

Construct a list of one configuration dictionary with just the tag name and the props you want to override, and then use system.tag.configure() with merge mode.

1 Like

If I may go into this a bit more.

getConfiguration will get the JSON definition of the select tag path. It will contain at a minimum the names and types of the nodes (tags/UDT insts/folders etc) within it, along with every property value that has been configured by the user – these are all essentially overrides to the default values (note that a default value can be overridden to the default value itself). For tags within UDT instances, it will also include the user-set values for their props as well, both from overrides placed on the instance as well as those set within the definition. So if you then go to write this all back to the system, the UDT instance tags will have overrides configured on their tags that were originally only defined in the UDT definition and not at the instance level. This has the effect of essentially decoupling that config from the UDT definition, as those values are now overridden at the instance. This is the danger of using getConfiguration with configure as then changes to those props on the definition will no longer propagate to the instances.

The minimum that you need to supply to the configure function is the name of the nodes you want to affect (and the structure to them). With the merge option, you can then add the props that you want to modify into the node/tag dicts and it will only set prop overrides for those props. Be sure to set it to merge though otherwise you will clear all other config on those tags

2 Likes

Wow, okay. Since I couldn’t find any other thread on the forum about this subject, I assumed nobody had the same issue. I’m positively surprised that I’m now learning about a function of which I initially thought “Yeah lets give this a try” (system.tag.configure())

I had noticed this during my quick tests yesterday, but wasn’t sure whether I was hallucinating or ‘random’ properties were being shown as overriden without changing value. Thank you for confirming I’m not going crazy.

But I can’t get them through system.tag.getConfiguration(), right? Since that would cause the same issue, just on a smaller scale?

I’ll be trying some things out and report back later this week. Thank you, gentlemen.

When using merge mode, you only have to supply the properties you wish to change (and the name, to apply to the correct tag). system.tag.getConfiguration() gives you everything that is there, including default values for things that aren't overridden. If you don't want to change these properties, don't feed them back into system.tag.configure().

1 Like

Following on from Phil, you can use system.tag.getConfiguration to pull the tag structure itself if you don't know it or need it to be dynamic, but you should first be cleansing every tag that is returned by removing the props other than the name and tags objects, depending what parts of the returned structure you actually need. Then you can add the props and their values that you want to change. You could technically also use the other tag browse functions like tag.browse and tag.query (memory’s off on that one - I havent been at work for a while, on long service leave), however with these you will need to create the folder structures from the tagpaths yourself which is doable, but more effort.

Note also, that configure is only needed to be used to set read only configuration or to add binding types to prop values (and some other situations like to remove prop values). If you just want to write to read write prop values (ie set prop value overrides) or write to the value of tags, then you can and should use tag.write

1 Like

I do feel like I’m learning a lot about how system.tag.configure() works, but I don’t think it’s the solution to my original answer.

I really hope I’m not missing an important detail one of you already shared in this thread. I’m really trying to understand, but I feel like I’m missing something.

When initialised, the _Function property has a value of 2:

image

Originally, I changed the value through system.tag.writeBlocking([path],[value]) This, logically, would show the value as overriden.

image

If I would then change it back to 2, through the same function, it would still show overriden.

image

What I then tried, but did in the incorrect way, was using system.tag.configure()

The value is currently still showing Overriden.

Writing None changes the value to null:

params = [{'_Function': None, 'name': 'tagName'}]
system.tag.configure(parentPath, params, 'm')

image

Writing 2 directly after, sets the value correctly, but still shows Overriden:

params = [{'_Function': 2, 'name': 'tagName'}]
system.tag.configure(parentPath, params, 'm')

image

Thank you again for your time. I really appreciate your input.

It’s still showing overridden when you set it to 2 because it’s still a value that exists in the instance of it. You need to remove the value prop altogether from the UDT instance json. In this case, it’s a lot more difficult a task programmatically, since you need to get the local json definition and not the full definition. The local definition being exactly what you would get from right clicking on the UDT instance and copying the JSON. This is the exact reason I requested the getLocalConfiguration in Paul’s extensions module

Do you actually want to do this programmatically, or are you just trying to get it done using any way?

To do it manually, you can right click on the UDT instance, copy json. Paste into notepad, find your tag and remove the value prop. Save the file as a json file, and then reimport it back into the designer using overwrite

1 Like

My first step in the process was to get it done in any way, to see if it was possible. Step 2 would be to do it programmatically.

Thank you for your clear explaination. It’s like you guys are peeling away Ignition’s software layer by layer, showing me how ignition really works.

I suspect that you are hitting a corner case because the target property is custom. It doesn't have a platform definition or 3rd party module definition that would indicate what the default value is. That it exists in the UDT definition should provide the default for this case, but doesn't. :man_shrugging:

I suggest you open a support ticket so this can be investigated properly.

I’m going to circle back to this. If you read the entire UDT definition using the path to the UDT definition you get JSON with the default values. Why not read that UDT definition and then pull out the members that you want and write the individual tags to the instance?

edit: nevermind, I see that the issue is not getting the default value into the UDT instance but getting rid of the override marker.

Not that it should be this difficult, but an example of how to make this work is as follows. Use this only as a guideline as it is a VERY basic example of how it can be done:

# Update the provider as needed
provider = 'default'

# Query to find all UDT Members that have overrides
query = {
  "options": {
    "includeUdtMembers": True,
    "includeUdtDefinitions": False
  },
  "condition": {
    "attributes": {
      "values": [
        "override"
      ],
      "requireAll": True
    }
  },
  "returnProperties": [
    "tagQueryOverrides"
  ]
}

results = system.tag.query(provider, query)

# For all items that have overrides
for result in results:
	# Generate a list of all the overrides
	overrides = [item.strip() for item in result['tagQueryOverrides'].split(',')]
	
	# Query again returning the singular tag we are working with ensuring that we are returning overrides in the query
	query1 = {
        "options": {
        "includeUdtMembers": True,
        "includeUdtDefinitions": False
      },
      "condition": {
        "path": result['fullPath'].toStringFull(),
        "attributes": {
          "values": [],
          "requireAll": True
        }
      },
      "returnProperties": overrides
    }
	results1 = system.tag.query(provider, query1)

	# Process the results to construct a dictionary of all the overrides values being returned
	for result1 in results1:
		overrideVals = {'name': result1['name']}
		
		for override in overrides:
			if override == 'value':
				# Special handling is needed for values (and potentially others, including alarms) because a Qualifed Value is returned 
				overrideVals[override] = result1[override].getValue()
			else:
				overrideVals[override] = result1[override]
		# Example of removing a specifc override
		del overrideVals['value']
		
		# Log to show what is being set for the member tag definition
		print('Writing {0} to tag {1}/{2}'.format(overrideVals, result1['fullPath'].getParentPath(), overrideVals['name']))
		
		# Write configuration to the member tag, overwriting the existing definition
		system.tag.configure(result1['fullPath'].getParentPath(), overrideVals, 'o')

An internal ticket has been created to try and make something easier to achieve. Let me know if you have any questions.

2 Likes

Check @paul-griffith ‘s ignition extensions module as this already has a function getLocalConfigurarion which returns exactly what you get when you right click on a UDT instance and copy the json. Ie you get the basic tag structure and any overridden prop values applied for the instance; you don't get any overridden prop values defined in the UDT definition itself. I’ve always wanted this to be a part of the product rather than within a 3rd party module which doesn’t work on edge. That and the isAvailable expression function which is an absolute necessity imo, which checks if a tag is both not disabled and exists – ie the two conditions which might hide a graphical element for a UDT that supports multiple configurations. Without having this in a single function requires a surprisingly difficult and overly complicated expression!