Expression Tag RunScript Invalid Datatype for Dataset (PyDictionary)

I have an expression tag that runs a script (getTrendList()) via runScript().

This is the script:

def getAllTrendPens():
	data = system.db.runNamedQuery("getHistoryTags")
		
	if data is not None:
		historyTagPaths = data.getColumnAsList(0)
		
		trendLabelPaths = [historyTag+".Trend_Label" for historyTag in historyTagPaths]
	
		
		trendLabels_qv = system.tag.readBlocking(trendLabelPaths)
	
		trendLabels = [label.value for label in trendLabels_qv]
		
		colors = ["#66FFFF","#B266FF","#FF3333", "#66FF66", "#000099", "#FF66B2", "#CCCC00", "#000000", "#606060" ]
		
		pens = []
		
		for i, pen in enumerate(trendLabels):
			if pen is not None:
				color = colors[i % len(colors)]
				#print pen
				#print historyTagPaths[i]
				jsonObject = {
						
								  "name": pen,
								  "visible": False,
								  "enabled": True,
								  "selectable": True,
								  "axis": "",
								  "plot": 0,
								  "display": {
								    "type": "line",
								    "interpolation": "curveLinear",
								    "breakLine": True,
								    "radius": 3,
								    "styles": {
								      "normal": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 0.8,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 0.8
								        }
								      },
								      "highlighted": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 1,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 1
								        }
								      },
								      "selected": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 1,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 1
								        }
								      },
								      "muted": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 0.4,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 0.4
								        }
								      }
								    }
								  },
								  "data": {
								    "source": "histprov:MSSQLSERVER1:/drv:ignition-scada-pc:default:/tag:"+historyTagPaths[i],
								    "aggregateMode": "default"
								  }
						
							}
				pens.append(jsonObject)
				
	return pens
	
def getTrendList():

	headers = ["Name", "Pen"]

	pens = trendPens.getAllTrendPens()
	
	names = [pen["name"] for pen in pens]
	
	data = [[name,pen] for name, pen in zip(names, pens)]
		
	dataset = system.dataset.toDataSet(headers, data)
	
	return dataset

When I call trendPens.getTrendList() from the script console it returns a dataset, but when called from the expression I get a type conversion error.

Error_TypeConversion("class org.python.core.PyDictionary: Invalid DataType for Dataset.")

You can't nest complex data types in datasets that will be assigned to tags. Because it blows up their serialization for retention. Your jsonObject isn't JSON, it is a python dictionary. Convert it to JSON (string) if you want to store it in a dataset in a tag.

1 Like

and what's the best way to do that?

edit: I found

system.util.jsonEncode()
3 Likes

How can I get the "name" field out of the JSON object after encoding? Script looks like this now:

def getAllTrendPens():
	data = system.db.runNamedQuery("getHistoryTags")
		
	if data is not None:
		historyTagPaths = data.getColumnAsList(0)
		
		trendLabelPaths = [historyTag+".Trend_Label" for historyTag in historyTagPaths]
	
		
		trendLabels_qv = system.tag.readBlocking(trendLabelPaths)
	
		trendLabels = [label.value for label in trendLabels_qv]
		
		colors = ["#66FFFF","#B266FF","#FF3333", "#66FF66", "#000099", "#FF66B2", "#CCCC00", "#000000", "#606060" ]
		
		pens = []
		
		for i, pen in enumerate(trendLabels):
			if pen is not None:
				color = colors[i % len(colors)]
				#print pen
				#print historyTagPaths[i]
				jsonObject = {
						
								  "name": pen,
								  "visible": False,
								  "enabled": True,
								  "selectable": True,
								  "axis": "",
								  "plot": 0,
								  "display": {
								    "type": "line",
								    "interpolation": "curveLinear",
								    "breakLine": True,
								    "radius": 3,
								    "styles": {
								      "normal": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 0.8,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 0.8
								        }
								      },
								      "highlighted": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 1,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 1
								        }
								      },
								      "selected": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 1,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 1
								        }
								      },
								      "muted": {
								        "stroke": {
								          "color": color,
								          "width": 1,
								          "opacity": 0.4,
								          "dashArray": 0
								        },
								        "fill": {
								          "color": color,
								          "opacity": 0.4
								        }
								      }
								    }
								  },
								  "data": {
								    "source": "histprov:MSSQLSERVER1:/drv:ignition-scada-pc:default:/tag:"+historyTagPaths[i],
								    "aggregateMode": "default"
								  }
						
							}
				pens.append(system.util.jsonEncode(jsonObject))
				
	return pens
	
def getTrendList():

	headers = ["Name", "Pen"]

	pens = trendPens.getAllTrendPens()
	
	names = [pen[0] for pen in pens]
	
	data = [[name,pen] for name, pen in zip(names, pens)]
		
	dataset = system.dataset.toDataSet(headers, data)
	
	return dataset

But my name column is just "{"

Edit: I used system.util.jsonDecode() like so:

def getTrendList():

	headers = ["Name", "Pen"]

	pens = trendPens.getAllTrendPens()
	
	names = [system.util.jsonDecode(pen)["name"] for pen in pens]
	
	data = [[name,pen] for name, pen in zip(names, pens)]
		
	dataset = system.dataset.toDataSet(headers, data)
	
	return dataset

A Document tag type instead of a Dataset tag type might be more friendly in your application.

How so? I'll be binding the dataset to a dropdown's option prop. I have not used the Document datatype.

It should let you avoid the conversion to/from strings. I haven't tried it with a drop-down options prop.