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!
1 Like
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
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.
3 Likes