Race condition question Transaction group vs change event script

Can I do inserts from a transaction group and script resets on the same tags' change event scripts?

Example:
My workorder tag transaction group triggers the transaction group to collect my infeed value.
My workorder tag change script resets my infeed value.

Or will the be a race condition?
Do I need to both insert and reset from a tag change event script?
Is a tag change event script reliable enough for inserting to tables?

I wouldn't be surprised if it gives you grief in the future.

Is it possible to set up your PLC to reset the value instead of Ignition? I'd have the PLC reset the value once it receives a good/complete status from the transaction group.

If not, do everything from a Gateway tag change event script.

If you use a gateway tag change event then yes. We run several of our transactions this way because we need to split data collected into multiple tables. It also allows for more thorough handshaking, additional data processing, and additional actions after inserting.

A basic framework from pturmel :

Gateway Tag Change Event Transaction Framework
from java.lang import Throwable
logger = system.util.getLogger("SomeProject.someScript")

cache = {}
echoTagPath = '[someProvider]path/to/trigger/echo'
failTagPath = '[someProvider]path/to/failure/bit'
opcServer = "Ignition OPC UA Server"
opcItems = [... all the opc item paths to read together ...]
transactionSQL = """Insert Into "someTable" (t_stamp, ...  other columns ...)
	Values (CURRENT_TIMESTAMP, ... ? placeholders for values ...)"""

def myTransaction(initialChange, newValue, event):
	if initialChange:
		cache['lastEcho'] = system.tag.readBlocking([echoTagPath])[0].value

	# Check for zero, null, or duplicate trigger
	if not newValue.value or newValue.value == cache['lastEcho']:
		return

	# Set the cached last trigger early to prevent accidental retriggers
	# if the DB operations run long.  Also prevents retriggers after failure
	# unless the project is saved/restarted.
	cache['lastEcho'] = newValue.value

	# Obtain all of the data to record.  Check for all good.
	QVlist = system.opc.readValues(opcServer, opcItems)
	if all([qv.quality.good for qv in QVlist]):
		# extract all the values and submit the SQL
		params = [qv.value for qv in QVlist]
		try:
			# Possibly use system.db.runSFPrepUpdate() instead.
			system.db.runPrepUpdate(transactionSQL, params)
			system.tag.writeBlocking([echoTagPath], [newValue.value])
		except Throwable, t:
			# Log and set failure handshake
			logger.warn("Java Error recording transaction", t)
			system.tag.writeBlocking([failTagPath], [True])
		except Exception, e:
			# See https://www.automation-pros.com/ignition/later.py
			logger.warn("Jython Error recording transaction", later.PythonAsJavaException(e))
			system.tag.writeBlocking([failTagPath], [True])
	else:
		# Log failed OPC reads
		failed = [(item, qv) for (item, qv) in zip(opcItems, QVlist) if not qv.quality.good]
		logger.warnf("OPC Read Error(s) for transaction: %s", repr(failed))
		system.tag.writeBlocking([failTagPath], [True])
1 Like

Thanks

I like to trend the PLC value for diagnostics.
I am resetting a memory tag, positive increment counter of the PLC value.
So I would not reset from the PLC in this case.


That script seems great for letting you insert to different tables.
I am hoping that is more than I need.

I am thinking about using the tag change scripts so that I have easy access to the previous value without having to depend on an additional script and tag.

Gateway tag change scripts also have access to the previous value.

2 Likes

Where is the transaction being called?

except Throwable, t:
			# Log and set failure handshake
			logger.warn("Java Error recording transaction", t)

Is this for a special logger or Ignition's builtin?
Because I am getting an error that Throwable is not defined when attempting to use it.


Going to try this instead.

You're writing a Gateway Tag Change event script. Essentially you are writing the transaction from scratch. The event is triggered based on what tag's you assign to the event.

Throwable is a Java type, so you have to import it into Jython

1 Like

I tried

from java.lang import Throwable
logger = system.util.getLogger("mylogger")
Line = "test"

try:
	# Placeholder
	 raise Throwable("Testing Throwable exception")
	#system.db.runPrepUpdate(queryWOEnd, args)
except Throwable, t:
	logger.warn("Demo workorder script queryWOEnd failed for Line " + str(Line), t)

It compiles, but I don't see the output in the logs.

Where are you running it? If the designer script console, it will only show up in the designer's log viewer, not in the gateway.

1 Like

Thanks