Saving a configuration of a power chart in runtime?

Hi everyone,

I’m using Perspective 8.1.2. I’m trying to figure out the best approach to save a configuration of the power chart in runtime (Pens and axes/plots). I’m not really sure where to start with this, so any help is appreciated. Preferably something that can be saved on the gateway and retrieved, rather than an SQL approach.

3 Likes

If you don’t want to go sql, then the nest best thing would be dataset tags to store the various table data. It’s not a 5min thing to setup. I would make it work for both dataset tags and sql tables, or at least make it easy to convert the code for either

1 Like

I think datasets are probably going to align more with my ignition skillset, can you point me to an ignition doc which has the process for turning the JSON into a dataset? I’ve not seen it done before.

@michael2 I think you’r going on right way. I was facing same problem during last week now it’s cleared. Thanks to you for this. :slightly_smiling_face:

Look up jsonEncode and decode in the manual, in only on my phone atm

1 Like

Thanks Nick, I’ll have a look into this.

Managed to get this working. Created a dataset which had a column for each JSON string in the props of the power chart (config, pens, plots, etc.), which then saved it to a tag with a name defined by the user. Does the same thing in reverse to ‘open’ the saved config.

1 Like

I’m looking to do the same thing, but having trouble dealing with the JSON, I think, and conversions to get it out of and back into the Power Chart properties. Can you post some simple sample code that demonstrates what you have done with this? Thanks.

There is probably a better way of doing this, but this is the way I did it:

Saving to a tag:

config = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.config)
interaction = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.interaction)
axes = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.axes)
pens = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.pens)
plots = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.plots)
dataColumns = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.dataColumns)
title = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.title)
timeAxis = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.timeAxis)
legend = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.legend)
style = system.util.jsonEncode(self.parent.parent.getChild("PowerChart").props.style)
#put JSON Strings in dataset
headers = ['config','interaction','axes','pens','plots','dataColumns','title','timeAxis','legend','style']
rows = [[config,interaction,axes,pens,plots,dataColumns,title,timeAxis,legend,style]]
system.tag.write(FilePath, system.dataset.toDataSet(headers,rows))

Retrieving from a tag:

data = system.tag.read(FilePath).value
self.parent.parent.getChild("PowerChart").props.config = system.util.jsonDecode(data.getValueAt(0,0))
self.parent.parent.getChild("PowerChart").props.interaction = system.util.jsonDecode(data.getValueAt(0,1))
self.parent.parent.getChild("PowerChart").props.axes = system.util.jsonDecode(data.getValueAt(0,2))
self.parent.parent.getChild("PowerChart").props.pens = system.util.jsonDecode(data.getValueAt(0,3))
self.parent.parent.getChild("PowerChart").props.plots = system.util.jsonDecode(data.getValueAt(0,4))
self.parent.parent.getChild("PowerChart").props.dataColumns = system.util.jsonDecode(data.getValueAt(0,5))
self.parent.parent.getChild("PowerChart").props.title = system.util.jsonDecode(data.getValueAt(0,6))
self.parent.parent.getChild("PowerChart").props.timeAxis = system.util.jsonDecode(data.getValueAt(0,7))
self.parent.parent.getChild("PowerChart").props.legend = system.util.jsonDecode(data.getValueAt(0,8))
self.parent.parent.getChild("PowerChart").props.style = system.util.jsonDecode(data.getValueAt(0,9))

3 Likes

Thanks for sharing that!

Perhaps an old thread, but thought I'd mention a couple of things for additional reference:

  1. Ignition Exchange hosts a project (Ad Hoc Trends) which offers some interesting insight as to possibilities for Saving / Retrieving chart configurations, as well as some ways to customize the chart during runtime. We opted to go a different route, in an effort to simplify a few layers.

  2. Our solution for exporting, a 'Button' component on the same page as the trend, with an onActionPerformed script, which allows a user to export/download all of the powerChart.props to a json file for future retrieval:

