Script to Browse OPC and Create Tags

Hello again everyone

I’ve got a client who has about 5000 tags in their OPC-DA server. I only really care about 200 of them. I have to make tags for all of them, but who wants to make that many by hand when the computer can do it for you? Also, they have 300 sites, so I’d prefer to get this script working so I don’t have to make 5000 tags manually. The good thing is that all their tags are located in one directory, JAXHISTORIANP, and follow the same naming convention: [3 letter division]+[site name]+[Specific tag name]. In this instance, I care about the tags that start with “MED Cabarrus”, so this is what I have so far:

server = 'JaxHistorianP OPCDA'
item = "MED Cabarrus*"

tags = system.opc.browse(opcServer = server, folderPath = path, opcItemPath = item)
for row in tags:
	newTagName = row.getOpcItemPath()
	newTagType = row.getType()
	newTagDataType = row.getDataType()
	system.tag.addTag(parentPath = "Cabarrus", name=newTagName, tagType=newTagType, dataType = newTagDataType,attributes={"OPCServer":server, "OPCItemPath":newTagName})

I keep getting read timeouts. Even if I narrow it down to one specific tag, I still get a timeout. I changed the timeout for the server in the gateway and within the designer itself to 10 minutes, but it’s still the same result.

If I do:

server = 'JaxHistorianP OPCDA'
path = '\\\JAXHISTORIANP\MED Cabarrus Clean Stone Bin 03 Loads'

system.tag.addTag(parentPath = "Cabarrus", name="asdf", tagType="OPC", dataType = "Int4",attributes={"OPCServer":server, "OPCItemPath":path})

everything works out.

So any help to get this script to work would be incredible.



1 Like

You probably need to switch to using the browseServer function as explained here.

Thanks for the suggestion, Kevin. I’m able to see the tags I want now! I’m still having a little trouble getting the datatype of each of the tags to work when adding them. Here’s what I have:

server = 'JaxHistorianP OPCDA'
prefix = "MED Cabarrus"

tags = system.opc.browseServer(server, path)
for tag in tags:
	tagName = tag.getDisplayName()					#Tag Name
	tagRawDataType = tag.getDatatype()				#Data type with extra java juice on it
	if prefix in tagName:		
		opcPath = tag.getDescription()				#OPC Path
		system.tag.addTag(prefix, name = tagName, tagType= "OPC", dataType = tagRawDataType,attributes={"OPCServer":server, "OPCItemPath":opcPath})

So this is all fine and dandy but for my datatypes that function returns java.lang.Float or whatever else there is there (hence my java juice comment).

I tried just doing a split or rfind to give me just the datatype at the end, but I get an error saying type object 'java.lang.Float' has no attribute 'rfind'

I’ve dug up all the other hidden gems I needed from .browseServer, but I guess I don’t have a good enough shovel for this one.

Appreciate it!


Try something like this…

from com.inductiveautomation.ignition.common.sqltags.model.types import DataType

... do your browse and get tagRawDataType ...

dataType = str(DataType.getTypeForClass(tagRawDataType))

Thanks for your help man. Real lifesaver :v:

In case anyone a year or two from now needs the final script:

def createTagsFromOPC(server, path, prefix, ignitionDir):
	from com.inductiveautomation.ignition.common.sqltags.model.types import DataType
	#server 															#OPC Server Name
	#path																#Directory tags are in on the server
	#prefix																#What the tags I'm looking for start with
	#ignitionDir														#Where I want the tags to go in Ignition. Optional maybe? Idk just make good folder structure
	totalTagsCreated = 0
	totalTagsSkipped = 0
	tags = system.opc.browseServer(server, path)
	for tag in tags:
		tagName = tag.getDisplayName()									#Tag Name
		tagRawDataType = tag.getDatatype()								#Data type with extra java juice on it
		tagDataType = str(DataType.getTypeForClass(tagRawDataType))		#Datatype to use in addTag
		if prefix in tagName:
			opcPath = tag.getDescription()								#OPC Path
			tagPath = '' + ignitionDir + '/' + tagName
			if system.tag.exists(tagPath):
				print tagPath + " already exists and was skipped"
				totalTagsSkipped += 1
					system.tag.addTag(ignitionDir, name = tagName, tagType= "OPC", dataType = tagDataType,attributes={"OPCServer":server, "OPCItemPath":opcPath})
					print tagName + " was created"
					totalTagsCreated += 1
					print tagName + " was not created. This tag most likely contains illegal characters in its name. Please try to create it manually."
					totalTagsSkipped += 1
	print "Tags created:"
	print totalTagsCreated
	print ''
	print "Tags skipped:"
	print totalTagsSkipped
	print ''
	print ''
	print 'Shoutout to Kevin Herron from Inductive Automation for his help'
	print ''

I made it a global function so it can be accessed anywhere from the gateway

server = 'JaxHistorianP OPCDA'
prefix = "MED Cabarrus"
ignitionDir = "MED Cabarrus"

shared.Reuse.createTagsFromOPC(server, path, prefix, ignitionDir)

Hope this helps you, programmer from the future.



I was adding the ability to check and see if the ignitionDir folder existed and if not it would make it, but I ran the script to early and found out that the current script will do this for you.

In case you were wondering :+1:

I’ve been trying this solution but the .getDescription() function has not been returning any OPC Paths. I see that in the Gateway scope it returns a PyOPCTag which does not have this function, but in the Client scope it is supposed to return an OPCBrowseElement, which does have this function. I’ve tried moving my code into the Client scope but I can’t seem to get the actual OPC item Path.
Has system.opc.browseServer been changed since this post?

I don’t know what OP was doing with getDescription(), but that does not contain the NodeId / OPC Item Path - getNodeId() does.

Thank you for the reply, this has helped me make some progress. I’m now trying to combine the example you gave of the recursive browsing and this process to make the folders and tag structure for a given OPC path.
Thanks for the examples.

did you resolve this? Would you be willing to share your script?