Nick Mudge Ignition Software Consulting & Development

One of the Perfect Abstractions Ignition project developers developed a very useful tool for viewing the Ignition wrapper.log file in an Ignition client or designer.

Find out what the Ignition wrapper.log file is and why it is useful.

We are releasing the Wrapper.log Viewer project here for other people to use. Download this project file: WrapperLogViewer.proj. Ignition 7.7.5 or higher is required to import the project.

Here is a screenshot of the project:

The Wrapper.log Viewer project was designed to be very easy to install and use. To install it import the Wrapper.log Viewer project into an existing Ignition project or import it as a new project. Note that importing into an existing project will delete existing Gateway Event Scripts in the project. That is all that is needed to install it. No database connections or anything else.

To use the Wrapper.log Viewer project in an Ignition designer open up the ViewerWindow window and put the designer into preview mode. The current contents of the wrapper.log file will display within 5 seconds.

To use the project in a client simply start a client and open the ViewerWindow window. Very easy, nothing to it.

The Wrapper.log Viewer project has been tested on both Windows and Linux.

How it Works

The Wrapper.log Viewer project has a Gateway Timer Script that runs every 5 seconds. It checks to see if the wrapper.log file has been modified. If it has been modified then the last 64,000 characters of the wrapper.log file are copied into a memory tag. The memory tag is automatically created when the project is first used.

A binding and Python scripting in the ViewerWindow window updates the display of the wrapper.log file when the content changes.

The AutoRefresh button is used to toggle on and off the functionality to automatically update the display of the wrapper.log file content. The auto update functionality is on by default.

The ViewerWindow window automatically scrolls the display of the content to the newest content as it comes in.

The Highlight Text field is used to highlight text in the wrapper.log contents that is displayed. This is useful for searching and finding specific text in the content.

Find out what problem the Wrapper.log Viewer project solves.

More Useful Projects

The Perfect Abstractions development team is interested in developing more useful tools and projects. If you think of something that you want feel free to tell us. We might implement it.

The wrapper.log file is a file on the file system where Ignition is installed.

Ignition logs errors and various important information about what Ignition is doing to the wrapper.log file.

The wrapper.log file is used to test and debug Python scripts that execute in the Ignition Gateway. Gateway Event Scripts, Tag Event Scripts, Python scripts in Alarm Notification Pipelines and Python scripts in Sequential Function Charts all output print statements and logging statements to the wrapper.log file, and the wrapper.log file can be used to debug or test any of them.

The wrapper.log file also collects a lot of information about the internal workings of Ignition. If something is wrong with Ignition the wrapper.log file is a place to go to see if some error is being thrown causing things to not work correctly. If you want to know what and when something is happening in the Ignition Gateway the wrapper.log file may have some useful information about it.

The Problem

Ignition is very often installed on a computer server that most people do not have local access to -- meaning that people have to gain remote access to the computer in order to access files on the computer. Since the wrapper.log file is stored on the hard drive of the computer where Ignition is installed people have to use a remote access tool like RDP for windows or SSH for Linux or something like VNC. This also means these people need a username/password to log in to the server. This can be a lot of trouble just to view the wrapper.log file.

Some developers may not have or want remote access to the server where Ignition is installed, but if they don't have it then they can't view the wrapper.log file. This problem is solved to a degree by having administrative/configuration access to Ignition's System Console webpage where much of the same information from the wrapper.log file is displayed. But again, it requires that users have access to the configuration of Ignition's gateway in order to see logging information. Developers may not have administrative access to the Ignition gateway. And system administrators may not want to give administrative access to Ignition to all Ignition developers.

The Solution

The Wrapper.log Viewer project solves the problem by providing easy access to the wrapper.log file in an Ignition client or designer.

A year ago I started Perfect Abstractions. It was just me delivering custom Ignition programming to clients.

That was great but I was only able to do so much work on my own. I want my company to grow and be able to to handle a much larger volume of work.

Some time ago I found a bright software developer and helped him get up to speed with Ignition development. He now works with me on client projects. More recently I found four more bright people and they are currently in training to become expert Ignition developers.

Perfect Abstractions is changing from being a one-man company to being a team of Ignition developers. We will be able to handle more clients and projects.

My job is changing. Instead of implementing all projects myself my Ignition development team will help. It is my job to understand what the client needs and use my team to get it delivered.

If you have software applications that need to be implemented contact me and we can talk about how it can be done.

Edit (19 May 2015): Four people are in training to become Ignition developers so I am not hiring now. But I am interested in talking with people about future possibilities.

