In a component script, is there a way to evaluate a string as a line of the script?
For example...
system.db.runPrepUpdate(query, [10])
could be replaced with...
i = 10
evaluate(stringFormat("system.db.runPrepUpdate(query, [%d])", i)
In a component script, is there a way to evaluate a string as a line of the script?
For example...
system.db.runPrepUpdate(query, [10])
could be replaced with...
i = 10
evaluate(stringFormat("system.db.runPrepUpdate(query, [%d])", i)
What problem are you trying to solve? You can just use,
i = 10
system.db.runPrepUpdate(query, [i])
What problem are you trying to solve? Let us help you find a safe way to do what you need.
I am trying to make 'save recipe' 'upload recipe' 'download recipe' buttons that will dynamically pull all the tags from a folder and add it to the query
That doesn't explain why you need to evaluate a string as jython/python. You might possibly need to construct a SQL query dynamically, but careful DB architecture should avoid that, too. Please share some examples of the data you need in these recipes.
(For a fully generic way to associate tags and values, consider examining the database architecture for Ignition's own historian. No dynamic jython nor dynamic SQL required, aside from partitioned table names.)
I don't think you've thought this through. For example, upload and download can't both be reading tags and writing to the database. One should transfer from tags to DB and the other the opposite - depending on which way you think is "up".
When you need to write to the database you read your tags into a list and provide that list of values as arguements to your query.
# Pseudo code ...
tagPaths = ["path/tag1", "path/tag2", "path/tag3"]
qualifiedValues = system.tag.readBlocking(tagPaths)
args = []
for tag in qualifiedValues:
args.append(tag.value)
query = """INSERT INTO myTable (recipeParam1, recipeParam2, recipeParam3)
VALUES (?, ?, ?)"""
system.db.runPrepUpdate(query, args)
Further reading:
https://docs.inductiveautomation.com/display/DOC81/system.tag.readBlocking
https://docs.inductiveautomation.com/display/DOC81/system.db.runPrepUpdate?src=sidebar
There are separate buttons for selecting, saving, deleting, uploading, and downloading. First 3 push and pull from the sql database and the last 2 just assign memory tags to opc tags
Oooo! Sounds like an anti-pattern. Specifically, that you can't have two or more independent clients, each reviewing/editing/saving recipes, while another (perhaps with different privileges) transfers to/from the PLC.
Basically, don't use memory tags for user interfaces. User interfaces should use session custom properties (in Perspective) or Client Tags (in Vision) to perform the intermediate handling of recipe values.
(This anti-pattern is common when people with stand-alone HMI experience use a high-quality SCADA system for the first time.)
Why can't/shouldn't mem tags be used for recipe handling? Is it because they can be accessed by other clients in the gateway?
Where should mem tags be used? Just for communicating between clients?
Precisely. If two clients, or client + designer, are both looking at that UI, they will interfere with each other.
Memory tags hold process state, not UI state, or hold UI information that is required to be synchronized across clients.
Awesome thank you! Off the top of your head are there any other considerations to make going from stand alone HMIs to Ignition?
Not everything needs to be, nor should be a tag. This is the biggest thing for me, particularly if you come from a long history of AB experience. Some things that you were forced to make a tag in other platforms just don't need to be that.
I've been trying to keep everything in scripts which is really nice after Wonderware
So, the first thing I would tell you is this: If you can do it as an expression, you absolutely should.
Use indirect binding and custom properties in combination with expressions. The expression language is ridiculously powerful, (especially if you can utilize @pturmel free Simulation Aids module). There are things that it can't do, like dynamic recursive searches, but for the most part I have found nearly everything I need to handle can be handled there.
Scripting is an extremely powerful tool, and it can unlock many doors, but some of those doors are locked for good reason.
I would recommend exhausting methods for accomplishing tasks with property bindings and expressions before finally moving on to a script. Otherwise you'll find your self with a nest of performance issues without really knowing why they're performing poorly (and that's the best outcome).
Actually, don't. Or rather, use expression bindings first, where you can. They are much more efficient than scripted equivalents. Anywhere you are using a property change event of some kind, take a hard look at whether it should be a binding at the receiving end.
Scripts that handle other events likely cannot be converted to expression bindings, so don't look hard there. However, avoid writing event scripts or transforms that are more than one or two lines. Those should call a project library function instead. That is where scripts are best maintained and most performant (and can have cached/static values that persist from one call to another).
Much appreciated!
When making new projects for new machines, should you also be making new databases and connections and stuff that are associated with that project?
Varies. Generally not multiple databases, as that complicates site-wide dashboards.
Just for clarification, do the different schemas in MySQL count as different databases or are the different servers the databases?
Basically does this count as 3 databases or just 3 groups in the same database?
The point where it counts is when setting up your connection(s) in Ignition. If you can access all of the schemas from one Ignition connection, it is effectively one database. Probably still not recommended, though, as it will likely confuse your designer's query utilities.