Evaluate Expression Language in Script

I’m trying to write a script that creates a list of alarms setup on an Ignition System.

So far I’ve got it iterating through all the Tags then through all Alarms, but when I print the alarms, many of my bindings show up as expressions (which is fine because that’s what I have) but I would like to evaluate the expressions.

I don’t see a good way to do this. Does anyone know of one?

If not and you would like similar functionality could you vote for my feature request:

http://ideas.inductiveautomation.com/forums/255378-ignition-features-and-ideas/suggestions/20458549-create-a-script-function-to-evaluate-an-expression

Thanks!

I’m pretty sure the expression parser only exists in the designer. Bindings are stored and activated from the serialized objects of the expression after parsing.

Is there actually a tool that does the expression parsing that I can access?
I’m not seeing anything.

We needed to do this on a project, so we created a test expression tag that we would write expressions into through scripting and then read the result out of. It’s not a perfect solution but it worked well enough for our application.

This means the gateway has the parser class available. You might have to go spelunking in gateway.jar. /-:

@JMcguigan I don’t think that will work for us, because many of the expressions have relative tag paths.

@pturmel Thats useful to know. Thanks for clarifying. Should I be able to use that from a normal script or would I have to create an Ignition module for it?

This is as far as I got - so close, and yet so far:

from com.inductiveautomation.ignition.common.expressions.parsing import ELParserHarness
ELParserHarness().parse("1+1", None).execute()

The trick is acquiring an ‘ExpressionParseContext’ for the second argument to parse() - which I’m fairly certain requires a custom module. Without that, expression functions don’t work.

Also - a disclaimer: This is not officially supported or encouraged.

1 Like

It seems the link to my feature request broke. Here is a new link:

http://ideas.inductiveautomation.com/ignition-features-and-ideas/p/create-a-script-function-to-evaluate-an-expression

Here is something to get you started:

In shared.expression, place the following:

from com.inductiveautomation.ignition.client.expressions import ClientFunctionFactory
from com.inductiveautomation.ignition.common.expressions import ExpressionParseContext,BoundTagExpression,TagListener,DefaultFunctionFactory
from com.inductiveautomation.ignition.common.expressions.parsing import ELParserHarness
from com.inductiveautomation.ignition.common.sqltags.parser import TagPathParser
from com.inductiveautomation.ignition.common.sqltags.model.types import DataQuality

class MyExpressionParseContext(ExpressionParseContext):

	def createBoundExpression(self, path):
		try:
			tagPath = TagPathParser.parse(path)
			exp = BoundTagExpression(tagPath)
			v = system.tag.read(path)
			exp.setTagListenerDelegate(TagListener(tagPath, v))
			return exp;
		except:
			return None;

	def getFunctionFactory(self):
		return ClientFunctionFactory(DefaultFunctionFactory.getSharedInstance())
		
parser = ELParserHarness()
parseContext = MyExpressionParseContext()

def parse(expression):
	p = parser.parse(expression,parseContext)
	if p is not None:
		return p.execute().value
	return None

Now, in somewhere where scripts run, place the following as an example

print shared.expressions.parse("{[System]Gateway/Performance/Memory Usage}/1024/1024")

Now, this is a basic implementation. Because parse contexts are so different, you will probably have to extend something other than ExpressionParseContext. Maybe AlarmExpressionParseContext. But i am lazy, so you will have to figure that part out. :wink:

3 Likes