Problem
I was working on a template where I had to display steps in a sequence on the HMI. The number of steps could change from sequence to sequence and the template required a few parameters.
Figure 1 - Template Repeater
I decided to go with the template repeater component, but that component only provides you with two options regarding how the template is configured.
- I could have included a parameter called index and the repeater will replicate the template a specified number of times, incrementing the index parameter for each instance. This wouldn’t work for me because I needed to pass the path of UDT tag that is used by my template, not just an index.
- I could have created a static dataset and manually added the necessary parameters as columns, and then manually create a row for each step. Then I would have needed to bind the path of the tag to the correct parameter for each step. This turned out to be very tedious and time consuming. I decided that there had to be a better way.
There are also occasions where templates that would appear in the middle of the layout should not be visible for one reason or another. I would want to shift the items below the invisible item up so that any blank space would be eliminated.
Solution
To solve this problem, I needed to create the dataset dynamically with a python script, then bind the resulting dataset to the Template Parameter property of the template repeater. This is a step by step tutorial on how I solved this problem.
- Drop the template repeater component on the display as you normally would. There are plenty of videos and instructions on using the template repeater on the Inductive Automation website.
- Point the “Template Path” parameter to the template you want to repeat.
Figure 2 - Template Path
3. We are going to add a custom method to the template repeater component you placed on your display. Ensure the component is selected and click the “Scripting…” item in the toolbar.
Figure 3 - Open Script Window
4. When the Component Scripting window opens; do the following:
Figure 4 - Component Scripting Window
1) Double click the “Add Method” item on the right. This will create a new blank method where you can write your code.
2) Enter a name for the method. I called mine “buildDataset”
3) List the parameters required by your custom method separated by commas. In this example only one parameter is needed; “path”. The custom method automatically passes the component that contains the script and can be referenced using the keyword “self”. If your template requires more than one parameter, you would list them as “arg1, arg2, arg3” and so on.
4) Write your script. I wanted to create a variable number of items in the repeater depending on how many steps there were in the sequence. Fortunately, the sequencer I am using has a tag that indicates how many steps exist. I bound that tag to the template repeaters Repeat Count property, so I could use it in my script. Here is a run-down on how this script works:
-This script will need to return a DataSet typed variable and will require the system library, so we need to import “system”
import system
-Create an array to hold the data rows
rows = []
-Create the headers for the dataset. For my template, we need an “Index” and “path” parameters.
headers = [“Index”, “path”]
-Execute a for loop to iterate through the number steps in the sequencer. I accomplish this by using the Repeat Count property of the template repeater which I bound to a tag with the maximum step index. The Repeat Count parameter is referenced using the “self” keyword. The Ignition user manual lists all the parameters that can be used in these kinds of scripts.
for x in range (self.repeatCount):
-step 0 is not used in my sequencer, it is reserved as an empty step and I do not want to include it in my dataset. If there are any other conditions that you would not want to include the row in the dataset, this is where you would include them.
if x>0:
rows.append([x, path])
-Return the data as a dataset, so that it can bind to the “Template Parameters” property.
return system.dataset.toDataSet(headers, rows)
-Here is the whole script:
5) Click the ok button to close the Scripting window.
5. Click the binding button for the “Template Parameters” property of the template repeater. This will open the Property Binding window. You will want to bind using the “Expression” option.
Figure 5 - Template Parameters Binding
6. Bind the custom method to the “Template Parameters” property using the runScript function. The syntax is: runScript(self.nameOfScript, polling rate, parameters)
- self.nameOfScript: The custom method and the “Template Parameters” both belong to the instance in the display so the method can be referenced using the “self” keyword.
- Polling Rate parameter is used to set how frequently the dataset should be refreshed. In this example it does not need to be refreshed, so it will be set to 0.
- Finally, that last parameter is the list of parameters that will be passed to the custom method. This example is passing a custom display property that has the path of the steps tag.
- The final expression for this example is:
runScript(“self.buildDataset”, 0, {Root Container.Path})
7. The template repeater will now self-populate based on the tag indicated by the “path” parameter and the Repeat Count property. The Repeat Count property can be bound to a PLC tag or entered on the fly. This technique can be expanded to add field validation to parameters, or any number of advanced functionality.
About the Author:
Jamie has left Hallam-ICS to pursue other endeavors. If you have questions about this article or other Ignition questions, contact Burton Preston. Burton is a Gold Certified Ignition developer.
About Hallam-ICS:
Hallam-ICS is an engineering and automation company that designs MEP systems for facilities and plants, engineers control and automation solutions, and ensures safety and regulatory compliance through arc flash studies, commissioning, and validation. Our offices are located in Massachusetts, Connecticut, New York, Vermont and North Carolina and our projects take us world-wide.