Perspective - Status/ribbon chart

Hi All

We are monitoring several CNC machines for their status (idle/in process/in alarm). Using the Ignition historian, we have a database containing timestamp, and several columns for machine status (integer). In Vision, we have a status chart to show the status of each machine over the last 24 hours. This works well. Our historian is currently set to log data on change with a maximum time of 1 minute.

I am now replicating the system in Perspective. With the help of the following posts, I have a basic "ribbon" chart working in Perspective.

Perspective Status Chart - Ignition - Inductive Automation Forum

Perspective :: XY Chart :: Is it possible to make a status chart out of the XY Chart? - Ignition - Inductive Automation Forum

I am now stuck on how to translate the data from our historian to the array type format required by the XY chart. Our historian query returns data as a dataset (2D array). The required format for the perspective component appears to be as follows:
[
{
"mode": 1,
"fromDate": "2018-01-01 08:00",
"toDate": "2018-01-01 10:00",
"color": "Green"
},
{
"mode": 2,
"fromDate": "2018-01-01 12:00",
"toDate": "2018-01-01 15:00",
"color": "Red"
}
]

Can anyone explain the basic process for feeding the perspective XY chart with data from the ignition historian? Any pointers?

Best regards

1 Like

I have done the Equipment Schedule with module visiĂłn using the named queries.
image
right now i am trying to do it with ribbon chart.

image
But i do not know how to make the code to have dynamic graph.
In the case of:
instance ID should be the ID of the table?
Data, seams an structure that is in array, buy i do not know hoy to prepare this data. Is an script? or can be SQL code?


Looks like is a structure to make some where. But i don’t understand how that structure take data from mysql
someone can give me some light on this?
I do not know the variable process to make this graph dynamic, and show values from mysql projects.
An small video will give a good idea how to configure the graph
Thanks

I have made a sql querry but give the table data has a data set.
Can we get any idea that how to make this structure code from sql?
image

Oscar, if you haven’t figured this out yet, you have to loop through your dataset (perhaps in a Script Transform) and create the structure that is expected. Your data probably only has a date column and an integer status column. This script might help you get started.

	data = <some code that returns a dataset goes here>
	
	prevmode = -1
	prevstart = 0
	events = []
	modes = {0:"Unknown", 1:"Fault", 2:"Offline", 3:"Standby", 4:"Production"}
	for row in range(data.getRowCount()):
		mode = data.getValueAt(row,1)
		time = system.date.toMillis(data.getValueAt(row,0))
		if row == 0:
			prevmode = mode
			prevstart = system.date.toMillis(start)
		if row > 0:
			if mode <> prevmode:
				events.append({
					"mode": modes[prevmode],
					"start": prevstart,
					"end": time,
				})
				prevmode = mode
				prevstart = time
	data = ([
		{"name": "",
		"events": events
		}
	])
	return data
2 Likes

I don’t think I can find a way to adapt it. Has anyone who has used this gadget have an example of data extracted from the BDD?

Anyway, thanks for the help.

Oscar, what is BDD? Also, have you tried adding the script transform? This is almost exactly the code I use and it works when pulling data from the tag historian. Is your status an integer? Did you also update the modes parameter to reflect all the different possible modes you have? If you don’t do both the data nd the modes, it won’t work.

BDD → SQL data base


I have done with the vision module, but in perspective i have to make this structure that i don, t know how to make.
the objective is to follow status of the projects and machines stored in a Mysql.

For those english speakers scratching their heads, it's the french acronym for «Base de données», what we call a Database and abbreviate "DB".

5 Likes

Oscar, in Perspective, you have the option of adding a Transform. This helps you “transform” your original BDD query from a dataset to the expected structure. Add a Script transform and copy/paste the script I provided. Edit the first line that says data = and simply put data = value. Then, observe the Binding Preview to see how your dataset gets converted to the object the Ribbon Chart is expecting.

image

My ribbon chart is acting weird. Any progress I made gets deleted any time I save the project and close the window and come back to it. It reloads the originally data.
Does anyone else have same problem?

1 Like

I'm running into the same issue right now.
Have you, or anyone else, been able to solve this?

UPDATE:
I came up with a temporary fix, though not that neat.
Disabling the script behind the exampleData property seems to do the trick for now.

Was there a better fix for this issue ?

Hi Drojas. Thank you for this. It is a great help. (Im from a PLC background so python is all new to me)
Apart from changing the variable name from 'start' to 'time' in line prevstart = system.date.toMillis(start),
it works fine with a table that just contains mode and start variables.

what I am trying to figure out is how to create a table with Multiple machines (ie data[0], data[1], data[2] etc etc . What would be your suggestion to point me in the right direction?

Daniel,
Depending on how your status data comes in (probably from a Tag History Query). Most likely you would need to just loop through each machine/column and allocate the events into an array of data like you said (data[0], data[1]...etc.). Below is modified code to help.

Note: the reason I had "start" instead of "time" on that prevstart= system.date.toMillis(start) is because I was setting my chart to a fixed start date...say July 1st and needed the chart to be filled in even if the first event didn't start until July 2nd. Anyways, you could do whatever you want for those scenarios or modify the tag history query to return bounding values too.

#sometimes the dataset returned by tag historian query doesn't return
# the first line with your starting date.  this fills in the chart with previous mode or 0 if you choose instead of None.
start = <some starting date for your chart>

data = <some code that returns a dataset with multiple columns..one per machine goes here>

prevmode = -1
prevstart = 0
ribbonData = [] #create a new variable to store data instead of overwriting data like in previous example.
modes = {0:"Unknown", 1:"Fault", 2:"Offline", 3:"Standby", 4:"Production"}
for column in range(1,data.getColumnCount()):
	events = [] #re-initialize events for every column
	for row in range(data.getRowCount()):
		mode = data.getValueAt(row,column)
		time = system.date.toMillis(data.getValueAt(row,0))
		if row == 0:
			prevmode = mode
			prevstart = system.date.toMillis(start)
		if row > 0:
			if mode <> prevmode:
				events.append({
					"mode": modes[prevmode],
					"start": prevstart,
					"end": time,
				})
				prevmode = mode
				prevstart = time
	ribbonData.append([
		{"name": "",
		"events": events
		}
	])
return ribbonData

Hi Thanks for your reply. I did it slightly differently but it’s not as tidy as your solution. I have added a machine iD as a pointer to populate the correct areas during the loop and assemble data at the end