Script writing to a memory tag dataset

I have a series of tags that are reading values from a plc. I'd like to consolidate these tags into a single dataset with the intention of binding a table's data to the dataset for easy display.

My thought would be to have a Refresh button run a script like the following:
Script was simplified from my original but gives the same error that is getting me stuck.

#get existing dataset
newData = system.tag.readBlocking(["[default]tagPath/existingDataset"])
#get data for new row
startTime = system.tag.readBlocking(["[default]tagPath/StartTime.value"])
endTime = system.tag.readBlocking(["[default]tagPath/EndTime.value"])
FT = system.tag.readBlocking(["[default]tagPath/FG.value"])

#create new row	
newRow = [startTime, endTime, FT]

print(newData)
#prints [[Dataset [0R ⅹ 3C], Good, Tue Feb 21 12:04:53 CST 2023 (1677002693877)]]

#following lines fails - TypeError: addRow(): 1st arg can't be coerced to com.inductiveautomation.ignition.common.Dataset
newData = system.dataset.addRow(newData, newRow)

#write back to the memory tag	
system.tag.write("[default]tagPath/existingDataSet", newData)

Before the second to last line the print(NewData) will output:
[[Dataset [0R ⅹ 3C], Good, Tue Feb 21 12:04:53 CST 2023 (1677002693877)]]

On the following line (second to last line) the script fails with a error:
"TypeError: addRow(): 1st arg can't be coerced to com.inductiveautomation.ignition.common.Dataset"

The examples I'm finding usually reference a tables existing prop.data and I could do that but would prefer to use a project script since I'll be re-utilizing this for multiple lines.

Am I misunderstanding something in my addRow command?

Your tag reads are returning Qualified Values, which include a value, quality and timestamp, which you can see in your print statement. You need to use .value to get the value only.

newData = system.tag.readBlocking(["[default]tagPath/existingDataset"]).value

I can see that you have a .value in your start and end time tag paths, these should be outside the function as per above, not in the tag path.

You have also used system.tag.write which was deprecated after version 7.9 - I'm assuming you are on 8+ given you have used system.tag.readBlocking. You will want to change this to system.tag.writeBlocking

1 Like

?
[0].value
v.s
.value
the read blocking returns the list[0=value,1=quality and 2=timestamp] correct? or can we just access .value as you indicated?

best

readBlocking unconditionally returns a list of qualified value objects.

So the correct syntax is readBlocking(["path/to/tag"])[0].value - get the first element of the list/index 0, and return its value property.

readBlocking(["path/to/tag"]) and readBlocking(["path/to/tag.value"]) are exactly equivalent; both will still have the same return value (a list of qualified values). We assume that if you don't specify a property underneath a tag, you wanted to read the value of it, as a shortcut.

As an aside, you basically never want to manually issue multiple read calls in a row from a script. Always try to collect your writes into as few calls as possible; it's significantly more efficient. E.G:

tagPaths = [
	"[default]tagPath/existingDataset",
	"[default]tagPath/StartTime",
	"[default]tagPath/EndTime",
	"[default]tagPath/FG"
]
newData, startTime, endTime, FT = [qv.value for qv in system.tag.readBlocking(tagPaths)]
4 Likes

Why not use a UDT?

Thanks all. That really helped to wrap my head around the variables and how they were interacting.

Got it working and optimized the multiple read/writes.