I’m trying to write a script to go through the properties on each template piece so that I can easily audit the scripting code. There’s a ton of template pieces to go through, doing this manually will be tedious and prone to error
Does Ignition have something built-in? Something like system.tag.browseTags but for templates?
If you will add these two functions to my original post that pturmel linked you will have everything needed.
def getTemplateInstance(event, templatePath):
"""
Return Template Instance.
Pass the path into here.
"""
context = getContext(event)
project_obj = context.getProject()
templateManager = context.getTemplateManager()
templateId = templateManager.getId(templatePath)
return templateManager.getTemplateInstance(templateId)
def getTemplateInstanceProperties(templateInstance):
"""
Returns list of properties on template instance.
Other cool methods are getShortDescription and getPropertyValue, setPropertyValue etc.
if you dir(templateInstance) the methods are available.
"""
return [str(prop.getName()) for prop in templateInstance.getProperties()]
raymond1982 - Bro. You are awesome. I like that other thread, answered 3 years after the question… good example of why necromancing rules are stupid… it’s not like the problem goes away
Thanks a ton, that takes care of the heavy lifting
No problem man. I have learned a lot on the forum and am trying to contribute on some of the more esoteric items. We use meta programming and reflection/inspection to achieve some of the more dynamic things in our project. It would be nice if these were canned system functions but the ignition devs have a tremendous workload so id rather just do it myself than burden them with a feature req.
Right? I agree. I’ve feature requested a stop/interrupt button for the script console, that seems like a much bigger fish to fry, especially since while this isn’t as simple (at least the first time), it can be done, whereas the other is a gaping hole in the feature set that really needs someone on the Inductive team to fix
yes. This may require some explanation. Instead of using an event object i create a Jframe and grab the projects highest most frame reference and get it that way… I work in console a lot too and this helps. This is a singleton class which makes it nice. Load it at startup and dont worry about getting it again.Heavily unsupported.
from system.util import CLIENT_FLAG, DESIGNER_FLAG
from javax.swing import JFrame
from java.awt.event import WindowEvent
try:
from com.inductiveautomation.ignition.designer import IgnitionDesigner
except ImportError:
pass
from com.inductiveautomation.factorypmi.application.runtime import ClientPanel
class ActiveContext(object):
"""
Singleton for a stable ignition context reference.
NOTE: Mainly for code running where there is no event
object to derive context access. i.e.
scripts launched automatically or script-console..
# Has been tested for Designer,
# Script Console, Client [Full Screen, Published].
# We call this as a startup script.
# Tested on Ignition Version 7.9.3
# Certian API dependencies may need to be resolved
# on versions before or after (7.9.3).
"""
def __new__(cls):
"""
Hook into the class constructor.
Adds an class attribute reference to the
instance.
"""
if not hasattr(cls, 'instance'):
cls.instance = super(ActiveContext, cls).__new__(cls)
# we only need to establish the context reference 1 time.
cls.instance.run()
return cls.instance
def run(self):
"""Get context."""
print '*************************** Acquiring Project Context ***************************'
self.valid = True
self.context = self.resolveContext()
def isValid(self):
"""Is Context Valid."""
return self.valid
def setValid(self):
"""Set Valid State."""
self.valid = False if self.valid else True
def resolveDesignerContext(self):
"""Return designer context."""
try:
return IgnitionDesigner.getFrame().getContext()
except AttributeError:
pass
self.isValid()
def resolveClientContext(self):
"""
Attempt to resolve client context.
By creating a frame it prevents the need to
traverse the object heirarchy. i.e. parent.parent....
"""
# acquire project name.
projName = system.util.getProjectName()
# Frame title.
frame_name = 'ThrowAway'
# Create disposable top level frame object.
frm = JFrame(frame_name)
# Adjust close behavior.
frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
# get the windows.
windows = frm.getWindows()
# cleanup frame.
frm.dispose()
# iterate windows, filter on the title containing the
# project name.
for window in windows:
try:
if projName in window.getTitle():
pane = window.getContentPane()
# Compare the content pane instance
# to the ClientPanel object.
if isinstance(pane, ClientPanel):
if hasattr(pane, 'getClientContext'):
return pane.getClientContext()
except AttributeError:
pass
self.isValid()
def resolveContext(self):
"""Attempt to resolve the Context."""
current_flag = system.util.getSystemFlags()
ctx = self.resolveDesignerContext
# If False assumes the client context.
if current_flag not in [DESIGNER_FLAG, 3]:
ctx = self.resolveClientContext
return ctx()
def __call__(self):
"""Calls to the Instance return the Context."""
return self.getContext()
def getContext(self):
"""Return Context."""
return self.context
ctx = ActiveContext()
def initActiveContext():
"""Called from startup script"""
return ctx
That’s great, I’ve wanted to get project stuff from the designer script console occasionally, never knew how to do it. I hacked up your script a bit for the designer to get the global project, then I can see scripts, pipelines, etc that I don’t think I could before:
try:
from com.inductiveautomation.ignition.designer import IgnitionDesigner
except ImportError:
pass
try:
cx = IgnitionDesigner.getFrame().getContext()
except AttributeError:
cx = None
if cx is not None:
globalProject = cx.getGlobalProject().getProject()
Lets take the unsupported level up a bit though. Can we get the global project, but in Gateway context? Like in a gateway timer script. WITHOUT using SRContext.
To be honest even if knew i wouldn’t post it. The possibility of someone crashing their gateway is very real. That SRContext is heroically unsupported.
Template Manager is a singleton which takes the context as an argument in the constructor. By adding the below and using the above code copied into my script console this is what i got. Seems to work fine. You would have needed to edit the code that depended on the event object. If you`re working at this layer you can never be sure how much explanation is needed.
from com.inductiveautomation.factorypmi.application.model import TemplateManager
print TemplateManager(ctx.getContext())
>>> com.inductiveautomation.factorypmi.application.model.TemplateManager@6270e73a