Adding post-delay to query tag

Hi,
I have a query tag:
‘’‘SELECT MIN (New_Tag)
FROM [Production].[dbo].[tests]’’’
that must be executed 5 seconds after the AUTO tag is true.

I tried the following:

‘’'from time import sleep
sleep(5)
start = system.tag.readBlocking ("[default]AUTO")[0].value

if start ==1:
SELECT MIN (New_Tag)
FROM [Production].[dbo].[TESTS]’’’

but it does not work. Any ideas?

I think the general consensus around here is to avoid time.sleep() whenever possible. Try replacing it with system.util.invokeLater or system.util.invokeAsynchronous. I think usually invokeLater is reserved for GUI interactions so I think invokeAsynchronous is what you should try.

EDIT : Evidently system.util.invokeLater is not available in tag scripts as @bakarabinchak.psi mentioned*
Use a tag event script on value change of your AUTO tag. When the AUTO tag goes true, run your query as a named query then write the results to a memory tag instead of using a query tag.

if currentValue.value:
	def runQuery():
		results = system.db.runNamedQuery(myQuery,{})
		system.db.write(memoryTag,results)
	system.util.invokeLater(runQuery,5000)

I got it to work but not sure if this is a best practice.
In AUTO tag event script

if currentValue.value:  
  shared.test.delay()

in shared.test.delay() script

def delay():
	now = system.date.now()
	future = system.date.addSeconds(now,5)
	while(1):
		if system.date.now() == future:
			system.tag.write('Testing/delayedTag',1)
			break

You would run your query then write results to a memory tag when the current time is 5 seconds in the future.

dkhayes117, thank you very much for your efforts.
I could not make your first script (the one using system.util.invokeLater) working, though there were no errors.
Regarding your second proposal, where the db query part must be inserted?

def delay():
	now = system.date.now()
	future = system.date.addSeconds(now,5)
	while(1):
		if system.date.now() == future:
			results = system.db.runNamedQuery(myQuery,{})
		        system.db.write(yourMemoryTagPath,results)
			break

You could use an expression tag to monitor the timestamp of when the AUTO bit turns on.

{[.]Auto} && (secondsBetween({[.]Auto.Timestamp}, now()) >= 5)
1 Like

You have re-implemented time.sleep() in a horribly CPU-burning way. Without addressing the reason sleep is bad: it ties up anything else that needs to run on that shared thread or in that work queue.

Don't do it. Use state machines and either timer scripts or scripts triggered repeatedly by scan class/tag group. If a state machine cannot handle your case (really freaking rare), use a sleep only in an asynchronous thread.

2 Likes

Noted, thanks!

OK, trying to wrap all that have been said above, can somebody tell me why the following tag change script does not work on condition that it is working on the script console:

‘’'if previousValue.value == 0 and currentValue.value == 1 and initialChange == False:
def runThisLater():

		ss = system.tag.readBlocking(["[New]StartCount"])[0].value
	system.tag.writeBlocking(["[New]Trigger"],[ss])     

system.util.invokeLater(runThisLater, 5000)'''

Firstly, you don't need both the previous and current values. This is a tag change event, so if current value is true, then the previous value must be false in order for it to trigger. Secondly, invokeLater() is not available for use in a tag change event. I think it is only for client scripting not gateway scripts. Use Jordan's suggestion.

Put a tag change event on the expression tag above like so

if currentValue.value  and not initialChange:
	results = system.db.runNamedQuery(myQuery,{})
	system.db.write(memoryTag,results)

Still does not work.
The outcome of:
‘’‘results = system.db.runNamedQuery(myQuery,{})’’’
is dataset, which cannot be written to the memoryTag.
By the way, is “system.db.write” included in 8.04? I could not find it when i was checking the syntax.

system.db.write() is a v7.9 function. v8.0.x is writeBlocking() or writeAync() You’ll want to use the writeBlocking() one I believe. Make sure your memory tag is of dataset type. It should work.

system.db.write isn’t a valid function anywhere. system.tag.write will work in 7.9 or 8.0; in 8.0 it just automatically calls system.tag.writeAsync.

I can’t believe I missed that. Yes it should be system.tag not system.db!!!

1 Like

Hi,

I tried this tag event scrip on Trigger tagt:
‘’‘if currentValue.value:
results = system.db.runNamedQuery(“Query”,{})
system.tag.writeBlocking(["[New]TestTag",[results]])’’’

where TestTag is dataset memory type tag.
The Named Query is tested and works, system.tag,writeBlocking is working in the script console too.
The thing is I cannot understand if the script works:

Capture
How to make visible the value in the dataset and use it after in expressions?

I tried this tag event script:

‘’’ if currentValue == 1:
results = system.db.runNamedQuery(“Query”,{})
outcome = results.getValueAt(0,0)
system.tag.writeBlocking(["[New]Tag",[outcome]]) ‘’’
Again it works in the script console, but not like tag event script.
What is the problem?

Your runNamedQuery call probably needs to include the project name. Tag event scripts execute in a global scope (outside of any specific project) but named queries reside inside specific projects. Note the ‘Gateway Scope Syntax’ section on the manual page: https://docs.inductiveautomation.com/display/DOC80/system.db.runNamedQuery

Thanks a lot, adding the project name fixed the issue.

1 Like