Perspective: Ad Hoc Trend Version 1.0.5 - Start/End Datetime Not Loading into Power Chart Correctly

The plot thickens.

What you need to do is customize pyToGson to serialize into a non-string format; Java Date objects are already a timestamp-in-milliseconds, which can be losslessly handed around and converted into a timestamp for representation (indeed, it’s handed between Perspective’s frontend and backend as a timestamp already). Luckily, albeit not intuitively, pyToGson already has a second parameter that allows you to pass a custom Gson instance to override serialization behavior.

from com.inductiveautomation.ignition.common import TypeUtilities
from com.inductiveautomation.ignition.common.gson import GsonBuilder, JsonSerializer, JsonPrimitive
from java.util import Date
from java.lang import Long

class DateSerializer(JsonSerializer):
	def serialize(self, src, typeOfSrc, ctx):
		return JsonPrimitive(Long(src.time))

gson = GsonBuilder().registerTypeAdapter(Date, DateSerializer()).create()

pyObj = {
	"str": "one",
	"number": 1.23,
	"date": system.date.now()
}

json = TypeUtilities.pyToGson(pyObj, gson)

print json

This should return a json structure like {"date":1607649727033,"str":"one","number":1.23}, instead of {"date":"Dec 10, 2020, 5:10:05 PM","str":"one","number":1.23} - and then it’s just a matter of parsing the long timestamp back into a date (system.date.fromMillis()).

PGriffith

Thanks for the code snippet. This is exactly what we need! I have implemented the change and put this serialization code in a “helper” custom method within the Ad Hoc Trends. Early indications show it is working. (I will conduct some more testing to be sure).

In short, the changes I made (thanks to you BTW) are as follows:

Change to Custom methods under view.rootContainer (Ad Hoc Trends):

New method: newPyToGson (Fixes date formatting issue)

def newPyToGson(self, config):
“”"
Custom method that can be invoked directly on this component.

Arguments:
	self: A reference to the component that is invoking this function.
	config: 
"""
#  *** newPyToGson ***
# This revised pyToGson custom method handles an issue with the standard pyToGson method that
#  stores dateTime in a format that is incompatible with the Power Chart obj.. This fixes the issue
#  where "saved" chartsettings.json files do not "load" correctly to show the startDate and endDate periods within the 
#  Power Chart trend.  CJG
from com.inductiveautomation.ignition.common import TypeUtilities
from com.inductiveautomation.ignition.common.gson import GsonBuilder, JsonSerializer, JsonPrimitive
from java.util import Date
from java.lang import Long

#create a Json serializer that stores date as millisecond time stamp
class DateSerializer(JsonSerializer):
	def serialize(self, src, typeOfSrc, ctx):
		return JsonPrimitive(Long(src.time))

# register the Date to be serialized as milliseconds
gson = GsonBuilder().registerTypeAdapter(Date, DateSerializer()).create()

# Serialize pyObj using new gson serializer that tells pyToGson to serialize date in milliseconds
return  TypeUtilities.pyToGson(config, gson)

Change: getConfigJson (section snippet of code)

if config:
	from com.inductiveautomation.ignition.common import TypeUtilities
	#************* CJG attempt to see what date time is coming back from pyToGson ***
	#system.perspective.print("getConfigJson **** Before pyToGson method call ****")
	#system.perspective.print(config)
	
	# myreturnIntercept = str(TypeUtilities.pyToGson(config)) <-- Deprecated method
	myreturnIntercept = str(self.view.rootContainer.newPyToGson(config)) #  <---- newPyToGson method 
	
	#system.perspective.print(" getConfigJson **** After pyToGson method call ****")
	#system.perspective.print(myreturnIntercept)
	return myreturnIntercept
return '{}'

New to the community, so not sure how to get others to verify and test, but I will move on to the next issue with the Ad Hoc Trend which seems to be the Realtime “Pause” and “Refresh Rate” function:
image

These buttons don’t seem to behave correctly. :slight_smile:

Thanks again for all the help, it was a bit of a grind that is for sure.

2 Likes

I added a conversion of the long to date here so there was not a Powerchart Prop error on config.startDate & config.endDate ( loadFromFile method);

def loadFromFile(self, configJson, includePlots, includeDisplay):
	"""
	Custom method that can be invoked directly on this component.

	Arguments:
		self: A reference to the component that is invoking this function.
		configJson: 
		includePlots: 
		includeDisplay: 
	"""
	# save files are split into two sections -
	#  the configured plots (pens/axes/plots) and the overall display settings (legends/columns)
	if configJson:
		config = system.util.jsonDecode(configJson)
		powerChart = self.view.getChild('root/PowerChart')
		if includePlots:
			if 'config' in config:
				powerChart.props.config = config['config']
				1. if powerChart.props.config.mode == 'historical' :
2. 					powerChart.props.config.startDate = system.date.fromMillis(powerChart.props.config.startDate)
3. 					powerChart.props.config.endDate = system.date.fromMillis(powerChart.props.config.endDate)
			if 'axes' in config:
				powerChart.props.axes = config['axes']
			if 'pens' in config:
				powerChart.props.pens = config['pens']
			if 'plots' in config:
				powerChart.props.plots = config['plots']
			if 'title' in config:
				powerChart.props.title = config['title']
			
		if includeDisplay:
			if 'timeAxis' in config:
				powerChart.props.timeAxis = config['timeAxis']
			if 'interaction' in config:
				powerChart.props.interaction = config['interaction']
			if 'dataColumns' in config:
				powerChart.props.dataColumns = config['dataColumns']
			if 'legend' in config:
				powerChart.props.legend = config['legend']

Great. That’s a solution too. You will have to make this change to all datetime props and will need to change this for the dB load functions too. (and any where else date is being extracted from the the JSON file with the date format issue). Thanks for the other option/approach! I will probably stick with the newPyToGson custom method approach for now.

I want to display unit of that tag pens on axis so how to derive that. some one guide me