Autogenerate Views inside the Perspective View Folder Structure (Self Aware SCADA)

@PGriffith How would I invoke the “Save or Save All ‘actions’ in the designer”?

Currently I am able to create new views in the designer with a script using the classes and methods you’ve suggested. After manually saving the project updates in the designer the new views are displayed in perspective. I’m trying to automate the saving step of this process.

Also would and approach using the ‘updateProject’ method below work or something similar?

No. updateProject is the opposite direction; it’s pulling changes from the gateway into the current Designer session. Like I said earlier - there’s no direct way to invoke the save/save all actions.

IgnitionDesigner has a private method handleSave. With reflection, you can invoke this method despite it’s “private” status. It takes the following arguments:

boolean saveAs,
String newName,
boolean commitOnly,
boolean skipReOpen,
boolean showDialog

Whatever you do here is totally unsupported and subject to change between Ignition versions. This private method could start taking a new argument in the next Ignition release, and you would only know about it once your code stops working.

@PGriffith could you please give me and example of how to invoke the "handleSave" method correctly with jython reflection? I've tried multiple variations and have been unsuccessful. With my latest attempt I can't figure out if I'm calling handleSave incorrectly or there is additional requirements that I'm missing.

Thank you for the help!

If you install Ignition Extensions it adds a system.project.save() method. You can also look into the code to see how I'm calling it via reflection.

2 Likes

@PGriffith This is awesome thank you!

@PGriffith How do I assign JsonObjects to other JsonObjects?

In the example below I'm trying to set the anchor property to the rotate property for the position argument in the ComponentConfig() object but unable to with addProperty().

Instead of addProperty, you just use add(name, element): JsonObject - gson 2.9.1 javadoc

1 Like

@PGriffith Thank you!

@PGriffith I'm receiving the import error below when trying to call a script that contains the Java Classes being used to build the views inside the designer from an onClick event inside a view.

However the same script runs without errors when calling from the script console.

Would this be caused by a scope limitation on the java classes?

Yes. The script console is running inside the local designer scope.
Any scripting in Perspective (even inside the designer in Perspective) is actually running on the gateway. The gateway and the designer have totally different classes available to them. Generally you'll see this in their package names; e.g. com.inductiveautomation.perspective.gateway or com.inductiveautomation.perspective.designer. Classes you can use in both locations will have common in their package name.

2 Likes

@PGriffith I used the system.project.getProject() function you created instead of importing IgnitionDesigner and works great thanks again!

Now when I call the same script I mentioned earlier from an onClick event inside a view I'm getting 'ImportError: No module named perspective'. It occurs on all of the com.inductiveautomation.perspective.common imports. I'm assuming since it has common in the name it is not a scope issue.

Any thoughts on the cause and how to resolve this issue?

Thank you!

In the designer, every module shares a single 'classloader' - this is a Java/JVM mechanism. It means that all of the modules can look at each other's code at runtime, essentially.

In the gateway (including Perspective, as mentioned above) you don't have arbitrary access to other modules. With the exception of scripting functions that manually link in specific pieces of a module's functionality, you don't have any direct access.

What you can do instead, especially since you already have Ignition Extensions installed, is something like:
eventConfigClass = system.util.getContext().getModuleManager().resolveClass("com.inductiveautomation.perspective.common.config.EventConfig"), and so on for the different classes you want to load.

3 Likes

@PGriffith I am able to use 'createOrModify()' from the script console but when I execute from a perspective view in the designer I'm getting the AttributeError below.

Is this because system.project.getProject() is a DesignableProject when used in the script console and a RuntimeProject when used on a perspective view? (I'm referencing the Ignition Extensions summary)

designableProject = system.project.getProject()
designableProject.createOrModify(newView)

Caused by: org.python.core.PyException: AttributeError: 'com.inductiveautomation.ignition.common.project.Ru' object has no attribute 'createOrModify'

Yes. On the gateway you can only make direct modifications as resource operations; it's a different API to how you would interact with the designer. It's possible, but would require some rework of the script. Start with ProjectManager.push and ChangeOperations as your research targets.

1 Like

@PGriffith the push() TypeError expects 2 arguments but I only see one in the documentation. Do you know what I'm missing?

Thank you!

Looks like you are trying call it statically. You need an instance of ProjectManagerBase, not the class. (The instance becomes the self first argument that the error is referring to.)

2 Likes

@pturmel thank you for the help!

I'm getting the 'No visible constructors' TypeError on both instances (ChangeOperation() and ProjectManagerBase()).

Am I calling them correctly?

You won't be able to construct that. You have to get one somewhere, usually indirectly through the gateway context.

1 Like

This is the part I struggle most with! probably because most of it is undocumented :slight_smile:

ChangeOperation has various static methods to construct:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.21/com/inductiveautomation/ignition/common/project/ChangeOperation.html#newCreateOp(com.inductiveautomation.ignition.common.project.resource.ProjectResource)

A ProjectManager can be retrieved from GatewayContext.