Awhile ago I found an experienced software developer and trained him on developing projects with Ignition. He is now working with me as a subcontractor on an Ignition project. The experience has been great. I need to do it more.

I am interested in finding programmers to get to know, train on Ignition and hire as employees or subcontractors. I am building a team of Ignition developers.

Here is what I am looking for:

Required

  1. Competent at programming with a firm grasp of programming in general.
  2. Ability to learn new things quickly.
  3. Communicates well verbally and in writing.

Not Required, but nice to have

  1. Knowledge of and experience with Ignition
  2. Python programming knowledge and experience.
  3. Java knowledge and experience.
  4. PLC programming knowledge and experience.
  5. Manufacturing knowledge and expericence.
  6. Software development knowledge and experience.

Most of the work is done remotely.

If you are interested then let's talk.

Recently Chris Powell, who I met in the Ignition Chat Room, started writing blog posts about Ignition - giving examples of how to use various functionality.

He wrote a guest post on my blog about Ignition Power Tables.

He recently started his own blog about Ignition. His first posts are about Ignition's Calendar Components and Ignition Template Repeaters.

For a long time there was no officially supported way to create screens dynamically in Ignition. Screens were created up front by designers/programmers by dropping components on windows and then scripting and configuring them.

There was no dynamic creation of components based on current data from a database or other source of information.

Ignition Containers

This has changed in Ignition. It started with the Template Repeater which was released in Ignition 7.7.0. This component allows an Ignition template to be configured and repeated any number of times. A vertical or horizontal scroll bar is automatically added to the template repeater when there isn't enough space for all templates to fit within the designated space. This is a great component but has various limitations; for example it only allows one template to be repeated in a single direction.

The Template Canvas was released in December 2014 in Ignition 7.7.2. The Template Canvas is the most powerful, most significant single component to be released by Inductive Automation since Ignition itself was released in 2010.

The Template Canvas makes it possible to dynamically create any number of instances of any number of templates. The position, width and height of each template instance can be configured. If there isn't enough space for all template instances to fit within the designated space scroll bars are automatically added - vertical or horizontal or both. Once all templates are displayed on a screen their position and configuration can be changed through Python scripting.

How to Use the Template Canvas

First a Template Canvas is dropped onto an Ignition window. You will see a box of ant track lines. The Template Canvas is a kind of Ignition container and the ant track lines show the dimensions of the Template Canvas. This shows how much space the Template Canvas will use on the window. Change the position and width and height of the Template Canvas as needed.

Templates Property

The Templates property of a Template Canvas is a dataset that contains template instance information. Each row of the dataset specifies a template to use to create a template instance and its position and layout. Populating this property is what creates and positions template instances. Here is a view of a Templates dataset:

Ignition Templates Dataset
Ignition Containers

There are different ways to populate the Templates property. One way is to use the Template Canvas Customizer. Right click on the Template Canvas in the designer, hover the mouse over Customizers, then choose Template Canvas Customizer. Using this customizer you can select templates to use and the layout and positioning. The Template Canvas Customizer also lets you input values for any template instance parameters. The Template Canvas Customizer is a static upfront way to create the Templates dataset. Using it is a good way to get started with the Template Canvas.

A dynamic way to create the Templates property (and therefor dynamically create template instances and configuration) is to bind a database query to the Templates property.

Python scripting is the most powerful and flexible way to dynamically create a dataset for the Templates property. Python provides many tools and capabilities to analyze and manipulate data and many ways to access sources of data.

Layout and Positioning

There are two ways to position template instances: Absolute Positioning and Layout Positioning.

Absolute Positioning uses absolute x and y coordinates and values for width and height. The x, y, width and height columns in the Templates dataset are used for Absolution Positioning. x and y coordinates need to be calculated for each template instance.

Layout Positioning uses a powerful and easy to use layout manager called MigLayout. The "layout" column in the Templates dataset is used for Layout Positioning. The layout column holds a MigLayout string for each row in the dataset.

Documentation for MigLayout is here: MigLayout QuickStart

Here is a handy MigLayout cheetsheet: MigLayout Cheetsheet.

Initializing Template Instances

By initializing template instances I mean setting any template parameters for each instance. There are a couple ways to do this.

The Template Canvas Templates property can have a column called "parameters". This column holds a string representation of a Python dictionary. Each item in the dictionary contains the name of a template parameter and a value to be set for the template parameter. The Template Canvas Customizer uses the "parameters" column to set parameter values for template instances.

Another way is to use the initializeTemplate extension function on the Template Canvas. Remember an extension function is an editable function on a component that exists to customize it.

