[Question] How do I use .readAsync to read tag value

Hi all,

Would anybody be able to provide an example on how to use the new system.tag.readAsync, for whatever reason I’m not able to wrap my head around the callback that must be provided in the function.

Thanks

1 Like

It expects you to provide a callback function that will accept a list of qualified values.

Something like this:

def callback(values):
	print [qv.value for qv in values]
	
system.tag.readAsync(['Tag1', 'Tag2'], callback)
2 Likes

What exactly is the scope of the callback function? I ran the script in the script console and all the print statements printed in the output console of my designer instead of the script console. I also couldn’t figure out a way to return values to the main of my script, certainly I can use the readBlocking method to do this, I just wanted to verify if this was how readAsync was supposed to function.

1 Like

The callback will likely be coming in on another thread. I don't think it's strange that the print out went to the designer's output console rather than the script interpreter.

If you want to "return" the values to your main script then you really just want a blocking call. If you're using the async version you should be writing logic that continues from the point of the callback.

2 Likes

Thanks, so that means that essentially we should not plan on trying to write a universal callback method. readAsync should only be used for a specific purpose where the end result is not used locally within the current script? Is there a benefit to utilizing readAsync instead of a separate global script that does the same thing but uses a blocking call?

readAsync could be useful to e.g. make a call to read a tag value and then update the UI later on the callback thread using invokeLater, all without blocking the UI thread this script may have been invoked from.

2 Likes

You can make semi-generic callbacks by creating jython classes that implement the __callable__ special method, and supply an instance as the callback. Have the __init__ method save the state you need to carry your logic forward.

2 Likes

Kevin, did I understand correctly that system.tag.readAsync() only works in Vision and in Perpspective and doesnt’ work in the gateway scripts and in the script console?

No, readAsync and readBlocking are available in all scopes - in fact, all tag operations are now asynchronous by default; the readBlocking methods just perform the asynchronous call and wait for the result for you.

1 Like

Will the system.tag.readAll() and writeAll functions continue to be supported in version 8 onward or will they be depricated in future versions?

They are already “deprecated” but we will almost certainly never make them stop working. They’re already bridging to readBlocking/writeBlocking behind the scenes, but removing a system function outright would unnecessarily break existing projects (which is why system.tag.getTagValue() still works, nearly a decade later)

4 Likes

Indeed, the function system.tag.readAsync() in the console works. However, for some reason she doesn’t work in my gateway timer script.

This is the script that I use:

tagPaths = ['[default]test_folder/test_val1','[default]test_folder/test_val2']

def callback(values):
	arr = []
	for qv in values:
		print qv.value
		arr.append(str(qv.value))
	system.tag.write('[default]test_folder/result',str(arr))

system.tag.readAsync(tagPaths, callback)

Is the error “global name system is not defined”? I had to add import system inside the callback function definition to get your example to work (due to gateway timer scripts having weird legacy scoping rules), but after doing so, it worked fine.

1 Like

Thanks so much. It work

Am I using this correctly? When I run it in the script console all it will return is ‘None’

def tag_value(values):
	return [qv.value for qv in values]
def tag_quality(values):
	return [qv.quality for qv in values]
def tag_timestamp(values):
	return [qv.timestamp for qv in values]

tagPath = '[Carefree]Customers/Demo/well_1/Reads/Flow'
print system.tag.readAsync([tagPath],tag_value)
print system.tag.readAsync([tagPath],tag_quality)
print system.tag.readAsync([tagPath],tag_timestamp)

No, if you wanted to see some results you’d put the print statements in each of those methods.

The way you have it written now expects a synchronous result, so you should just use the synchronous version of the function if that’s what you want.

The async functions don’t return anything, they call some other function with the eventual result.

What is the synchronous version of the system.tag.readAsync function?

The new system.tag.readBlocking or the (legacy) system.tag.read are synchronous.

1 Like

So… The question remains unanswered?

When I read a tag, it implies that I need the value to return to the calling context.
…then, I will use the value to affect the decisions that follow.

def callback(values):

 <?? return values ??>      #<??Return this list to the calling function ??>

tagPaths = [’[default]test_folder/test_val1’,’[default]test_folder/test_val2’]
system.tag.readAsync(tagPaths, callback)

values = < ? Return the values object list from the callback function ? >

val1 = values[0].value
val2 = values[1].value

if val1 = True:
print “Value 1 is True”

if val2 = True:
print “Value 2 is True”

<etc…>

The expected functionality, would be read the values and don’t block other processes, then return all the values to the point of the call (or slightly there after). …similar to the .join operator when utilizing multi-threading / multi-processing.

If the deprecated system.tag.read is ever removed…this will cause issue.

It was answered, use system.tag.readBlocking.

That's not how .join() works. The thread calling join() blocks, just like the thread calling system.tag.readBlocking will block.