The scripting language in Ignition is Python. The implementation of Python in Ignition is Jython 2.5. Jython 2.5 is written in Java and runs where Java runs.
In this article the terms "Python module" and "Python script" mean the same thing and are used interchangeably. Normally a Python module is a file with Python code in it that has the file extension .py. In Ignition, Python modules are event scripts or user-defined library scripts.
Event scripts are Python scripts that respond to events. There are many kinds of events in different places. Events occur in clients, on components and windows and in the Ignition Gateway. Some of the events that trigger Python scripts to run are mouseClicked, propertyChange, visionWindowOpened, Timer, Tag Change, Startup and Shutdown.
User-defined libraries of Python functions and modules are created and used to reuse Python code and reduce code duplication in Ignition. In Ignition 7.6 and earlier the Script Module Editor is used to create and edit these libraries. All these libraries are prefixed with the package name "app". For example a function call could be app.util.doSomething(). "util" is a Python module and "doSomething" is a function that exists in the "util" module.
Starting in Ignition 7.7 the Script Module Editor and the "app" libraries are being phased out in favor of a new user interface and modules that have a different package prefix.
The "app" modules are being replaced with modules prefixed with "project". Like the "app"-based modules the "project"-based modules are specific to projects and accessible in client scripts and gateway scripts.
The new user interface displays the names of script modules in the project browser. Python modules are edited in a new Script Editor that is embedded into the designer similar to the editing interface for windows. The Script Editor can be floated out of the designer into its own separate window. This is really useful for writing modules and implementing component and window functionality at the same time because the Script Editor can be open on one screen and the window editor open on another screen. Both editors can be easily viewed and worked with together.
The new Script Editor features a quick jump list that lists all the defined functions in a Python module in alphabetical order. Clicking on any of the functions takes the cursor in the editing window directly to the function definition.
A new Auto-Commit checkbox exists that when checked will automatically apply script changes to the designer when changes are made and there are no Python syntax errors.
It is notable that writing scripts using the new Script Editor is smoother than using the old Script Module Editor in Ignition 7.6 and earlier. A problem with the Script Module Editor is when a user switches to a different Python module the scroll and cursor positions in the prior module are lost. A user writing code at line 325 may need to look at something in a different module and so switches to the different module in the Script Module Editor. When the user switches back to the original module the scroll and cursor positions are set to line 0. The user now needs to search through his/her module code to find where he/she was working. This can be frustrating if a user needs to refer to different modules many times during development. This is solved in Ignition 7.7 which does not lose the scroll and cursor positions when switching to a different module. When a user switches back to a module the scroll and cursor positions are the same as when the user left.
Also the Script Module Editor moves the scroll position of code slightly when the "Apply" button is pressed to apply changes to the designer. This is gone in the new Script Editor which doesn't change the scroll position when code is applied.
Ignition 7.6 projects that are imported into Ignition 7.7 will still have the Script Module Editor and the app libraries. In the Project Browser a Legacy Scripts node can be double clicked to bring up the Script Module Editor. Users are able to choose to use app or project for new script modules. New projects created in Ignition 7.7 do not have the Legacy Script node and the old Script Module Editor and app script modules are not used.
Shared script libraries use the same editing interface as the project libraries. Shared scripts exist under the Global / Script Library node in the Project Browser.
Shared scripts are not exported when projects are exported. A new "Export Global" option exists in the Designer for exporting global resources.
Never before was there a builtin way for a client to send data to another client, or for a client to send a message to any project on the gateway, or for projects to send messages to other projects and clients. Now there is. Ignition 7.7 adds the system.util.sendMessage scripting function.
The system.util.sendMessage function provides a way to send data and call functions (called message handlers) in other clients and projects. system.util.sendMessage can specify which clients or projects to send messages to based on a number of different optional criteria. Messages can be sent and received based on who is logged in, user role, host name, project name, client session ID, client scope and gateway scope. This is really awesome.
A new event exists in Client Event Scripts and Gateway Event Scripts called Message. A message handler script is executed when it receives a message from a call to system.util.sendMessage.
Ignition always had Python syntax error detection and reporting. It was done after changes were made and a user clicked the Apply or Save button. In Ignition 7.7 Python syntax errors are shown on the fly as a user types.
Ignition always had the ability to add custom properties to components. Now in Ignition 7.7 custom methods can be added to components. The functionality is called Custom Functions but it is really custom methods.
Once a custom method/function is created on a component it can be called in other functions and scripts. As an example the custom method "printName" could be created for a label component. The label component could then have a "mouseClicked" event script that calls event.source.printName() to print the name of the label.
The IA Labs Scripting Module has been integrated into the Ignition platform. This module brings many new scripting functions. New scripting functions exist for the following functionality:
A list of these new functions can be seen in the IA Labs Scripting Module User Manual.
For the first time Python scripts can be added directly to the configuration of individual SQLTags. Tag Event Scripts always run on the Gateway and are not unique to any particular project which is why they can't reference any project's app.* or project.* Python script modules. Tag Event Scripts can access the global shared.* Python script modules.
Tag events exists for tag value changes, tag quality changes and alarm state changes.
Tag events also work with UDTs. If a tag event script is added to a tag in a UDT then all instances of the UDT will have the same event script on that tag. Changes to a tag event script in a UDT will be reflected in all instances of the UDT. Instances of a UDT have the option of overriding a parent UDT event script.
Ignition 7.7 provides a way to write Python modules outside Ignition in your favorite text editor or IDE and immediately use those modules in Ignition. Your Python scripts can even access and manipulate windows and components in the designer and in clients.
On Linux, Python module files are put in this directory: /var/lib/ignition/user-lib/pylib/. On windows, Python module files are put under the C:\Program Files\Inductive Automation\Ignition\user-lib\ directory.
When changes are made to a Python module file the changes are picked up right away by Ignition and the code is reloaded in the Gateway and the designer and a project update is sent to any open clients.
This is an awesome new way to write Python module libraries for Ignition. It also opens the door to using version control systems with Python libraries used in Ignition.
Of course third-party Python libraries written by others can also be added to the pylib directory.
Python module files that are added to the pylib directory are included in Gateway backups.
Here is an example of using an external Python module in Ignition. The nicktest.py is stored on a Ubuntu Linux computer here: /var/lib/ignition/user-lib/pylib/nicktest.py.
The Python module is used in a button with the following code in the actionPerformed event script:
In Ignition 7.6 and earlier Python functions could not access module-scoped variables. That changed in Ignition 7.7. The new scope change is called Standard Scoping. The old scoping is called Legacy Scoping.
Here is a simple example of Python code that uses Standard Scoping:
Notice that function definitions can access variables and functions that are defined at the module level. The greet module could be written to use Legacy Scoping as follows. This code works in Ignition 7.6 and earlier.
The "project" and "shared" Python libraries use Standard Scoping. The "app" libraries continue to use Legacy Scoping. Gateway scripts still use legacy scoping. By default event scripts use Standard Scoping. New advanced settings exist for changing the scope of event scripts to either Standard Scoping or Legacy Scoping. Projects imported from Ignition 7.6 and earlier use Legacy Scoping by default.
As a passing note, there's also a new "Invoke Later" advanced setting for event scripts that enable an event script to be run after current event processing is complete.
In Ignition 7.6 and earlier a special global variables scope exists. Any variable declared with "global" gets added to a set of global variables that can be accessed by name in any Python script in a project.
Here is an example of two Python modules using the global variables scope in Ignition 7.6.
This works in Ignition 7.6 because the "numbers" variable is made global in the data module and it is accessed in the addNumbers() function in the add module.
The special global variables scope is being phased out starting in Ignition 7.7. The "global" keyword is changed in Ignition 7.7 to work the way it works in Python 2.5.
In Ignition 7.7 the "global" keyword is used for creating or changing module variables within a local context.
Here is an example:
The global keyword was used so the age variable defined in module scope could be changed within the turned50 function. If the global keyword had not been used then a new local age variable would have been created, set to 50, and then discarded.
The special global variables scope still exists in Ignition 7.7 for backward compatibility. Python module scripts using Legacy Scoping have the same access to the special global variables as Ignition 7.6. Python module scripts using Standard Scoping can access the special global variables using the new system.util.getGlobals scripting function.
I would love to hear what you have to say about this article and what questions you might have about Ignition and what features you really like or are interested in. Contact me or leave a comment.
If you would like to be notified of future articles like this then join our mailing list.