def runAction(self, event):
	# Extract Props from Power Chart object, encode as JSON:
	powerChart = self.view.getChild('root/PowerChart')
	propsJson = system.util.jsonEncode(powerChart.props)
	
	# Send file-download to client.
	filename = "myTrend.json"
	system.perspective.download(filename, propsJson)
  1. Our solution for importing (somewhat lengthier-version of the export, by intention), involves a File-Upload component with the following onFileReceived script action:
def runAction(self, event):
	# Read file contents.
	fileName = event.file.name
	fileSize = event.file.size
	fileString = event.file.getString()
	
	# Convert file contents to JSON object.
	fileJSON = system.util.jsonDecode(fileString)
	
	# Define DateTime format from export (e.g. 'Jan 01, 2000, 11:59:59 PM')
	strDTFormat = 'MMM dd, yyyy, hh:mm:ss a'
	#"yyyy-MM-dd HH:mm:ss"
	
	def formatDateTime(wrkDateTime):
		if wrkDateTime is not None:
			return system.date.parse(wrkDateTime, strDTFormat)
		else:
			return wrkDateTime

	# Assign PowerChart object
	powerChart = self.view.getChild('root/PowerChart')
	
	# Write dictionary items from file to PowerChart Props:
	if 'config' in fileJSON:
		powerChart.props.config = fileJSON['config']
		# Convert all DateTime objects to format required of PowerChart:
		powerChart.props.config.startDate = formatDateTime(powerChart.props.config.startDate)
		powerChart.props.config.endDate = formatDateTime(powerChart.props.config.endDate)
		powerChart.props.config.rangeStartDate = formatDateTime(powerChart.props.config.rangeStartDate)
		powerChart.props.config.rangeEndDate = formatDateTime(powerChart.props.config.rangeEndDate)
	if 'interaction' in fileJSON:
		powerChart.props.interaction = fileJSON['interaction']
	if 'axes' in fileJSON:
		powerChart.props.axes = fileJSON['axes']
	if 'pens' in fileJSON:
		powerChart.props.pens = fileJSON['pens']
	if 'plots' in fileJSON:
		powerChart.props.plots = fileJSON['plots']
	if 'dataColumns' in fileJSON:
		powerChart.props.dataColumns = fileJSON['dataColumns']
	if 'title' in fileJSON:
		powerChart.props.title = fileJSON['title']
	if 'timeAxis' in fileJSON:
		powerChart.props.timeAxis = fileJSON['timeAxis']
	if 'legend' in fileJSON:
		powerChart.props.legend = fileJSON['legend']

Hope some of this helps!

3 Likes

Is it possible to automatically open a file with a button press using this method (or any method)? I'm trying to figure out how to setup pre-configured trends that the operator can load with the press of a button.

Yes.

The Ad Hoc Trends project that @Chris_Bingham mentions, retrieves the saved config from a database, but that can be adapted to a file. The important part is the encoding and decoding to and from JSON.

Yeah I'm wondering how to automatically upload a specific file by pressing a button

Are you using Perspective or Vision? Were will the file be located, on a client machine, on the gateway, on a network drive?

Perspective can't do that. But a button could load a specific file from the gateway filesystem.

Thanks! Do you happen to have anything i can reference, like a function name, that would help me get this working?

If the goal is to preconfigure a chart on a button-press, you could start 'simple' by using a script to write the specific parameters you require to the chart directly. To aid in generating the script, you could start by generating the trend that you desire in Designer, then right-click on specific properties (for example, the entire 'props.pens' object) and copy to your clipboard. Then, modify the scripts aforementioned (except within a button's onActionPerformed* event script) and paste the properties direct from your clipboard:

powerChart = self.view.getChild('root/PowerChart') # Update to match the path of your chart
powerChart.props.pens = (paste your pens JSON here)

You'll likely need to manipulate a few items so that they interpret correctly (true --> True, etc.). Once you're able to preset a trend with this method from your designer, other clients should experience same results.

Depending on number of 'pre-built trends' required, I could see this method growing to be undesirable. At this point (say, more than...3 trends?), I would consider using a database (or file, or other means of lookup), whereby a dropdown menu could select from the list of trends.

1 Like

Thanks Chris, this is exactly what I ended up doing