Modifying tag paths in gateway tag change event from jython?

Is it possible to add/remove tag paths within a gateway tag change event from jython?

I don’t think so. But you can probably construct what you need around the TagChangeListener interface. You’ll have to be real careful with code lifetimes, as a script module edit won’t automatically replace the implementation of listeners.

Right, looks like TagSubscriptionManager could help too. How do I get at the GatewayContext from jython?

And in GW tag event script event.getTag().getConfigProvider() is halfway there but .getGatewayContext() is protected.

from com.inductiveautomation.ignition.gateway import SRContext
context = SRContext.get()
2 Likes

heh… well that brought down the server.

Yeah, I’m pretty confident the SRContext class is protected for a reason. I’ve noticed it bring down the webserver a few times while testing various functions around it.

Thanks guys.

from com.inductiveautomation.ignition.common.sqltags.model.event import TagChangeListener
class IgnitionTagChangeListener(TagChangeListener):
	def getTagProperty(self):
		return None
	def tagChanged(self,e):
		logger = system.util.getLogger("activemq")
		logger.info("IgnitionTagChangeListener.tagChanged()")
		logger.info(str(e))
				
from javax.jms import MessageListener
class IgnitionMessageListener(MessageListener):
	def onMessage(self,message):
		logger = system.util.getLogger("activemq")
		logger.debug("[message arrived] " + str(message))
		logger.info("[message arrived] content => " + message.content.getData().tostring())
		
		from com.inductiveautomation.ignition.gateway import SRContext
		context = SRContext.get()
		tagManager = context.getTagManager()
		
		fullTagPath = message.destination.getTopicName().replace('topic://','').replace('.','/')
		
		if not system.tag.exists(fullTagPath):
			partition = fullTagPath.rpartition('/')
			parentTagPath = partition[0]
			tagName = partition[2]
			system.tag.addTag(parentPath=parentTagPath, 
				name=tagName, 
				tagType="MEMORY", 
				dataType="String")
		
		from com.inductiveautomation.ignition.common.sqltags.parser import TagPathParser
		
		tagPath = TagPathParser().parse("default",fullTagPath)
		listener = IgnitionTagChangeListener()
		
		tagManager.subscribe(tagPath,listener)
		
		system.tag.write(fullTagPath,message.content.getData().tostring())

You definitely need to keep track of what listeners you’ve created and attached in a safe place, only system.util.getGlobals() comes to mind. You need to have mechanisms to remove the listeners when you’re done with them, and to remove the old ones when you edit scripts. All of this is extraordinarily dangerous, as you’ve discovered.

Yes, that is all next on the list.

When scripts are edited and gateway projects restart, wouldn’t all the listeners be destroyed anyway?

No. Memory leak, and unexpected extra actions.

ok, that will be simple enough since I’m worried only about a single tag tree branch.

I thought globals are module scoped now, with no real global global?

system.util.getGlobals() is a truly global dictionary independent of script module edits and restarts. It is the dictionary that old-style scoped globals would get. Note that if you put a jython class object or instance or other callable in that dictionary, that version of the code stays there until you deliberately replace or delete it. Same is true of attaching java-extending jython objects as listeners or other callbacks on any java object. That version of that callable stays until deliberately removed. If your script module init blindly adds such a listener, you’ll end up with multiple listeners simultaneously.