Having trouble with system.tag.writeAsync

I have a series of tags that store the last 10 days of totalized values (tag names Day0-Day9). At midnight I want to shift each of the totals down 1 tag to act as a rolling totalizer.

My plan of attack was to use system.tag.readAsync to read the tags and system.tag.writeAsync to write the values to their new locations post-shift.

system.tag.readAsync is pointed to the tags for Day0 -Day8
system.tag.writeAsync is pointed to the tags for Day1-Day9

I got it to work once and then it just threw an error saying that “Length of values does not match length of paths”. I confirmed in a query window that the read was not listing as many values as I was sending read requests for.

Code is as follows:

#basically a blank callback for writeAsynch
def writeCallback(asynchReturn):
	i=0

#Callback for readAsync
def checkValues(asynchReturn):
	values = []
	for qValue in asynchReturn:
		print qValue.value
		values.append(qValue.value)
		
tagsRead = [
			... list of tags goes here (multiple 10 day totalizers and some other tags I'm shifting)
			]		
			
tagsWrite = [
			... list of tags goes here
			]
	
#print len(tagsRead)
#print len(tagsWrite)

system.tag.readAsync(tagsRead, checkValues)
#print len(values)
#print values
system.tag.writeAsync(tagsWrite, values, writeCallback)

What am I doing wrong?

PS: I’m planning to call this from a gateway script if that matters.

1 Like

I don’t have a 8.0 system to test it on right now but by the description of system.tag.readAsync(), I’m not sure how this would work for what you want. The manual lists that it doesn’t return anything. For it to do what you want, it would have to return “values” from the function you called with it. The example given in the manual does talk about writing to a tag or database though. If you can do your write inside of the function then it would work but your tag list would have to be available to the function when it is called. Calling it from inside of readAsync, you can only pass in the list of qualified values so I don’t believe that will work unless you can define your write tag list inside of the function. To use the results of values the way you are trying to, I would think you would have to do something like:

def checkValues(asynchReturn):
	values = []
	for qValue in asynchReturn:
		print qValue.value
		values.append(qValue.value)
    return values

qv = system.tag.readBlocking(tagsRead)
values = checkValues(qv)

Doing this you are actually returning the value to be used. If you don’t return the value it shouldn’t be able to be used later in the script.

Is there a reason you want to use the Async functions instead of the blocking? If your tag lists change I think you would be better off using blocking. If they don’t then you can define your write tag list in your function and do your write from inside of the function to achieve what your attempting to do.

As for your other note about the lengths not matching, can’t help with that when you take out your tag lists from the script. If it was there then people can look for typos that could cause it but when it isn’t there its hard to say anything other than a wild guess.

1 Like

I haven’t done much in Python and I only know the basics with the syntax. Your response was very helpful.

I changed my code to use readBlocking and writeBlocking and it does what I want. I just wanted to do this as a block shift to optimize the OPC side of things because performance was a concern.

I think my code was creating 2 different variables with the same name at different scopes. I was trying to use the values as a global but I didn’t need to do that. I just needed to be using readBlocking with the same tag list.

Thanks for your help.