[BUG] Imported tag quality showing as Bad_Disabled when Enabled


I’ve imported a whole bunch of tags from another gateway into a new gateway and having lots of issues…
Lots of UDT instances have imported and their tags are showing as Bad_Disabled when in fact they’re enabled… If I overwrite them to disabled and then remove the override they come good. In the past i’ve seen this before and I could just do a tag restart which would force them to read properly, but not this time :confused: I should have budgeted a lot more for this upgrade… I have similar issues with bindings becoming “stuck” with old values as well…


I tried deleting some of the tags and re-importing back in, but no change.
The only way I found to get this unstuck and enabled was to disable the root UDT instance and re-enable it (e.g. “Common”). Time to write a script…

In case it helps anyone else:

This will collect all root (non-nested) UDT Instance tag paths and disable and re-enable those that aren't already disabled.
This will fix "stuck" tags part of UDT instances that won't come good.
import time
import math

processNestedUDTInstances = False
processDisabledUDTInstances = False # DO NOT ENABLE UNLESS YOU KNOW THE RISKS

basePath = '[default]'
# found that writing all at once didn't fix some of the tags, so write them slowly in groups instead :/
tagWriteGroupSize = 10
tagWriteDelaySecs = 1

# get all UDT instance tags
UDTI = system.tag.browse(basePath, filter={'recursive': True, 'tagType': 'UDTInstance'}).results
# get a list of just the fullPaths
UDTI_TagPaths = [str(tag['fullPath']) for tag in UDTI]
# sort it alphabetically so we can remove nested UDT instances efficiently
UDTI_TagPaths = sorted(UDTI_TagPaths)

# loop through all UDT instance tag paths and add them into a new list if any item in the new list isn't in each of the tag paths.
# this effectively checks if the tag path is nested within any of the other tag paths already added to the new list.
### remove this for loop if you want to process ALL UDT instances, nested or not. ###
UDTI_Root_TagPaths = []
for tag in UDTI_TagPaths:
	if processNestedUDTInstances or not any([tagpath in tag for tagpath in UDTI_Root_TagPaths]):

# read the current Enabled status of each UDT Instance so that we don't inadvertently affect UDT instances that *should* be disabled.
disabledStatuses = system.tag.readBlocking(['{}.Enabled'.format(tag) for tag in UDTI_Root_TagPaths])
# get just disabled status values.
disabledStatuses = [tag.value for tag in disabledStatuses]

# remove the already disabled UDT instance tag paths from the list
UDTI_Root_TagPaths_NotDisabled = [tag for tag, state in zip(UDTI_Root_TagPaths, disabledStatuses) if processDisabledUDTInstances or state == True]
print 'Not disabled tag count: ', len(UDTI_Root_TagPaths_NotDisabled)
print "Already disabled tag count (these won't be processed): ", len(UDTI_Root_TagPaths)-len(UDTI_Root_TagPaths_NotDisabled)

# create a list of the UDT instance enabled tag paths
UDTI_Root_EnableTagPaths = ['{}.Enabled'.format(tag) for tag in UDTI_Root_TagPaths_NotDisabled]

# finally, disable them and re-enable them
print 'Disabling all UDT instances...'
system.tag.writeBlocking(UDTI_Root_EnableTagPaths, [False]*len(UDTI_Root_EnableTagPaths))

loopCount = int(math.ceil(1.0*len(UDTI_Root_EnableTagPaths)/tagWriteGroupSize))
totalSize = len(UDTI_Root_EnableTagPaths)
print 'Enabling UDT instances slowly in groups of ', tagWriteGroupSize
for index in range(loopCount):
	firstIndex = tagWriteGroupSize*index
	lastIndex = tagWriteGroupSize*(index+1)
	if lastIndex > totalSize: lastIndex = totalSize
	print 'Writing tag indexes: ',firstIndex, '->', lastIndex-1
	system.tag.writeBlocking(UDTI_Root_EnableTagPaths[firstIndex:lastIndex], [True]*len(UDTI_Root_EnableTagPaths[firstIndex:lastIndex]))

and this script to check if there are any remaining tags that are Bad_Disabled which are in fact Enabled:

This will check to see if there are any tags that are "stuck" with a Bad_Disabled quality when the tag is enabled.
import time
import math

basePath = '[pckg_barrelWashLine]Wolf Blass/Packaging/Barrel Washing/Stations'

# get all tags
tags = system.tag.browse(basePath, filter={'recursive': True, 'tagType': 'AtomicTag'}).results
# get a list of just the fullPaths
tagPaths = [str(tag['fullPath']) for tag in tags]
# sort it alphabetically
tagPaths = sorted(tagPaths)

# read the current quality status of each tag path.
tagPaths_qual = system.tag.readBlocking(['{}.Quality'.format(tag) for tag in tagPaths])
# get just disabled status values.
tagPaths_qual = [tag.value for tag in tagPaths_qual]

# read the current Enabled status of each tag path.
tagPaths_en = system.tag.readBlocking(['{}.Enabled'.format(tag) for tag in tagPaths])
# get just enabled status values.
tagPaths_en = [tag.value for tag in tagPaths_en]

badDisabledTagPaths = []
for t,e,q in zip(tagPaths, tagPaths_en, tagPaths_qual):
	if e and str(q) == 'Bad_Disabled':
		print t