initializeTemplate Ignition Script

The initializeTemplate function is called for each template instance created by the Template Canvas. The initializeTemplate function takes as an argument the template that it is called for. This extension function provides a chance to execute a Python script for each template instance to configure it, set template parameters etc. Each time the Template Canvas Templates property changes the initializeTemplate extension function runs for each template instance.

Template Canvas Video & Demo

I made a Template Canvas demo project and a video that shows how to use the Template Canvas. To see the video and get a copy of the Template Canvas demo project signup for my email list.

Okay you can see the video of the demo project here, and download the demo project here.

You are free to have and use the Template Canvas demo project for your own purposes.

Here's a screen shot of the Template Canvas demo application:

initializeTemplate Ignition Script

It is common in Ignition to want to copy visual displays, configuration and functionality. For example, if 20 motors are needed on a window create one motor and copy it 19 times.

But later those 20 motor displays will need to be changed. You know it will happen. Someone will request a change to them or you realize how to make them better etc. etc.

In the past you would need to change each motor display individually. In a large project where there are lots of copies of things the amount of work to make changes really adds up.

Ignition templates solve this problem. This is how:

  • Something is designed. This is a template.
  • The template is used in many places. Each use of a template is called a template instance.
  • When it needs to change it is changed in one place one time. All template instances are automatically updated.

Here's a quote from the Ignition User Manual:

Templates are components that can be re-used across many windows. They are designed separately, outside of any window. After being designed, they can be added to any of the windows within a project. The true power of a template is that if you change its design, all uses of that template across all windows will reflect those changes. This gives templates a major advantage over a copy-and-paste style of design.

Different Template Instance, Different Data

The graphics and functionality of each template instance (from the same template) is the same but the data used by each template instance is different.

Example: Motors template is used to create the Motor A template instance. The data from the actual physical Motor A on the plant floor is fed into the Motor A template instance so that it can display that data. The Motor B template instance is fed Motor B data etc.

Also see an Introduction to Templates.

This is a guest post from Chris Powell.

Recently, Inductive Automation added a new table to their list of components. The name 'Power Table' is not understated. I want to share a few of the features I have found for some of the non-programming background developers out there.

Since the release of Ignition V7.7, Inductive Automation has added Extension Functions to several components. Extension functions are editable functions that exist on components that are used to customize components. Let us go over some of these features as they relate to the power table component.

First, put a power table table on a window. Then select TestData to load the table with data.

Ignition Power Table

You can paste the code from the following sections into each power table extension function to see how it works. I hope this will make your use of power tables faster and easier to implement in your next project.

configureCell Extension Function

I use this feature to highlight each individual cell on each row based on the row's value. With this code, I can change the background color based on that cell's value. You may add custom properties to the power table and access them with 'self.propertyName'. I created the custom property called 'highsp' and used it in line 2. Here is code for this:


    if colName == 'Float Column':
        if value > self.highsp:  
            return {'background' : 'red'}
        elif value < 0.2:
            return {'background' : 'yellow'}
        else:
            return {'background' : self.background}
    elif colName == 'Boolean Column':
        if value == 1:
            return {'background' : '0,125,0'}
        else:
            return {'background' : self.background}
    else:
        return {'background' : self.background}

The only issue I noticed so far is the repaint of the table if you are using dynamic properties. So if my 'highsp' property changed, the table does not repaint. To fix this, add the following code to the propertyChange event handler:


if event.propertyName == 'highsp':
    event.source.parent.repaint()

This will force the table to repaint and you will see the changes.

While we are on the property changed event handler, this is where you will edit the Columns Attributes Data table. You create the entire table because it does not create itself unless you use the Table Customizer. The following code will build the Columns Attributes Data table from scratch each time new data is loaded. Add the following code to the property change event handler.


