I’m trying to make a script that will create a list of all Perspective Styles for the current project (and inherited projects) so that I can display a list of all styles visually. I have a global project, but in the future this might become more than just this, so I want to make it dynamic. I can get the active project name with system.project.getProjectName()
and all projects with system.project.getProjectNames()
, but I’m not sure how to check the inheritance structure?
There’s nothing exposed to general purpose scripting, but if you know how to get a GatewayContext (check around the forums) you can call getProjectManager()
and then from the project manager getProjectManifests()
, which will return a dictionary of {string: ProjectManifest}
, where each ProjectManifest
has a getParent()
method - with some tree-walking you can build up your inheritance structure that way.
Thanks Paul!
This walks through each project and pulls out the styles as dictionaries with:
- projectName
- styleFullPath (directory filepath)
- styleParentPath (relative-to-project path, excluding style name)
- styleName (just the name of the style; styleParentPath + ‘/’ + styleName = the full path to the style for Ignition purposes)
The relevant part of the code to this topic is:
from com.inductiveautomation.ignition.gateway import IgnitionGateway
context = IgnitionGateway.get()
projectMgr = context.getProjectManager()
projectMfst = projectMgr.getProjectManifests()
projectName = system.project.getProjectName()
projectMfst[projectName].getParent() # this is the name of the inherited project of the active project
This is the full script:
def findFolderStyles(projectName, folderPath):
import os
import sys
styles = []
for root, subdirs, files in os.walk(folderPath):
if 'resource.json' in files:
styles.append({'projectName':projectName,
'styleFullPath':str(root), # this is the full directory path to the style in Windows
'styleParentPath':'/'.join(root.replace(folderPath,'').split('\\')[:-1]), # gets the Perspective Style path used in Ignition, excluding the style name itself
'styleName':str(root.split('\\')[-1])
})
return styles
def findProjectStyles(projectName):
projectParentFolder = "C:\\Program Files\\Inductive Automation\\Ignition\\data\\projects\\"
styleClassesRelPath = "\\com.inductiveautomation.perspective\\style-classes\\"
styleClassFullPath = '%s%s%s' % (projectParentFolder, projectName, styleClassesRelPath)
return findFolderStyles(projectName, styleClassFullPath)
def findRelevantProjectStyles():
from com.inductiveautomation.ignition.gateway import IgnitionGateway
context = IgnitionGateway.get()
projectMgr = context.getProjectManager()
projectMfst = projectMgr.getProjectManifests()
projectName = system.project.getProjectName()
styles = []
# get the Perspective Styles defined in the current project
styles.extend(findProjectStyles(projectName))
while projectMfst[projectName].getParent() != '':
# get the parent project
projectName = projectMfst[projectName].getParent()
# get the Perspective Styles defined in the parent project
styles.extend(findProjectStyles(projectName))
return styles
styles = findRelevantProjectStyles()
udtInstances = styles
self.getChild("FlexRepeater").props.instances = udtInstances
Hello,
This is an old topic but just to share a more convenient method witch not browse windows files.
def findRelevantProjectStyles():
from com.inductiveautomation.ignition.gateway import IgnitionGateway
styles = []
projectName = system.util.getProjectName()
context = IgnitionGateway.get()
projectManager = context.getProjectManager()
runtimeProject = projectManager.getProject(projectName).get()
# Retrieve all ressources from project and its parents
allProjectResources = runtimeProject.getAllResources()
for projectResourceId,immutableProjectResource in allProjectResources.items():
ressourceType = immutableProjectResource.getResourceType()
typeId = ressourceType.getTypeId()
# Check if resource was a style-classes
if "style-classes" == typeId:
if not immutableProjectResource.isFolder():
styleFullPath = immutableProjectResource.getFolderPath()
styles.append({'projectName':immutableProjectResource.getProjectName(),
'styleFullPath':styleFullPath, # this is the full directory path to the style in Perspective Style
'styleParentPath':styleFullPath.rsplit("/",1)[0], # gets the Perspective Style path used in Ignition, excluding the style name itself
'styleName':immutableProjectResource.getResourceName()
})
return styles
Very nice, thanks for sharing!
I’m new to this, Can somebody help me how to use these functions as I’m facing difficulty, any docs related to this, how that import gateway is working what all things are available inside that, how to check that, how it can be utilized, suppose I had multiple gateways then how I can get details of those gateway by using this scripts. Can someone please help me on that.
You’ll need to run the function from the gateway scope(e.g. from a tag change script, perspective component event handler/script transform, gateway timer script, etc.).
To run it on multiple gateways from one, you would need to have them all attached on the GAN (gateway network) and then you would need to use system.util.sendRequest
to execute a function on the remote gateways.
Use this as a reference for the api classes etc. Note though that a lot of it is not publicly documented so most of the code on the forums dealing with this come from IA staff. Also note that using these methods is therefore completely unsupported (unless you get help on the forum) and is prone to breaking in future upgrades.
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/index.html
Thank you very much @nminchin really appreciate the time you spend for this detailed reply. I saw that document, but can’t understand that. there is an option to import ignition gateway, so what all functions are available in there. suppose I found some other script from this forum itself like
from com.inductiveautomation.ignition.gateway import IgnitionGateway
projectNames = list(IgnitionGateway.get().getProjectManager().projectNames)
I’m not understanding how it is working.From where that list is getting. I checked that link, it’s getting hard for me to find how it is working, can you help me with an example if possible how to read from that url for several packages which is available. I’m a noobie. Can u please help.?
Hi John. You are going to struggle a bit because you are asking for documentation for an object that IA has deliberately chosen not to document. You are also asking about access to information for which there is no supported method. People are trying to help you via unsupported methods, but they tend to be complicated and there is no magic wand.
Nick linked to the SDK documentation, which is the public "schematic" for Ignition's "control panel". It is bog-standard JavaDoc. If you learn to read that "schematic", you'll be able to infer a great deal about the undocumented parts. Reading JavaDoc is easiest if you have experience with Java. People who use jython a great deal (experienced Ignition script writers) often pick it up too, as jython permits using it's environment's java objects in a form close to native python.
Consider reading every topic in this search:
https://forum.inductiveautomation.com/search?q=import%20IgnitionGateway
They are all examples of the use of this particular unsupported platform object.
Another source of information would be the introspect
function from my inspect.py
helper library. These topics discuss it:
For this particular line, look at:
IgnitionGateway -> GatewayContext?:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/ignition/gateway/model/GatewayContext.html
get() -> GatewayContext
No idea about this one..
getProjectManager() -> ProjectManager
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/ignition/gateway/project/ProjectManager.html
projectNames -> list of strings:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/ignition/gateway/project/ProjectManagerBase.html#getProjectNames()
Also FYI, I don't understand the hows or the whys, but JavaBeans something or rather (that's the technical term) means that a Java getter and setter in Jython can be called without the get/set in the method name. But only sometimes.... @pturmel @pgriffith?
Q's:
- Why can
getProjectNames
be subd asprojectNames
butgetProjectManager()
can't be subd asprojectManager()
? but it can be subd forprojectManager
without the brackets? (it seems you can't use the method-without-the-get/set if you include args or brackets?)
e.g.runtimeProject = projectManager.project(projectName).get()
doesn't work withproject(projectName)
it has to begetProject(projectName)
- Also what's the
get()
for inIgnitionGateway.get()
? - Is it possible to inadvertently spawn another IgnitionGateway from script?
I probably should have asked these questions a long time ago...
Thank you very much for the time that you spend. I will definitely check. Thank you.
Superb, Thank you for that detailed explanation, now I will try to figure that around. superb guys. thank you for the support. I’m really loving this forum.
One of the best parts of Ignition imo! Compare Ignition's forum to other SCADA forums which are a pile of garbage from the 1900's You also get the devs always on here which is absolutely invaluable! But really, any question is fair game and you're likely to get a response within the day at least, if not within a few minutes or hours, depending on timezones. And the reason for that is that Ignitioners tend to be a passionate bunch since we're actually excited to use a product that wasn't obsoleted 15 years ago
-
getProjectNames
is property name that yields a method. You invoke methods using the parentheses operator. It’s name follows the NetBeans rule for a getter, so Jython injectsprojectNames
as a named property that yields the result of the method. (The latter is one less step for the interpreter, so will run slightly faster.) -
IgnitionGateway
is a class. You can’t instantiate it yourself..get()
is a static method that retrieves the singleton instance that the platform creates during startup. Remember, this is undocumented, unsupported stuff, and the singleton pattern is an implementation detail. You just need to know that you have to work with an instance, not a class. -
No, the constructor is private, IIRC.