Script to compare and return dataset values

Hello,

I am trying to write a script that will run every 15 seconds on one popup screen only. I have a memory tag called Interlock that is a dataset. The columns are called InterlockedTags (this column provides the tag path), StatusForTrue (this tag is a static boolean that says whether true or false is the desired condition of the tag), and ColourNum (this is an int which will be used to turn the rows yellow if the condition is bad and grey if it is good). I am trying to write a script that will take the tag path from the InterlockedTags column and compare the actual status of that tag to the value in the StatusForTrue tag. If they are the same, I want it to return a 0 to the ColourNum column and if they are not the same I want to to return a 1 to ColourNum.

Can anyone help me decide what the best way to implement this is and where the script should actually go? I am not very familiar with the scripting language.

Thank you!

Are you using Vision or Perspective for graphics? If in Vision and you really only want to run the script when a particular window (popup in this case) is open you can use a timer component and add a script like this to the propertyChange listener. Using the default timer configuration in 8.1.5 this script executes every 10 seconds. you can change the bound to 15 to achieve 15 second delay.

I would still set your logic up in a script library and call it from the timer property change script. Doing it this way you can reuse the logic in another area if you need to.

if event.newValue==0:
	print 'Timer Test'

If there are multiple clients with this popup open, you donā€™t really want then to fight over writing to the dataset. It would be more efficient to call it from a gateway timer script.

Yes that is true as there may be multiple instances of a similar popup open at the same time. Thank you

I am using vision. Do you know if there is a system. function that I can use to compare the information in a specific cell to the information in a tag?

Itā€™s not a system.* function, but once you have a dataset you can use the getDataAt() method to inspect a particular cell.

Example:

data = event.source.parent.getComponent('Table').data
print data.getValueAt(2,2) # row, column; zero based indexing

Awesome, thank you. Do you know what the best way to get tag information based on the information in a cell? For example, if the cell is a string of the tag path to a boolean tag, how can I return a 0 or 1 just by taking the string tag path?

You can get column data as a list. Use that list with system.tag.readBlocking to get all your values at once.

Iā€™d also recommend converting to a PyDataSet to make it convenient to iterate through the data.

def myFunc(datasetPath):
	# Read the dataset tag. Convert to PyDataSet for easier iteration.
	dataIn = system.dataset.toPyDataSet(system.tag.readBlocking([datasetPath])[0].value)

	# Get column names. Coerce it to a list to use the same names in the new dataset.
	headers = list(dataIn.getColumnNames())
	
	# Get tag paths as a list
	tagList  = dataIn.getColumnAsList(headers.index('InterlockedTags'))

	# Read the tags
	tagValues = [tag.value for tag in system.tag.readBlocking(tagList)]

	# Construct the new dataset.
	data = []
	for row, actualValue in zip(dataIn, tagValues): 
		data.append([row['InterlockedTags'], row['StatusForTrue'], int(row['StatusForTrue'] != actualValue)])
	
	# Write back to the original tag
	system.tag.writeBlocking([datasetPath],[system.dataset.toDataSet(headers, data)])

myFunc('[default]path/to/Interlock')
3 Likes

Thanks Jordan. I am not really sure how or where to implement thisā€¦ The code I have come up with so far is shown below. I am not sure if I should put it in the table scripting, on the popup window itself, or somewhere else. Do you have any ideas?

rowNum = 0 #Need to get this value. 0 is placeholder value.
numOfRow = 4 #Number of total rows (this will vary depending on the tagpath). Need to get this value. 4 is placeholder value.

for rowNum in range (0, numOfRow, 1):
data = event.source.parent.getComponent(ā€˜Interlockā€™).data
pathToRead = system.tag.read(ā€œInterlockedTagsā€).value.geValueAt(rowNum, 0) #String containing the tag path
trueStatusCheck = data.getValueAt(rowNum, 1) #Boolean which shows the desired status
if pathToRead == trueStatusCheck:
colourNum = 1 #ColourNum is the third colum and I would like to make it control the colour of the row in the future.
else:
colourNum = 0

You need to encase your code in a preformatted block

rowNum = 0 #Need to get this value. 0 is placeholder value.
numOfRow = 4 #Number of total rows (this will vary depending on the tagpath). Need to get this value. 4 is placeholder value.

for rowNum in range (0, numOfRow, 1):
	data = event.source.parent.getComponent('Interlock').data
	pathToRead = system.tag.read("InterlockedTags").value.geValueAt(rowNum, 0) #String containing the tag path
	trueStatusCheck = data.getValueAt(rowNum, 1) #Boolean which shows the desired status
	if pathToRead == trueStatusCheck:
		colourNum = 1 #ColourNum is the third colum and I would like to make it control the colour of the row in the future.
	else:
		colourNum = 0

Sorry about that!

Sorry, at meetings this morning. Canā€™t give this much attention. Iā€™ll post something in a bit.

1 Like

The attached file may be iported into your project. It contains the script I posted above, and a getway timer script to call it every 15 seconds. update tagName in the gateway script to reflect where your tag is.

interlock_2021-06-08_0549.zip (2.3 KB)


Thank you very much! This makes sense now. I am getting an error when I run this code saying that ā€œTypeError: toPyDataSet(): 1st arg canā€™t be coerced to com.inductiveautomation.ignition.common.Datasetā€ for line 3. Do you know what might fix this?

Looks like a couple typos on line 3. Should be:

dataIn = system.dataset.toPyDataSet(system.tag.readBlocking([datasetPath])[0].value)
1 Like

That change to line 3 and making actualValue and actualVal variables match in line 16 and 17 fixed all the problems and the script works great.

Thanks again to everyone!!!

Thanks, post edited.