# Let's create the Column Attributes Data table.
# First, let's set the defaults.
if event.propertyName == 'data':
    name = ''
    dateFormat = 'MMM d, yyyy h:mm a'
    editable = 1
    filterable = 0
    hidden = 0
    horizontalAlignment = '-9'
    label = ''
    numberFormat = '#,##0.##'
    prefix = ''
    sortable = 1
    suffix = ''
    treatAsBoolean = 0
    verticalAlignment = 0
    wrapText = 0
	
    # Now let's get rows loaded in the table.
    rows = []
	
    table = event.newValue
    for k in table.columnNames:
        #Name of the column I want to be different from default.
        if k == 'Int Column': 
            name = k
            # Makes the 'Int Column' hidden.
            newrow = [name, dateFormat, editable, filterable, 1,
            horizontalAlignment, label, numberFormat, prefix,
            sortable, suffix, treatAsBoolean, verticalAlignment,
            wrapText]
        else:
            name = k
            newrow = [name, dateFormat, editable, filterable,
                      hidden, horizontalAlignment, label,
                      numberFormat, prefix, sortable, suffix,
                      treatAsBoolean, verticalAlignment, wrapText]
        rows.append(newrow)
	
    # Build the header
    headers = ["name", "dateFormat", "editable", "filterable",
               "hidden", "horizontalAlignment", "label",
               "numberFormat", "prefix", "sortable", "suffix",
               "treatAsBoolean", "verticalAlignment", "wrapText"]
	
    data = system.dataset.toDataSet(headers, rows)
    event.source.columnAttributesData = data

onCellEdited Extension Function

I mention this section because even if you have 'Editable' selected in the Column Attributes Data, it does not really edit anything. You need to enable this function and uncomment the code. I have added the code below. You also might want to add a call to 'system.db.runPrepUpdate' to send the update back to a database.


import system
self.data = system.dataset.setValue(self.data, rowIndex, colIndex, newValue)

Recently I found out how to setup autologin for the Ignition Designer. This is the ability to start the Ignition Designer from a desktop shortcut and it automatically logs in and opens a project.

This is especially useful when developing an Ignition module that affects the designer because the designer will need to be restarted many times to test code changes.

Here's how to setup autologin for the Ignition Designer:

  1. Create a designer shortcut using a native client launcher.
  2. Edit the shortcut. Add the following parameters to the Target: -Djavaws.ignition.debug=true -Dautologin.username=admin -Dautologin.password=password -Dproject.name=MyProject.
    Replace the username, password and project name with your specific information.

    Here is an example of a complete Target in a shortcut:
    C:\Users\nick\Downloads\clientlauncher.exe scope=D windowmode=window gateway.addr=192.168.1.4:8088:8043 -Djavaws.ignition.debug=true -Dautologin.username=admin -Dautologin.password=password -Dproject.name=MyProject

That's it. The next time the shortcut is double-clicked the designer will automatically login and open the project.

Security must be kept in mind, as this setup makes it easy for people to log in to the designer as you if they get your Designer shortcut.

One of the great things about Ignition is its ability to web-deploy applications created with it. Notice that Ignition applications are not "web-based", they are "web-deployed". Web-deployed means an application is downloaded from a web server and started.

Web-based applications are web-deployed too — web-based applications and Ignition applications have that in common. Web-based applications are webpages downloaded from a web server and ran in a web browser. Ignition applications are downloaded from Ignition's web server and ran in a Java Virtual Machine. (In other words an Ignition application is downloaded and automatically started as a Java desktop application.)

Ignition does have a built-in web-based application for configuring many things in Ignition. But the applications/projects created with Ignition are typically Java desktop applications that are web-deployed.

Ignition has two separate web-deploying technologies. Both of them can be used to deploy Ignition applications.

In the beginning Ignition only used Java Web Start, which is a web-deploying technology controlled and owned by Oracle. Here is a good description of Java Web Start from www.java.com:

The Java Web Start software allows you to download and run Java applications from the web. The Java Web Start software:
  • Provides an easy, one-click activation of applications
  • Guarantees that you are always running the latest version of the application
  • Eliminates complicated installation or upgrade procedures

The problem with Java Web Start is that it is controlled by Oracle. In the past changes were made to Java Web Start that broke functionality in Ignition and in once case temporarily broke the ability to start projects on Linux.

Inductive Automation decided to implement their own web-deploying technology and did so. With this technology under their control they could make it stable, keep it from breaking Ignition, and add new functionality to it. This technology is called Native Client Launchers. It is called Native Client Launchers because separate client launcher executable programs exist for OS X, Windows and Linux.

One of the advantages of the client native launchers is that they can be used to create stable desktop shortcuts to projects or the Ignition designer. Shortcuts created with Java Web Start sometimes stop working.

Using a native client launcher is easy. Download the native client launcher executable for your operating system and then run it. The native client launcher will scan your network for Ignition servers. It will provide you with a list of Ignition servers it found. Once you choose an Ignition server you are provided with a list of projects that exist in that Ignition server. From there you can launch projects or the designer, and create shortcuts to projects and the Ignition designer.

The native client launchers are part of your Ignition server and are downloaded from your Ignition server. You can find and download them from the Ignition homepage. Here is a screenshot that shows where the native client launchers can be downloaded.

Ignition Native Client Launchers

More blog posts...