Create Windows Vision from a script

Problem :

We wanted to convert a project from another supervisor to Ignition.

We opted for parsing the pages of the old supervisor into an XML file respecting the standards of a Windows Vision.
Once this is done we will browse the generated XML files and then, by scripting in a Designer scope, we will inject the pages into the Ignition project.
A fairly simple method to do this is to use the CopyPasteHandler.startPaste() class to simulate a Shift + Right Click -> Set XML From Clipboard.
This method calls a confirmation pop-up before generating the Windows.
It is therefore not possible to use it because the goal is to generate several thousand Windows automatically.

In order to get an idea of the composition of the XML of a Windows Vision, you can do Shift + Right click on a window then Copy XML To Clipboard then CTRL + V in a text editor.

You will find below the method used to answer our problem.
You will find all the classes/methods used on the JavaDoc : Overview

Solution :

SCOPE : DESIGNER

###Made by Sagnelonge Enzo - AXONE-IO
###Reverse Engeneering - Module designer & vision-designer
###Ignition v 8.1.10 - 2022/02/11
###CopyPasteHandler - CopyPasteHandler.startPaste()

from java.lang import String
from java.nio.charset import StandardCharsets
from java.io import ByteArrayInputStream
from com.inductiveautomation.ignition.common.project.resource import ProjectResource
from com.inductiveautomation.factorypmi.application.model import WindowInfo

#XML Window
xml = String(event.source.parent.getComponent('taXml').text)

#Retrieval of vision designer
fpmiWindow=event.source.parent.parent.parent.parent.parent
designer = fpmiWindow.topLevelAncestor
workspaceManager = designer.getWorkspace()
workspaceManager.setSelectedWorkspace("windows")
ws = workspaceManager.getSelectedWorkspace()

visionD = ws.getVisionDesigner()
rootPath = visionD.getSelectedWindowFolder()

#Deserialization
data = ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))
context = visionD.getDesignerContext()

deserializer = visionD.getDesignerContext().createDeserializer()
deser = deserializer.deserialize(data)
objects = deser.getRootObjects()
pastedWindow = objects.get(0)


#It is also possible to use addNewWindow but in this case a "name" confirmation pop-up will appear
#visionD.addNewWindow(visionD.getSelectedWindowFolder(), pastedWindow)

#Window Info
windowName = pastedWindow.getName()
newPath = rootPath.getChild("Your Window Name")#windowName

bytes = context.createSerializer().serializeBinary(pastedWindow,True)

#It is also possible to recreate in script an FPMIWindow
#window = FPMIWindow("Main Window")
#window.setSize(790, 1500)
#window.setMaximizable(false)
#window.setStartMaximized(true)
#window.setTitlebarDisplayPolicy(2)
#window.setBorderDisplayPolicy(2)
#bytes = context.createSerializer().serializeBinary(window,True)

wi = WindowInfo()
wi.setWindowName(windowName)
wi.setOpenOnStart(False)
wi.setSerializedCode(bytes)

#Serialization
xmlSerialize = context.createSerializer()
xmlSerialize.addObject(wi)
wiBytes = xmlSerialize.serializeBinary(True)

#Building
builder = ProjectResource.newBuilder()
project = visionD.getProject()

builder.setApplicationScope(4).putData(wiBytes)
builder.setProjectName(project.getName()).setResourcePath(newPath)

project.createResource(builder.build())
6 Likes

Impressive hacking :slight_smile:

Really nice to automate screen creation when switching scada package to Ignition. Thanks Enzo.

:grinning:
Thanks Enzo, migrations to ignition will take a boost. :rocket: