Extract Duration of Machine State from Datatable

This is likely an easy fix, but I am somewhat new to Ignition. I am attempting to sum three different machine states into one "Stopped" state (stop, fault, E-Stop). I created a table reporting the status of each state, but I am struggling with how to sum elapsed time between states. I am using Ignition Version 8.19

Below are my table binding and table view.


I had in mind to script this, but am also new to scripting. The path I wanted to take was this:
create new datatable
where all rows in range of current table that the value = n
datediff the t_stamp in row 1 - t_stamp in row 0

I do not know how to script this, unfortunately.

What kind of table is it? What property are binding this query to? Can you mock up a picture of how you would like the table to look once successful?

I mispoke with creating a table. I wish to create a dataset that will show a value in the first column (1, 4, or 5) and duration that each state persisted in the second column.

The timeframe is decided by the original tag history binding shown above. The purpose is just to show a sum of all durations in the dataset.

Here's an experiment I set up to illustrate a way to go about this. In the experiment, I used two tables called 't_stamp Table' and 'Duration Table'. The t_stamp table I filled with data that mimicked yours. Then, using scripting, I processed the data in the way you suggested and displayed it in the duration table.


Here is the script I used to process the data:

# Get the raw data
inputDataset = event.source.parent.getComponent('t_stamp Table').data

# Create the headers and data variables that will be requried for dataset creation
headers = ['Machine State', 'Duration']
data = []

# Process each row of the input dataset to produce the duration dataset
# Since the duration has to be calculated from two consecutive rows, start with row 1,
# so each iteration can be between the previous and current rows without creating an index error
for row in range(1, inputDataset.rowCount):

	# Grab the machine state from the previous row and the machine state column [column 1]
	machineState = inputDataset.getValueAt(row-1, 1)
	# Get the number of seconds between the previous row and the current row
	duration = system.date.secondsBetween(inputDataset.getValueAt(row-1, 0), inputDataset.getValueAt(row, 0))
	# Create a string to diplay the duration along with its unit [seconds]
	stringDuration = '{} seconds'.format(duration)
	# Append the processed row to the data list
	data.append([machineState, stringDuration])
# Create a dataset from the processed data
outputDataset = system.dataset.toDataSet(headers, data)

# Display the output dataset in the duration table
event.source.parent.getComponent('Duration Table').data = outputDataset

In case it is useful for somebody in the future, here is the script I developed for generating the random sample data:

import random
def getRandomData(iterations=200):
	# Initialize the start dateTime as now
	t_stamp = system.date.now()
	# Create the headers and data variables that will be requried for dataset creation
	headers = ['t_stamp', 'machineState']
	data = []
	# Iterate through the specified number of iterations to generate test data
	for _ in range(iterations):
		# Randomly increment the time by 3 seconds to 3 minutes
		seconds = random.randint(3, 180)
		# Generate a new timestamp using the randomly generated seconds
		t_stamp = system.date.addSeconds(t_stamp, seconds)
		# Randomly generate an integer between 0 to 5
		machineState = random.randint(0, 5)
		# Append the pair to the data list
		data.append([t_stamp, machineState])

	# Convert the data to a dataset and return it
	return system.dataset.toDataSet(headers, data)

# Generate a sample of 500 entries for demonstration
# Display the data in the t_stamp Table
event.source.parent.getComponent('t_stamp Table').data = getRandomData(500)
1 Like

Fantastic job! That will work really well for us. I likely will not need the string portion at the end, but that is pretty portable.

I appreciate your help.