Ignition User Manual
Ignition User Manual
Part I Introduction 18
1 Welcome to Ignition ................................................................................................................................... 18 2 Getting Help ................................................................................................................................... 18 3 Licensing, Activation, and Trial Mode ................................................................................................................................... 18 4 Quick................................................................................................................................... 20 Start
Installation (Window s) .......................................................................................................................................................... 20 Installation (Linux) .......................................................................................................................................................... 23 Installation (Debian Package Managem ent) .......................................................................................................................................................... 32 Upgrade (Window s) .......................................................................................................................................................... 34 Upgrade (Linux) .......................................................................................................................................................... 38 Gatew ay Hom.......................................................................................................................................................... 45 epage Connect to a PLC .......................................................................................................................................................... 46 Connect to a Database .......................................................................................................................................................... 46 Launch the Designer .......................................................................................................................................................... 47 Create som e .......................................................................................................................................................... 48 SQLTags Create a Window .......................................................................................................................................................... 49 Launch a Client .......................................................................................................................................................... 50 Create a Transaction Group .......................................................................................................................................................... 50 Uninstallation.......................................................................................................................................................... 50
Part II Overview
53
3 Modules ................................................................................................................................... 64
Overview .......................................................................................................................................................... 64 2012 Inductive Automation
3
OPC-UA Module .......................................................................................................................................................... 65 SQL Bridge Module .......................................................................................................................................................... 65 Vision Module .......................................................................................................................................................... 66 Reporting Module .......................................................................................................................................................... 66 Mobile Module .......................................................................................................................................................... 67 OPC-COM Module .......................................................................................................................................................... 67 Other Modules .......................................................................................................................................................... 67
4 Basic................................................................................................................................... 68 Usage
Gatew ay Navigation .......................................................................................................................................................... 68 Gatew ay Control Utility .......................................................................................................................................................... 69 Web Launching .......................................................................................................................................................... 71 Launching Clients .......................................................................................................................................................... 72 Launching the Designer .......................................................................................................................................................... 72
74
1 Gateway Configuration Overview ................................................................................................................................... 74 2 Logging into the configuration page ................................................................................................................................... 74 3 Basics ................................................................................................................................... 74
Basic Gatew ay Settings .......................................................................................................................................................... 74 Gatew ay Hom.......................................................................................................................................................... 76 epage Custom ization Setting the Port .......................................................................................................................................................... 76 Resetting the .......................................................................................................................................................... 76 trial period Activation .......................................................................................................................................................... 76 Online Activation ......................................................................................................................................................... 76 Offline Activation ......................................................................................................................................................... 77 Unactivation ......................................................................................................................................................... 77 Updating the License ......................................................................................................................................................... 77 Gatew ay Console .......................................................................................................................................................... 77
4 Projects ................................................................................................................................... 78
What is a Project? .......................................................................................................................................................... 78 Project Managem ent .......................................................................................................................................................... 78 Project Versioning .......................................................................................................................................................... 79 Im porting and Exporting Projects .......................................................................................................................................................... 80
5 Modules ................................................................................................................................... 80
Module Managem ent .......................................................................................................................................................... 80
6 Databases ................................................................................................................................... 81
Databases Overview .......................................................................................................................................................... 81 Supported Databases .......................................................................................................................................................... 82 Database Connections .......................................................................................................................................................... 83 Creating and Editing Connections ......................................................................................................................................................... 83 Monitoring ......................................................................................................................................................... 83 Connection Status Connecting to Microsoft SQL Server ......................................................................................................................................................... 84 Connecting to MySQL ......................................................................................................................................................... 90 Database Drivers .......................................................................................................................................................... 91 What is JDBC? ......................................................................................................................................................... 91 Can I connect using ODBC? ......................................................................................................................................................... 91 Adding a JDBC driver ......................................................................................................................................................... 92 Database Translators ......................................................................................................................................................... 92
Store and Forw ard for Reliability .......................................................................................................................................................... 95 Store and Forw ard for high-speed buffering .......................................................................................................................................................... 96 Engine Status.......................................................................................................................................................... 97 Monitoring Data Quarantining .......................................................................................................................................................... 97
8 OPC ................................................................................................................................... 98
What is OPC? .......................................................................................................................................................... 98 OPC Connections .......................................................................................................................................................... 99 Connecting to OPC-UA ......................................................................................................................................................... 99 Connecting to OPC Classic (COM) ......................................................................................................................................................... 100 Troubleshooting OPC-COM Connections ......................................................................................................................................................... 102 OPC Quick Client .......................................................................................................................................................... 104 Ignition OPC-UA Server .......................................................................................................................................................... 105 OPC-UA Server Settings ......................................................................................................................................................... 105 Adding a ......................................................................................................................................................... 105 New Device Verifying ......................................................................................................................................................... 105 Device Connectivity Drivers ......................................................................................................................................................... 106 Allen Bradley Drivers ......................................................................................................................................... 106 ControlLogix 5500 ................................................................................................................................... 106 MicroLogix 1100/1400 ................................................................................................................................... 107 PLC-5 ................................................................................................................................... 107 SLC 505 ................................................................................................................................... 108 Allen Bradley Connection Paths Explained ................................................................................................................................... 109 Simulator Drivers ......................................................................................................................................... 114 Generic Simulator ................................................................................................................................... 114 Allen Bradley SLC Simulator ................................................................................................................................... 116 Modbus Drivers......................................................................................................................................... 116 Modbus Ethernet ................................................................................................................................... 116 Overview ................................................................................................................................... 116 Device Configuration ................................................................................................................................... 116 Addressing ................................................................................................................................... 117 UDP and TCP Drivers ......................................................................................................................................... 124 UDP and TCP ................................................................................................................................... 124 Siemens Drivers ......................................................................................................................................... 126 Overview ................................................................................................................................... 126 Addressing ................................................................................................................................... 126
5
AD/Database Authentication Profile ......................................................................................................................................................... 140 Managing Users, Passw ords, and Roles .......................................................................................................................................................... 140 Enabling SSL.......................................................................................................................................................... 141 Encryption
153
7
Custom Palettes......................................................................................................................................... 206 SQLTags Drag-n-Drop ......................................................................................................................................... 206 Selecting ......................................................................................................................................................... 207 Components Manipulating Components ......................................................................................................................................................... 207 Keyboard......................................................................................................................................................... 209 Shortcuts Properties ......................................................................................................................................................... 210 The Property Editor ......................................................................................................................................................... 210 Fill and Stroke ......................................................................................................................................................... 211 Geometry......................................................................................................................................................... 213 and Paths Data Types ......................................................................................................................................................... 216 Component Customizers ......................................................................................................................................................... 217 Custom Properties ......................................................................................................................................................... 217 Component Styles ......................................................................................................................................................... 218 Quality Overlays ......................................................................................................................................................... 218 Touchscreen Support ......................................................................................................................................................... 219 Component Layout ......................................................................................................................................................... 220 Shape Components ......................................................................................................................................................... 222 Grouping ......................................................................................................................................................... 224 Using Symbol Factory ......................................................................................................................................................... 224 Tem plates .......................................................................................................................................................... 225 Introduction ......................................................................................................................................................... 225 Using Templates ......................................................................................................................................................... 226 Template ......................................................................................................................................................... 226 Parameters Property Binding .......................................................................................................................................................... 228 Overview......................................................................................................................................................... 228 Polling Options ......................................................................................................................................................... 229 Bidirectional Bindings ......................................................................................................................................................... 229 Indirect Bindings ......................................................................................................................................................... 230 Binding Types ......................................................................................................................................................... 230 Tag Binding ......................................................................................................................................... 230 Indirect Tag Binding ......................................................................................................................................... 231 SQLTags Historian Binding ......................................................................................................................................... 231 Property Binding ......................................................................................................................................... 232 Expression Binding ......................................................................................................................................... 232 DB Brow se Binding ......................................................................................................................................... 233 SQL Query Binding ......................................................................................................................................... 233 Cell Update Binding ......................................................................................................................................... 234 Function Binding ......................................................................................................................................... 234 Event Handlers .......................................................................................................................................................... 234 Overview......................................................................................................................................................... 234 The 'event' object ......................................................................................................................................................... 235 Event Types ......................................................................................................................................................... 236 Script Builders ......................................................................................................................................................... 242 Security .......................................................................................................................................................... 243 Role-based access ......................................................................................................................................................... 243 Tag Security ......................................................................................................................................................... 243 Component Security ......................................................................................................................................................... 244 Securing ......................................................................................................................................................... 244 event handlers
Getting Started ......................................................................................................................................................... 255 Step by Step Quick Start ......................................................................................................................................................... 255 Tutorials .......................................................................................................................................................... 266 Tutorial #1 - Table Example ......................................................................................................................................................... 266 Overview ......................................................................................................................................... 266 Background ......................................................................................................................................... 268 Getting Started ......................................................................................................................................... 269 Basic Layout ......................................................................................................................................... 270 Substitution Keys and Tables ......................................................................................................................................... 272 Row Versioning ......................................................................................................................................... 276 Tutorial #2 - Adding Graphs ......................................................................................................................................................... 280 Overview ......................................................................................................................................... 280 Background ......................................................................................................................................... 281 Getting Started ......................................................................................................................................... 282 Basic Layout ......................................................................................................................................... 283 More changes ......................................................................................................................................... 286 Graphs ......................................................................................................................................... 288 Tutorial #3 - PDF Example ......................................................................................................................................................... 292 Overview ......................................................................................................................................... 292 Background ......................................................................................................................................... 293 Creating the report ......................................................................................................................................... 294 Com ponents .......................................................................................................................................................... 296 Ignition Components ......................................................................................................................................................... 296 Row Selector ......................................................................................................................................... 296 Column Selector ......................................................................................................................................... 300 Report View er ......................................................................................................................................... 303 File Explorer ......................................................................................................................................... 307 PDF View er ......................................................................................................................................... 309 ReportView er Components ......................................................................................................................................................... 311 Basic Draw ing Tools ......................................................................................................................................... 311 Crosstab ......................................................................................................................................... 314 Graph ......................................................................................................................................... 315 Line Graph ......................................................................................................................................... 319 Images ......................................................................................................................................... 322 Labels ......................................................................................................................................... 325 Barcode ......................................................................................................................................... 327 Simple Table ......................................................................................................................................... 328 Tables ......................................................................................................................................... 329 Overview ................................................................................................................................... 329 Basics ................................................................................................................................... 330 Table Row s ................................................................................................................................... 336 Sorting and Filtering ................................................................................................................................... 338 Row Versioning ................................................................................................................................... 340 Grouping ................................................................................................................................... 342 Table Groups ................................................................................................................................... 345 Concepts .......................................................................................................................................................... 346 User Interface ......................................................................................................................................................... 346 Selection and Alignment ......................................................................................................................................... 346 Object Layout ......................................................................................................................................... 348 Text Editing ......................................................................................................................................... 350 Report Designer ......................................................................................................................................... 351 Menu ................................................................................................................................... 352 Toolbar ................................................................................................................................... 355 Attributes Panel ................................................................................................................................... 356 2012 Inductive Automation
9
Inspector Panel ................................................................................................................................... 361 Basic ......................................................................................................................................................... 373 Dynamic Properties ......................................................................................................................................... 373 Substitution Keys ......................................................................................................................................... 375 Expressions, operators, and functions ......................................................................................................................................... 378 Saving Reports ......................................................................................................................................... 380 PDF Reports ......................................................................................................................................... 382 Date Formatting......................................................................................................................................... 386 Paterns Label Sw ich Versions, Graph ......................................................................................................................................... 391 Dataset Key - Table or Graph ......................................................................................................................................... 395 Advanced ......................................................................................................................................................... 398 BLOB images ......................................................................................................................................... 398 Image Placeholders ......................................................................................................................................... 402 Property Expressions ......................................................................................................................................... 404
Part V Scripting
409
442
1 Using HTML in Ignition ................................................................................................................................... 442 2 Kepware OPC-UA Connection Guide ................................................................................................................................... 444 3 Troubleshooting Gateway Scripts ................................................................................................................................... 448 4 Changing Memory Allocation for Ignition ................................................................................................................................... 450 5 Mapping a Network Drive ................................................................................................................................... 452
2012 Inductive Automation
6 Creating an Editable Table in Ignition ................................................................................................................................... 453 7 Create Basic Navigation Windows ................................................................................................................................... 456 8 Indirect Bindings and Window Parameters ................................................................................................................................... 460 9 Database Performance Tips ................................................................................................................................... 463 10 Accessing Ignition Over a WAN ................................................................................................................................... 465
468
1 Licensing and Activation ................................................................................................................................... 468 2 Making Backups ................................................................................................................................... 468 3 Restoring from a Backup ................................................................................................................................... 468 4 Transferring Servers ................................................................................................................................... 468 5 Gateway Homepage Customization ................................................................................................................................... 469 6 Gateway Web Security ................................................................................................................................... 469 7 Gateway Monitoring ................................................................................................................................... 469 8 Installing a Genuine SSL Certificate ................................................................................................................................... 471
474
11
Meter .......................................................................................................................................................... 561 Com pass .......................................................................................................................................................... 566 Therm om eter .......................................................................................................................................................... 569 Docum ent View er .......................................................................................................................................................... 572 IP Cam era View er .......................................................................................................................................................... 574
7 Misc................................................................................................................................... 670
Container .......................................................................................................................................................... 670 Paintable Canvas .......................................................................................................................................................... 673 Line .......................................................................................................................................................... 675 Pipe Segm ent .......................................................................................................................................................... 677 Pipe Joint .......................................................................................................................................................... 679 Sound Player .......................................................................................................................................................... 681 Tim er .......................................................................................................................................................... 682 Signal Generator .......................................................................................................................................................... 684
698
13
repeat .......................................................................................................................................................... 713 replace .......................................................................................................................................................... 714 right .......................................................................................................................................................... 714 split .......................................................................................................................................................... 714 stringForm at .......................................................................................................................................................... 715 substring .......................................................................................................................................................... 715 trim .......................................................................................................................................................... 715 upper .......................................................................................................................................................... 716
727
system .db.com m itTransaction .......................................................................................................................................................... 742 system .db.createSProcCall .......................................................................................................................................................... 743 system .db.dateForm at .......................................................................................................................................................... 745 system .db.execSProcCall .......................................................................................................................................................... 745 system .db.getConnectionInfo .......................................................................................................................................................... 746 system .db.getConnections .......................................................................................................................................................... 746 system .db.refresh .......................................................................................................................................................... 746 system .db.rollbackTransaction .......................................................................................................................................................... 747 system .db.runPrepQuery .......................................................................................................................................................... 747 system .db.runPrepUpdate .......................................................................................................................................................... 748 system .db.runQuery .......................................................................................................................................................... 750 system .db.runScalarQuery .......................................................................................................................................................... 752 system .db.runUpdateQuery .......................................................................................................................................................... 752
15
system .nav.goHom e .......................................................................................................................................................... 776 system .nav.openWindow .......................................................................................................................................................... 777 system .nav.openWindow Instance .......................................................................................................................................................... 777 system .nav.sw apTo .......................................................................................................................................................... 778 system .nav.sw apWindow .......................................................................................................................................................... 779
system .tag.w riteAll .......................................................................................................................................................... 803 system .tag.w riteSynchronous .......................................................................................................................................................... 804
Index
817
Introduction
Part I
Introduction
18
1
1.1
Introduction
Welcome to Ignition
Welcome to Ignition by Inductive Automation, the next generation of accessible, scalable, and datacentric HMI/SCADA/MES software. Ignition was designed from the ground up to be approachable and easy to get started with, but highly flexible and capable of scaling up to the largest projects. This guide aims to introduce you to Ignition and its architecture, get you started quickly, and then provide all of the reference resources you should need as you become more proficient with the system. We recommend proceeding through this manual roughly in the order that it's laid out. In particular, we recommend starting with the following topics: What is Ignition? Architecture Overview Quick Start
1.2
Getting Help
If you get stuck designing a system in Ignition, don't worry! There are lots of ways to get help.
Online Forum
One of the most effective ways to get help is our active user forum. The forum is always available, and is actively patrolled by Inductive Automation staff and many knowledgeable users. Chances are you will find your question already answered in an existing post, but if not you can be assured that yours will receive a quick reply. The forum can be found under the Support section of the Inductive Automation website.
Phone Support
You can reach us during business hours 8am-5pm PST at 1-800-266-7798. Support charges may apply. 24-hour support is also available, at an additional fee.
E-Mail Support
E-mail support is available at support@inductiveautomation.com
1.3
Introduction
19
Ignition can be used for 2-hours at a time, with no other restrictions. At the end of the demo period, the system will stop most functions. For example, transaction groups will stop logging, and clients will show a demo screen. By logging into the gateway, you may re-start the demo period, and enable another 2 hours of execution. The demo period may be restarted any number of times. All portions of the gateway (and therefore, all modules) share the same clock and will timeout simultaneously.
License Reloading
If you purchase additional modules, they will be added onto your existing CD-Key. To update your license, you must reload it, which can be performed from the same location in the gateway as activation.
Introduction
20
Transferring Licenses
If you would like to transfer your license from one machine to another, simply unactivate the currently licensed machine. This process is similar to the licensing procedure, but in reverse. If the licensed Ignition server has internet access, the unactivation will occur immediately, and the license will again be available for activation. If you do not have internet access, an unactivation request file will be generated, and the license will not be allowed to activate until the file is loaded into the Inductive Automation website, or emailed to support.
Emergency Activation
Licenses may only be activated one time. After that, if not properly unactivated, you must call Inductive Automation in order add another license grant to your cd key. However, in cases where activation is not possible, the system will be activated in emergency mode. In this mode, a temporary activation is granted that will run for 7 days, in order to provide you with enough time to contact us. The presence of an emergency activation will be displayed when logged into the gateway configuration, but will not otherwise affect clients or functionality.
1.4
1.4.1
Quick Start
Installation (Windows)
Ignition by Inductive Automation is really easy to install. To get started, simply download the Windows executable installer from our website, and double-click on it. Be sure to download the 32-bit installer for a 32-bit Windows installation, and the 64-bit installer for a 64-bit Windows installation. You can run a 32bit installer in a 64-bit Windows system, but the 32-bit installation has memory restrictions as compared to the 64-bit installation. After the installer starts, if you agree to the licensing terms, continue on to the next step.
The first option in the installer is to choose where Ignition is installed on your hard drive. The default (your Program Files directory) is usually a good choice. After you have selected your installation directory, click on Next.
Introduction
21
The next option in the installer is to choose the installation mode. For most scenarios, the Typical mode will install everything that you need to get started. If you would like to add an optional module, such as the OEE Downtime module, select the Custom mode. You can also use the Custom mode to control which modules get installed. When you have made your selection, click on Next.
If you have selected Custom Mode, you will be presented with the screen above. To view a brief description of the module, click on the module name. Checking the checkbox next to a module will install the module as part of the Ignition installation. Clearing the checkbox next to a module will prevent the module from being installed. When you have made your selections, click on Next.
Introduction
22
Ready to Install
Ignition is ready to be installed. At this point, you may click the Back button to change your selections. Click the Next button to finish the installation. Once Ignition starts installing, it may take a few minutes to finish. Ignition installs itself as a Window Service, so it will start automatically when your computer starts up.
When the installation is complete, press the "Finish" button. If you have chosen to start Ignition now, you will see a splash screen informing you that the Ignition service is starting.
Introduction
23
Once the Ignition Gateway starts up, your web browser will open and bring you to the Gateway Homepage.
Automated installation
Ignition can be silently installed from a command shell without showing any user prompts. This allows you to automate Ignition installation across different machines using scripts. Keep in mind that the installer cannot automatically start the Gateway after a silent installation. Use the net start ignition command as shown below. Command line example:
Ignition-7.x.x-windows-x64-installer.exe --mode unattended --prefix "C:\some folder" --unattendedmodeui none net start ignition
Flags: -- mode unattended (ensures that no prompts appear during installation) -- prefix "C:\some folder" (optional flag; if a value is set, then Ignition will be installed in the specified folder, otherwise Ignition will be installed in a default location under C:\Program Files) -- unattendedmodeui none | minimal (the 'none' flag will not display any sort of graphic during installation; the 'minimal' flag will display a small progress bar and nothing else)
1.4.2
Installation (Linux)
Ignition comes with Linux executable installers that can be run under any Linux distribution. The installers are capable of running in graphical mode or in command line mode, allowing you to install Ignition on a headless Linux server. To install under a Linux OS, it is assumed that you are comfortable operating a shell. The installer will install files in the following locations: /usr/local/bin/ignition (unless a different installation directory was used)- contains binaries, startup scripts and the uninstall executable /var/lib/ignition/data - contains application-generated files, temporary files and the internal database /var/lib/ignition/user-lib - contains modules and JDBC jars /var/log/ignition - contains the wrapper.log and other log files /etc/ignition - contains configuration files. Symbolic links to these files are created in /var/lib/ignition/ data. The first step is to download the Ignition Linux executable installer from our website. Be sure to download the 32-bit installer for a 32-bit Linux installation, and the 64-bit installer for a 64-bit Linux installation. A 32-bit installer will not launch in a 64-bit system and vice versa. After downloading the
Introduction
24
installer, follow the directions below to install Ignition as a Linux service. You'll also find these directions in the distribution file's README, available in /usr/local/bin/ignition after installation. You need to be able to run as ROOT (prefix everything with 'sudo', run 'sudo su', or login as root user). 1. Install Java 6 (if not already installed) Non-Ubuntu users: you should install Java using your package management utility (such as yum for Fedora-based systems). If you cannot install Java using a package management utility, you can unzip the Java executables to a folder and give the location to that folder during Ignition installation. Note that when you unzip the Java executables to a folder, you will also need to add the executables to the system PATH. Ubuntu users: at the command line, run sudo apt-get install sun-java6-jre If apt returns an error that sun-java6-jre is not available, then you must follow these steps to add the java 6 repository: Graphical mode: At the command line, start the Software Sources tool: sudo software-properties-gtk Within the tool, click on the Other Software tab and click on the Add button. Add this to the APT line textbox: deb http://archive.canonical.com/ubuntu maverick partner Click the Add Source button. Then click on Close. When prompted, allow updated lists to reload. From a command shell, run sudo apt-get install sun-java6-jre Command line mode: Copy /etc/apt/sources.list to /etc/apt/sources.list.bak Edit /etc/apt/sources.list and add this line: deb http://archive.canonical.com/ubuntu maverick partner To update the download list, run sudo apt-get update Finally, run: sudo apt-get install sun-java6-jre 2. Open a command shell and navigate to the installer executable. On the command line, run: chmod +x ignition_X.X.X-installer.run 3. Start the installer executable If you are running the installer in a shell in a graphical environment, the graphical installer will open automatically. If you are running the installer in a headless Linux installation, or through a SSH shell, the text installer will open automatically. Want to run the text installer in a graphical environment?
2012 Inductive Automation
Introduction
25
Add --mode text to the end of the command below. On the command line, run: ./ignition_X.X.X-installer.run After the installer starts, if you agree to the licensing terms, continue on to the next step.
This section allows you to change the installation location. Use the default value of /user/local/bin/ ignition unless you have a need to use a different folder. After you have selected your installation directory, continue on to the next step.
Introduction
26
In order to set the permissions on the folders created by the installer, the Linux installer requires a user name. This user will be able to start and stop Ignition and run the Gateway Control Utility and command line interfaces. The binaries in the installation folder are still owned by root and cannot be modified without root access. The selected user must already exist on the system before starting the installer. For Ubuntu installations, the user that invoked sudo is used by default. For other Linux installations, this field is initially blank. After you have entered the user, continue on to the next step.
Introduction
27
Normally, the installer is capable of auto-detecting a Java 6 installation that has been installed thru APT or some other Linux package management tool. In these cases, the installer will use that Java installation and skip past this step. However, if you have installed Java by extracting the Java binaries to a folder and adding them to the system PATH, the installer will be unable to find the Java binaries. In this case, you must provide the installer with a full path to the Java executable.
Introduction
28
The next option in the installer is to choose the installation mode. For most scenarios, the Typical mode will install everything that you need to get started. If you would like to add an optional module, such as the OEE Downtime module, select the Custom mode. You can also use the Custom mode to control which modules get installed. When you have made your selection, continue on to the next step.
Introduction
29
If you have selected Custom Mode, you will be presented with the screen above. Graphical mode- to view a brief description of the module, click on the module name. Checking the checkbox next to a module will install the module as part of the Ignition installation. Clearing the checkbox next to a module will prevent the module from being installed. Text mode- you will be presented with a list of all the modules, one at a time. Type "y" to install the module, and type "n" to prevent the module from being installed. When you have made your selections, continue on to the next step.
Introduction
30
Ignition is ready to be installed. At this point, you may click the Back button (graphical mode) to change your selections. For the text mode, you can only abort the installation at this point by typing "n". Click the Next button (graphical mode) or type "y" (text mode) to finish the installation.
Introduction
31
When the installation is complete, press the "Finish" button (graphical mode) or type "y" to start Ignition or "n" to simply exit (text mode). If you have chosen to start Ignition now, then Ignition will be started as a background process. Use a web browser to navigate to http://localhost:8088 to confirm that your Gateway is running. 4. Stopping and starting Ignition After installation, you can start and stop Ignition with the following commands: /etc/init.d/ignition start /etc/init.d/ignition stop
Introduction
32
5. Ignition as a service When installing under Ubuntu, Ignition will start automatically whenever the computer reboots. If you wish to stop this behaviour then you need to use the update-rc.d tool to remove the service (uninstalling Ignition also removes the service). /etc/init.d/ignition stop update-rc.d -f ignition remove rm /etc/init.d/ignition When installing under other Linux distributions, you will need to use that distribution's method to automatically start a program after reboot. For example, this command will autostart Ignition installed in a Fedora 15 system (run as root user): chkconfig --level 2345 ignition on 6. Setting the system PATH For Ubuntu installations, the installation directory is automatically appended to the system PATH. This allows you to start programs like the Gateway Control Utility from the command line without specifying a complete path to the installation directory. Note that after installation, you need to close and reopen the command shell for the PATH change to take effect. For other Linux installations, you will need to manually add /usr/local/bin/ignition (or your installation directory) to any script that can set the system PATH (such as .profile or .bashrc).
Automated installation
Ignition can be silently installed from a command shell without showing any user prompts. This allows you to automate Ignition installation across different machines using scripts. Keep in mind that the installer cannot automatically start the Gateway after a silent installation. Use the /etc/init.d/ ignition start command as shown below. Command line example:
sudo ./ignition-7.x.x-linux-x64-installer.run --mode unattended --prefix /somefolder/ bin/ignition --unattendedmodeui none /etc/init.d/ignition start
Flags: -- mode unattended (ensures that no prompts appear during installation) -- prefix /somefolder/bin/ignition (optional flag; if a value is set, then Ignition will be installed in the specified folder, otherwise Ignition will be installed in /usr/local/bin/ignition by default) -- serviceuser username (allows a Linux system user to be installed (i.e., a user that cannot log in to the OS)) -- unattendedmodeui none | minimal (the 'none' flag will not display any sort of graphic during installation; the 'minimal' flag will display a small progress bar and nothing else, but only if you are working in a graphical system)
1.4.3
Introduction
33
to the Internet so that the installer and updates can be installed automatically. If you are installing Ignition to a non Internet-connected machine, use the downloadable Linux installers instead (see the Installation (Linux) section for more details). The Ignition Debian installers are dependent on an existing Java 6 installation through APT. Only the Sun Java 6 Java Runtime Environment (JRE) is officially supported by Inductive Automation, although Ignition will likely run with any Java 6 JRE installed on the Linux system. See the first part of the Installation (Linux) section for instructions on how to install Java using APT. The installer will install files in the following locations: /usr/local/bin/ignition - contains binaries and startup scripts /var/lib/ignition/data - contains application-generated files, temporary files and the internal database /var/lib/ignition/user-lib - contains modules and JDBC jars /var/log/ignition - contains the wrapper.log and other log files /etc/ignition - contains configuration files. Symbolic links to these files are created in /var/lib/ignition/ data. When installing Ignition, you can choose whether to use the graphical package management tools, or install completely from the command line. With either option, Linux will automatically download the correct 32-bit or 64-bit installer depending on your installed system architecture. Note that the instructions below were written for an Ubuntu Linux system, but other Debian systems should still contain the same tools (although they may be under different menus). Graphical installation: 1. Download the Inductive Automation public key file from http://archive.inductiveautomation.com/ia. public.key or run wget http://archive.inductiveautomation.com/ia.public.key on the command line. 2. Within Ubuntu, navigate to System -> Administration -> Synaptic Package Manager. 3. Within Synaptic Package Manager, navigate to Settings -> Repositories. 4. Navigate to the Authentication tab. Click on "Import Key File" and select the downloaded ia.public.key file. 5. Navigate to the Other Software tab and click on the "Add" button. Add the following text to the textbox: deb http://archive.inductiveautomation.com/apt ignition non-free 6. If you would like to add the Ignition beta repository, click the "Add" button again and add this text to the textbox: deb http://archive.inductiveautomation.com/apt ignition-beta non-free 7. Be sure to uncheck the checkboxes next to repositories ending with "Source Code", as Ignition does not supply source code with the repositories. 8. Click the Close button. Within Synaptic Package Manager, click the Reload button. You can now type in "ignition" into the Quick Filter box and see the latest available Ignition repositories. 9. Right-click on the Ignition repository that you would like to install, and select "Mark for Installation".
Introduction
34
Then click the Apply button at the top. Ignition will be automatically downloaded and started. Navigate to http://localhost:8088 to log into the Ignition gateway.
Command line installation: 1. Run wget http://archive.inductiveautomation.com/ia.public.key 2. Run sudo apt-key add ia.public.key 3. Copy /etc/apt/sources.list to /etc/apt/sources.list.bak 4. Edit /etc/apt/sources.list and add these lines (the ignition-beta line is optional): deb http://archive.inductiveautomation.com/apt ignition non-free deb http://archive.inductiveautomation.com/apt ignition-beta non-free 5. Run sudo apt-get update to update the download list within the APT utility. 6. Run sudo apt-get install ignition to install the latest stable Ignition version or run sudo apt-get install ignition-beta to install the latest beta Ignition version. If you would like to run the Gateway Command Utility or gwcmd right after installation, open a command shell in your home folder and run source .profile. This will force your command shell to reload the . profile script, which has been updated with a path to the Ignition executable during installation. Upgrades During an upgrade, the Ignition internal database, configuration files, and any custom installed modules will not be changed. Whenever a new version of Ignition is released, the online Debian repositories also get updated with the latest version. Your Linux environment will list Ignition in the list of package upgrades when a new version is available. As with the installation, you can choose whether to upgrade using a graphical environment or using the command line. Graphical Upgrade: Ignition will appear as an entry under your system's Update Manager under the "Other Updates" section. If you choose to install updates using the Update Manager, Ignition will be upgraded at the same time as other packages. You can also manually upgrade Ignition using Symantic Package Manager. Locate "ignition" or "ignition-beta" in the list using the Quick Filter. Ignition can also be found in the World Wide Web section. Right-click and select "Mark for Upgrade". Then click "Apply" at the top. The latest version of Ignition will be downloaded and installed. Command line upgrade: Run sudo apt-get upgrade to upgrade all installed packages, including Ignition. To only upgrade Ignition, run sudo apt-get install ignition or sudo apt-get install ignition-beta. The APT utility will recognize that Ignition is already installed, and will perform the upgrade.
1.4.4
Upgrade (Windows)
The Ignition upgrade process is designed to be as painless as possible. Before performing any upgrade, you should back up your gateway (see Backups). The Ignition installer also doubles as an upgrader. Simply download the Windows executable installer from our website, and double-click on it. Be sure to download the 32-bit installer for a 32-bit Windows installation, and the 64-bit installer for a 64-bit Windows installation. If you attempt to upgrade a 32-bit installation with a 64-bit installer, or vice versa, the installer will throw an error. After double-clicking on the executable installer, you will be presented with this screen:
Introduction
35
Click Yes to start the upgrade process. The first stage of this process will be to stop the Ignition Windows service on the machine. If you abort the upgrade process before it completes, the installer will attempt to restart your old Ignition Windows service. After accepting the license agreement, you will be presented with the Upgrade Mode screen.
For most scenarios, choosing to just upgrade currently installed modules will be sufficient, as it will upgrade the Ignition base installation and the existing modules. Choosing "Yes" will take you to the module selection screen on the next page, where you can add a module that was not part of the original installation or uninstall a currently installed module. When you have made your selection, click on Next.
Introduction
36
If you have chose to select which modules to add or remove on the previous screen, you will be presented with the screen above. To view a brief description of the module, click on the module name. Checking the checkbox next to a module will install the module as part of the upgrade. Clearing the checkbox next to a module will uninstall the module during the upgrade. When you have made your selections, click on Next.
Ready to Install
Ignition is ready to be upgraded. At this point, you may click the Back button to change your selections. Click the Next button to finish the upgrade. Once the upgrade process starts, it may take a few minutes to finish. At the end of the upgrade process, you will see the screen below.
Introduction
37
Press the "Finish" button to close the process. If you have chosen to start Ignition now, you will see a splash screen informing you that the Ignition service is starting.
Once the Ignition Gateway starts up, your web browser will open and bring you to the Gateway Homepage.
Automated upgrade
Ignition can be silently upgraded from a command shell without showing any user prompts. Keep in mind that you should make a Gateway backup before performing any type of upgrade. Also, the installer cannot automatically start the Gateway after a silent upgrade. Use the net start ignition command as shown below. Command line example:
gwcmd -b C:\backups\mybackup.gwbk Ignition-7.x.x-windows-x64-installer.exe --mode unattended --unattendedmodeui none -autoupgrade true net start ignition
Flags: -- mode unattended (ensures that no prompts appear during installation) -- unattendedmodeui none | minimal (the 'none' flag will not display any sort of graphic during installation; the 'minimal' flag will display a small progress bar and nothing else)
2012 Inductive Automation
Introduction
38
1.4.5
Upgrade (Linux)
Unlike some Linux operations, the Ignition Linux upgrade process is designed to be as painless as possible. Note that while Ignition is currently optimized for Ubuntu Linux, the upgrade process will work for any Linux distribution. Before performing any upgrade, you should back up your gateway (see Backups). The Ignition installer also doubles as an upgrader. Simply download the Linux executable installer from our website, and double-click on it. Be sure to download the 32-bit installer for a 32-bit Linux installation, and the 64-bit installer for a 64-bit Linux installation. A 32-bit installer will not launch in a 64-bit system and vice versa. You need to be able to run as ROOT (prefix everything with 'sudo', run 'sudo su', or login as root user) to perform the upgrade. After downloading the installer, open a command shell and navigate to the installer executable. Run: chmod 744 * Then run: ./ignition_X.X.X-installer.run If you are running the installer in a shell in a graphical environment, the graphical installer will open automatically. If you are running the installer in a headless Linux installation, or through a SSH shell, the text installer will open automatically. Want to run the text installer in a graphical environment? Add -mode text to the end of the command above. After the installer starts, if you agree to the licensing terms, continue on to the next step.
Introduction
39
Linux does not have the concept of a central registry like Windows systems do. Therefore, you must provide the location of the existing Ignition installation. By default, this value is /usr/local/bin/ignition, unless you have installed Ignition in another location. After you have selected your installation directory, continue on to the next step.
Introduction
40
If the upgrader is able to locate Ignition in the specified folder, you will presented with the screen above. Click Yes or type "y" to continue. .
Introduction
41
For most scenarios, choosing to just upgrade currently installed modules will be sufficient, as it will upgrade the Ignition base installation and the existing modules. Choosing "Yes" will take you to the module selection screen on the next page, where you can add a module that was not part of the original installation or uninstall a currently installed module. When you have made your selection, continue to the next section.
Introduction
42
If you have chose to select which modules to add or remove on the previous screen, you will be presented with the screen above. Graphical mode-to view a brief description of the module, click on the module name. Checking the checkbox next to a module will install the module as part of the upgrade. Clearing the checkbox next to a module will uninstall the module during the upgrade. Text mode- you will be presented with a list of all the modules, one at a time. Type "y" to install or upgrade the module, and type "n" to uninstall the module. When you have made your selections, continue on to the next step.
Introduction
43
Ignition is ready to be upgraded. At this point, you may click the Back button (graphical mode) to change your selections. For the text mode, you can only abort the upgrade at this point by typing "n". Click the Next button (graphical mode) or type "y" (text mode) to finish the upgrade.
Introduction
44
When the upgrade is complete, press the "Finish" button (graphical mode) or type "y" to start Ignition or "n" to simply exit (text mode). If you have chosen to start Ignition now, then Ignition will be started as a background process. Use a web browser to navigate to http://localhost:8088 to confirm that your Gateway is running. For instructions on how to stop or start Ignition, see the Installation (Linux) section.
Automated upgrade
Ignition can be silently upgraded from a command shell without showing any user prompts. Keep in mind that you should make a Gateway backup before performing any type of upgrade. Also, the installer cannot automatically start the Gateway after a silent upgrade. Use the /etc/init.d/ignition start command as shown below. Command line example:
gwcmd -b /var/backups/mybackup.gwbk sudo ./ignition-7.x.x-linux-x64-installer.run --mode unattended --unattendedmodeui none --autoupgrade true /etc/init.d/ignition start
Flags: -- mode unattended (ensures that no prompts appear during installation) -- unattendedmodeui none | minimal (the 'none' flag will not display any sort of graphic during installation; the 'minimal' flag will display a small progress bar and nothing else, but only if you are working in a graphical system) -- autoupgrade true (runs the installer in upgrade mode)
Introduction
45
1.4.6
Gateway Homepage
The Ignition Gateway is a web server. When it is running, you access it through a web browser. For example, if you are logged into the computer that you installed Ignition on, open up a web browser and go to the address: http://localhost:8088 and it will bring up the Gateway Homepage, pictured here.
The first time you go to the Gateway Homepage, It will show you 5 common steps to help you get started. You can follow along with these steps and/or with this quick-start guide - they follow the same basic workflow.
Introduction
46
The first step is to log into the Gateway's Configuration Section. To do this, click on the large "Configure" button in the top navigation bar. You will be asked to log in - the default username/password is: admin / password Once you are in the configuration section you can navigate to the various configuration areas using the menu tree on the left-hand side of the page. Learn more about using Gateway's web interface in the Gateway Navigation section.
1.4.7
Connect to a PLC
Now that we've installed Ignition and have logged into the Configuration section of the web interface, lets install a device. A device is a named connection to an industrial device like a PLC. There are also "simulator" devices that you can add that will mimic a connection to a real device in case you don't have one handy. This step is optional! You can come back to it later if you'd like. The next steps will be more interesting if you add a device now, however. These devices are part of the integrated Ignition OPC-UA server module. If you have a classic OPC server (OPC-DA 2.0 or 3.0) that you'd like to connect to, see the OPC-COM Module.
Adding a Device
To add a device, use the left-hand side configuration menu to go to the OPC-UA > Devices section. Once at the Devices page, click on the Add a Device... link at the bottom of the table.
Choose a Driver
You will be given the option to pick the driver for the device you want. If you don't have a device that matches one of the available drivers, you can add a simulator device so you have some data to play with.
1.4.8
Connect to a Database
Many of the advanced features of Ignition, such as the Transaction Groups and SQLTags Historian require a connection to an external database. If you don't have a database, like Microsoft SQL Server, MySQL, or Oracle installed, don't worry - you can come back to this step later.
Introduction
47
Database connections in Ignition are powered by JDBC drivers. Ignition ships with drivers for Microsoft SQL Server, MySQL, Oracle, and PostgreSQL. Adding a new JDBC driver for other databases, like IBM DB2, is not very difficult, see Adding a JDBC driver. Pick the JDBC driver your database, and click on the "Next >" button.
1.4.9
Web-Launching
Web-launching is one of the best parts about Ignition. This is how we launch both the Designer, which is where you'll configure your projects, and our Ignition Vision Clients. Web-launching is a technology that lets you launch a full-fledged application with zero installation just by clicking a link on a webpage. This means that with Ignition, you'll only ever need to install the Gateway. All of your Clients and Designers do not need to be installed, and they are always kept up-to-date. Once you start using web-launched clients, you'll wonder how you ever did without them. In order to successfully web-launch, you'll need Java 5 or Java 6 installed. If you're on the computer that's running the Ignition Gateway, you already have Java installed - the Ignition installer made sure of that. If you're on a computer that is accessing the Gateway over the network, the Java Detection panel on the bottom of the Gateway's homepage will detect whether or not Java is installed.
Introduction
48
Designer is the same as for the Gateway Configuration section: admin / password The next window will prompt you to open a project. You don't have any projects yet - so click on the " Create New" tab. Enter a name for your new project (no spaces!) and press the "Create" button. That's it - you're now editing your project!
Now you can browse all of your OPC connections. By default you've got a connection to the internal Ignition OPC-UA server, which has the device in it that you created earlier. Browse the device and find some tags that you're interested in. Highlight the tags and drag them into the "Tags" folder in the SQLTags Browser panel.
Introduction
49
Thats it - you now have some SQLTags. You should see their values come in and start updating.
Introduction
50
1.4.14 Uninstallation
Ignition installations contain an uninstaller executable that is created during a new installation. When Ignition is uninstalled, the settings database and folder (contained in the /data) folder is backed up to / data_<current date>. Similarly, modules and user-supplied JDBC jars (contained in the /user-lib folder), are backed up to /user-lib_<current date>. The Ignition service is also removed from Windows and
2012 Inductive Automation
Introduction
51
Ubuntu Linux installations automatically. Be sure to back up your gateway and unactivate your gateway license before uninstalling! Windows: To run the uninstaller, open the start menu and navigate to Programs > Inductive Automation > Ignition and select Uninstall Ignition. The uninstaller wizard will guide you through the uninstallation process. You can also uninstall Ignition from the Add/Remove Programs section of the Windows Control Panel. Linux (using downloaded installer): Linux installations contain an uninstaller executable as long as the original installation was Ignition 7.3 or later. To run the uninstaller, open a command shell and navigate to /user/local/bin/ignition (or your installation folder) and run ./uninstall as root or sudo. Linux Ignition installations before 7.3 utilized a zip file that was exploded in place to form an installation. Since these installations were never created with an installer executable, no uninstaller executable was ever generated. This is true even if using a 7.3 or later installer executable to upgrade an installation from before 7.3. For these installations, you must manually remove the Ignition folders using the commands below. /etc/init.d/ignition stop *Ubuntu only* update-rc.d -f ignition remove rm /etc/init.d/ignition rm -rf /usr/local/bin/ignition *Recommended* mv /var/lib/ignition/data /var/lib/ignition/data_<current date> *Recommended* mv /var/lib/ignition/user-lib /var/lib/ignition/user_lib_<current date> *Recommended* mv /etc/ignition /etc/ignition_<current date> rm -rf /var/log/ignition Ubuntu Package Management Uninstallation: Installations using the Ubuntu Package Manager offer the choice to remove the installation while retaining the configuration files in /etc, or to completely purge the installation from the system. If you choose to purge the installation, Ubuntu will need to download Ignition again if you would like to reinstall Ignition. Simple removal: open a command shell and run sudo apt-get remove ignition (for stable installations) or sudo apt-get remove ignition-beta (for beta installations). Full removal and purge: open a command shell and run sudo apt-get purge ignition (for stable installations) or sudo apt-get purge ignition-beta (for beta installations).
Overview
Part II
Overview
53
2
2.1
Overview
What is Ignition?
Ignition is an Industrial Application Server. Installed as server software, it uses webpages and weblaunching to create a wide variety of industrial applications. These sorts of applications typically fall under the definitions of HMI, SCADA, and MES applications. Ignition achieves its functionality through a modular architecture, meaning that multiple pieces work together seamlessly to provide features like: OPC-UA Server OPC-UA the leading industrial standard for data access. Using the OPC-UA Module, Ignition will act as an OPC-UA server, serving data collected by its built in drivers to other Ignition modules, as well as third-party OPC-UA clients. For more information about OPC, see the section What is OPC? For more information about the device drivers available in Ignition, see About Ignition Device Drivers Data Logger Ignition offers robust data-logging functionality. The SQL Bridge module offers historical logging, trigger based transactions with handshakes, and much more. Additionally, the ground-breaking SQLTag Historian feature makes it easier than ever to store and use historical process data. Status & Control Ignition offer first class status and control functionality, and can be used to create single-user terminals as well as distributed systems. SQLTags, Ignition's tag system, provides many powerful features and unparalleled ease of use. By simply dragging-and-dropping, you can create a powerful status and control screen in minutes. Features such as Redundancy and Panel Edition licensing help create dependable, fault-tolerant systems. Alerting Server Flexible alert monitoring is built into SQLTags, and the Ignition gateway supports a variety of logging and notification features. Alert Distribution Groups allow you to send email alerts with a high level of control. Alert history can easily be stored and queried, making it easy to track and analyze common problems in your process. Data Analysis Ignition offers industry-leading trending and data analysis functionality. The power of SQL database access is built in from the ground up, and offers a tremendous amount of power in today's IT centric plants. Powerful charting, tables, and reports combined with Ignition no-install, web-launched distribution model offer new possibilities in data analysis. PDF Reporting Create dynamic, data-rich PDF reports using the Reporting module. Leveraging the power of SQL databases, it's easy to tie together production and business data. See Also: Modules
2.2
2.2.1
Architecture
Architecture Overview
Ignition is a powerful server application that consists of many parts. However, it is designed to be approachable and easy to start using up front, with the power to accomplish many advanced tasks as the user requires them.
Overview
54
In order to effectively use this guide and to get started, there are a few basic concepts about the architecture of Ignition that should be understood from the start. These key concepts are located in the System Concepts chapter. In addition to the internal architecture of Ignition, there are many system architectures that are possible. This is how Ignition is installed, and how it interacts with other key systems, such as Databases and OPC servers. The Architecture Diagrams chapter outlines a variety of different possibilities. Most users will begin working with Ignition using a standard architecture, where the software and all components are all installed on a single machine. To receive the full benefit of Ignition, however, it's important to know what is possible- and therefore it is recommended that you at least browse through the various architecture diagrams and advanced architecture topics. As your system expands, you can come back to investigate the possibilities in more depth.
2.2.2
2.2.2.1
System Concepts
Ignition Gateway The Ignition gateway is the primary service that drives everything. It is a single application that runs an embedded web server, connects to data, executes modules, communicates with clients and more.
Overview
55
Launching clients
Clients are launched from the Gateway homepage, for a specific project. See the Gateway Navigation section for more information.
How it works
Normally, you can't launch Vision Module projects on mobile devices. This is due to the technical limitation that Java SE (Standard Edition) does not run on mobile devices. The Mobile Module gets around this limitation by launching the client on the Gateway in a special headless (invisible) mode, and then using HTML5 and AJAX to show the client's screen on the mobile device's browser.
Overview
56
Networking
Typically, the mobile device will connect to the Ignition Gateway via the facility's wireless LAN (802.11) infrastructure. To launch a mobile client, the mobile device simply connects to the Ignition Gateway by pointing its web browser to the Gateway's LAN address. It is important to understand that normally, the traffic is not going over the device's cellular connection. This wouldn't work, because the cellular connection connects to the internet, and without explicit setup, an Ignition Gateway is not accessible from the outside internet. Remote (as in, beyond the reach of 802.11 wireless LAN) mobile access can be enabled through the same networking strategies that enable remote access for standard Vision clients. Somehow, the mobile device must be able to access the Ignition Gateway via its cellular connection. One strategy would be to set up a VPN router and configure the mobile device as a VPN client. This way, the mobile device could directly access the LAN address of the Gateway as if it were on-site. Another technique would be to put the Ignition Gateway in a DMZ so that at least one NIC had a public IP address. Or, an edge router could be configured to port-forward the HTTP and HTTPS ports to the Gateway. Coordination with your I.T. department would be advised when attempting to set up remote access. 2.2.2.5 Database Access Access to relational databases is at the heart of the Ignition platform. Ignition can connect to any SQL database that has a JDBC driver, though depending on the database's capabilities, some features may not be available.
Overview
57
Introduction
SQLTags TM is the tag database mechanism of Ignition. Each tag in Ignition is a SQLTag, irregardless of whether the value comes from OPC, an expression, or is static. SQLTags provide a variety of configuration options, such as alerting, scaling, and historical storage. SQLTags are stored in tag providers. By default, a fresh Ignition installation will have an internal tag provider - this can be thought of as a standard internal tag database. Additionally, it is possible create external DB-based tag providers, thus turning your SQL database into the tag database. This ability opens up some very flexible architectures and is the primary reason why SQLTags have their name.
Overview
58
communicate the status of the system at a glance. One-click historical logging with SQLTags HistorianTM SQLTags Historian makes it easier than ever to store and use historical data. By simply selecting a checkbox on a tag, historical data will be stored in an efficient format in your SQL database, and will be available for querying through scripting, historical bindings and reporting. Drag-and-drop tags directly onto an EasyChartTM to create trends, or onto a table to display historical values. SQLTags Historian's robust querying features give you great flexibility in how you retrieve the data.
2.2.3
2.2.3.1
Architecture Diagrams
Standard Architecture
In the standard architecture, a single Ignition gateway is installed on a central server with all of the desired modules. Devices are connected over the network or serial links, and are accessed through Ignition OPC-UA or other OPC servers installed on the same machine. Database connections are made to database servers installed on the same machine or elsewhere on the network. Any network enabled device with Java and access to the server can launch clients by going to the gateway homepage. Designers can also be launched over the network. Both clients and designers can be launched locally at the server as well.
2012 Inductive Automation
Overview
59
2.2.3.2
OPC-UA Architecture
The OPC-UA architecture is very similar to the Standard architecture, but with only the Ignition OPC-UA module installed on the server. In this configuration, the Ignition gateway acts as a dedicated OPC-UA server. Any remote OPC-UA client, including other Ignition gateways, with network access can connect to the server and read and write data. This installation is useful for aggregating data from many sites. The low installation cost and the secure, painless connections provided by OPC-UA make it easy to access and collect data that wasn't previously available on the network.
Overview
60
2.2.3.3
Ignition is highly network centric, with the ability to connect to remote databases and OPC-UA servers as naturally as to local ones. This fact, combined with the built-in store & forward engine, make it possible to create wide, geographically dispersed systems with little additional work. Remote Ignition gateways with the OPC-UA and SQL Bridge modules can store data to central servers. Should the connection go down, the data will be cached until the connection is again available, ensuring that nothing is lost. Web-launched clients can be used on any computer with access to the network- even over a WAN (wide area network) or VPN (virtual private network). In this way, users can securely access data that has been pulled together from a wide variety of sources.
Overview
61
2.2.3.4
As described in the Remote Datalogging section, the network-centric nature of Ignition makes it easy to access data across a wide area network. Additional key features such as retargeting make it possible to blend complete systems hosted at different locations into one seamless architecture. Each location operates independently, but when combined with a secure inter-location network (such as a VPN over the internet), any location can securely interact with the other locations. There are many possible layers of security, included encrypted communication and the ability to adjust authentication access for each location. For example, users from remote sites may be allowed to only view data, and not modify or control machinery. Conversely, if desired, a central operator may be allowed to control aspects of each location.
Overview
62
2.2.3.5
With Ignition Panel Edition, you can install dedicated control clients close to hardware, ensuring availability should the network go down. Using Retargeting, the Panel project can be seamlessly integrated in to a larger system, and accessed from remote clients.
2.2.4
2.2.4.1
Overview
63
OPC-UA Only
OPC-UA is a network-based specification, and is ideal for collecting data from remote locations. Installing Ignition with only the OPC-UA gives you the ability to connect easily and securely from any number of other Ignition installations, or with other OPC-UA clients. This method only exposes data, however, and the client side must then record it if historical data is desired. If the connection goes down, data will not be available. This method offers the lowest cost, and is suited for situations where the data is not highly critical or historical- for example, remote realtime monitoring.
Overview
64
gateways, and each of those gateways will be able to access the tags driven by the others. Using this methodology it is possible to aggregate multiple remote sites and built a cohesive system that spans multiple parts of a single plant, or multiple separate plants entirely. 2.2.4.4 Client Retargeting Client Retargeting is the method by which Clients running a particular project switch to a different project on the fly, even if the other project is hosted on a different Ignition Gateway. Retargeting is a key feature used to build distributed systems. It allows you switch between projects and servers as easily as switching between windows. Using Retargeting, even geographically dispersed projects can be presented as a single cohesive unit.
Using Retargeting
Retargeting is accomplished through scripting, usually as a response to a button press or other component event. The system.util.retarget function allows you to specify a Gateway and project to retarget to. Authentication will be transferred with the request, and the switch will only occur if the current user also has rights to the target project.
2.3
2.3.1
Modules
Overview
What are modules?
Modules are applications that are built on the Ignition platform and integrate into the platform in order to offer functionality. Most of the main features of Ignition are actually provided by different modules such as the Vision and SQL Bridge modules. Modules integrate seamlessly into the system and provide things like new designer workspaces, new gateway settings, new drivers, and much more.
Why Modules?
The modular architecture of Ignition offers a wide array of benefits. Flexible licensing - only license the modules that you need, saving money and reducing complexity compared to big monolithic applications that try to do everything. At the same time, the modules have been designed to offer a broad swath of functionality, to avoid having too many pieces. Hot-swappable - Modules can be dynamically loaded and unloaded, allowing you to install, remove and upgrade them without affecting other parts of the system. This can have huge implications for big projects where up-time is important. Increased system stability - Building modules on a common platform means fewer bugs, better isolation, and all around increased stability.
Types of Modules
Module Name OPC-UA Module SQL Bridge Module Vision Module Description Provides OPC-UA server functionality and an open device driver API. Offers transactional datalogging, bi-directional OPC-to-DB synchronization, stored procedure support and more. Provides HMI/SCADA functionality with web-launched clients.
2012 Inductive Automation
Overview
65
Works with the Vision module to provide robust reporting capabilities. Allows Ignition to connect to older COM based OPC-DA servers.
2.3.2
OPC-UA Module
The Ignition OPC-UA module offers OPC-UA server functionality with a variety of device drivers and a robust, open driver API.
Redundancy Support
The OPC-UA module ties into the Ignition redundancy in order to provide efficient access to device data along with failover redundancy, with no additional configuration.
2.3.3
Overview
66
2.3.4
Vision Module
The Vision module provides the visual elements of Ignition. Vision offers a wide range of functionality, and can be used to create HMI style control systems, data analysis and trending applications, executive dashboards, and more. The projects are designed using the Ignition Designer, and clients are weblaunched with zero installation from any Java capable computer.
Vector graphics
Powerful vector-graphics drawing tools allow you to create inviting graphics for your project. Vector graphics are screen-resolution independent, allowing screens to look great on any size monitor. Advanced graphics features like gradients, Bzier curves, transparency, are easily accessible with the intuitive drawing tools. Create your own symbols, import them from *.svg files using drag-and-drop, or use the Symbol Factory module to access nearly 4,000 ready to use, professional-quality vector symbols.
Unlimited potential
Web-launched clients, the ability to seamlessly connect multiple projects through Retargeting, and no licensing restrictions on screens, tags, components or clients means the system can grow over time.
2.3.5
Reporting Module
The reporting module adds dynamic reporting functionality to the Vision module, allowing you to display reports to Vision clients or to generate PDF files. The reporting module offers flexible report generation, with a variety of components, charts and tables. Additionally, it supports the import of existing forms and images, allowing you to migrate from paper based tracking systems to an electronic system.
Overview
67
2.3.6
Mobile Module
The Mobile Module adds the ability to launch Vision Module projects on modern smartphones. This lets you keep track of your control system while moving around your facility. The Mobile Module can be combined with remote-access networking architecture to allow global on-the-go access to your control system.
2.3.7
OPC-COM Module
The OPC-COM module gives Ignition the ability to connect to legacy ("classic") COM based OPC-DA servers. It supports OPC-DA 2.0 and 3.0.
2.3.8
Other Modules
The pluggable module architecture allows quick integration of new modules into the Ignition platform. From time to time new modules will be release which add additional features.
Driver modules
Drivers for the OPC-UA module are deployed as modules themselves. While they don't add a visible element to the system, they are loaded and upgraded in the same manner as other Ignition modules.
ActiveX Module
There is a free module available for separate download from our website that adds an ActiveX palette to the Vision module. This lets you use ActiveX controls in your windows. This module comes with some caveats, however. ActiveX doesn't play all that gracefully with Ignition, because it is written in Java. ActiveX controls will only work on Windows. They also draw themselves "on top of" the entire Vision client application. This means that nothing can overlap them, not even other windows or dropdown menus. Because of these technical limitations, this module is provided as-is, with limited technical support. These details aside, the ActiveX component can be a great way to integrate a full-fledged PDF viewer or web-browser into your Ignition Vision application.
Overview
68
This module integrates Symbol Factory 2.5 from Software Toolbox into the Ignition Designer. The intuitive interface allows you to browse and search through nearly 4,000 high quality vector graphics symbols. Once you find the symbol you're looking for, simple drag-and-drop it onto a Vision window to use it right away. Double-click on the symbol to change it, or dynamically animate parts of it to bring your project to life.
2.4
2.4.1
Basic Usage
Gateway Navigation
Accessing the Gateway
The Ignition Gateway is accessed via a web browser. The web browser can be running on any machine that has network access to the host that is running the Ignition Gateway. By default, Ignition installs using port 8088. Example If the host's IP address was 10.0.28.30, you would access the Ignition Gateway via the URL:
http://10.0.28.30:8088
Gateway Sections
Across the top of the Ignition gateway you'll find several buttons that lead to the key sections of the server. Home The homepage shows a quick overview of the primary modules installed. From here you can: Launch Vision project clients. View the current status of the SQL Bridge module, and how many transaction groups are running. View the state of your device connections under the OPC-UA module. Status The status portal provides in depth information about various parts of the Ignition system. There are sub-pages containing information about: The state of the installed modules The status of all DB connections, OPC Server connections, and SQLTag providers. The status of the store and forward engine, including performance metrics and data cache information. Current designer and client sessions connected to the gateway. Status of all the Gateway Scripts that are running in each of the different projects on the Ignition Gateway Information and statistics regarding the OPC-UA server. Configure This section is where all gateway/platform configuration is performed. See Gateway Configuration for more complete details. In general, this is where you'll go to:
2012 Inductive Automation
Overview
69
Create new projects Create database connections Create connections to OPC servers Tune performance settings Modify SQLTags Historian data settings Manage users and roles and much more. Launch Designer This button directly launches the Ignition Designer.
2.4.2
Windows: The GCU can be launched from the start menu under Programs > Inductive Automation > Ignition > Launch Gateway Control Utility. You can also launch the GCU from either a command line or from the Start -> Run dialog by typing launch-gcu Linux: The GCU can be launched by opening a command shell and typing gcu. If you receive an error saying that "gcu can't be found", then you need to add the Ignition installation directory to your system path. See the Installation (Linux) section for instructions. If you are running in a headless Linux environment, or you have logged into the Linux machine through an SSH shell, then the functions of the GCU are still available in command-line form. See the Command Line Utility section below.
Overview
70
Gateway Status
The upper left side of the screen shows the state of the Tomcat web server and the Ignition Gateway web application. It is possible for the web server to be running while the Gateway has failed. For example, this can occur when the Gateway has faulted upon startup.
Commands
The GCU provides several commands that can be run to administer the gateway: Go to webpage Launches a web browser to the gateway home page. Restart Restarts the Tomcat web server. Reset Password Allows you to reset the root password of the system. This is not normally considered a security risk, because the GCU can only be used from the machine the software is installed on, which should be secure. However, it is important to know that this function is here, so that the GCU can be removed if the machine can't be properly secured (for example, when the server is also used as a client). Thread dump Downloads a file with the current states of all threads in the server, used by Inductive Automation for troubleshooting problems. Gateway Backup Downloads a Gateway backup (.gwbk) file to the local file system. A Save File dialog will open, allowing you to specify where to save the .gwbk file. Port Sets the primary, non-encrypted port used by clients to communicate with the server. Click the Save button to apply the port change to the gateway. The gateway must be restarted for the change to take effect. SSL Port Sets the port that will be used by clients for SSL communication. Click the Save button to apply the port change to the gateway. The gateway must be restarted for the change to take effect. Stop Service and Start Service Windows users get two additional buttons at the top. The stop button stops the Ignition Windows service, and the start button starts the Ignition Windows service. Linux users can stop and start the gateway with these command-line commands: /etc/init.d/ignition start /etc/init.d/ignition stop
Overview
71
path>
path. The path can be either an absolute path or a relative path.If a new file name is not specified at the end of the path, then the file name will become the current date and time along with the .gwbk extension. You will be prompted whether it is OK to overwrite the file if another .gwbk file with the same name already exists (override with the -y option to force the file to always be overwritten). -h,--help Shows the usage for this command -i,--info Retrieves server status and port information from the Gateway if it is running -k,--port <new port> Changes the Gateway http port -l,--sslport <new port> Changes the Gateway https port -p,--passwd Resets the Gateway login password -r,--restart Restarts the Gateway -t,--tdump Performs a thread dump in the Gateway and prints the dump to the command line -y,--promptyes Automatically answers "yes" to any prompt that may appear in the above commands (such as permission to overwrite an existing file).
2.4.3
Web Launching
Web-launching is the mechanism by which clients and designers are opened on a machine. They are launched from the Ignition gateway, download and run without requiring any installation steps.
Overview
72
2.4.4
Launching Clients
Clients are launched by going to the gateway homepage. See Gateway Navigation for more information about accessing the gateway. There are three ways to run clients: Windowed, Full screen, and Applet. The mode can be chosen from the drop down next to the project name. Clicking on the project name will launch the project in the default mode. Certain modes may not be available, depending on project settings.
Windowed
The "Windowed" mode is the standard launch method. The client will be web-launched using Java WebStart and will have its own window. In this mode, it will run as a full, independent application. After being launched, the browser can be closed and the project can be launched from a shortcut on the desktop.
Full Screen
The "full screen" launch mode is similar to the Windowed mode, and will also use web-launching to run the client as a full, independent application. In this mode, however, the client will occupy the full screen, and will not have a title bar. This mode is ideal for touch-screen display panels, and other displays where the Ignition project will be the sole focus on the screen.
Applet
Selecting "applet" launch mode will run the client application as an applet embedded in your web browser. Applet mode is most commonly used to integrate Vision projects into existing web sites, such as in a corporate intranet setting.
Mobile
If you have the Mobile Module installed, you can launch projects on your smartphone or tablet as well. All the user has to do to launch a mobile client is to connect their mobile device to the wireless network and point the web-browser to the Gateway's LAN address. At this point, they'll be presented with a mobile-optimized version of the Ignition Gateway homepage, where they can select a project to launch. Note that projects must have at least one window defined and be enabled for mobile launching in order to show up in this list. After selecting a project and logging in, they can use the project like a normal project. To access the mobile project context menu, press and hold on your touch-sensitive device. A circular menu will appear allowing you to switch between pointer and pan/zoom mode, as well as options for logging out and entering text input.
2.4.5
Gateway Configuration
Part III
Gateway Configuration
74
3
3.1
Gateway Configuration
Gateway Configuration Overview
The gateway is the central location where all general services are configured in Ignition. Additionally, the gateway configuration section is where operations such as backing up the system, restoring, and managing projects are performed. The gateway configuration settings cover the following broad categories: System Management - Licensing, Backup/Restore Module Management Database Connectivity OPC Connectivity SQLTags Security Alerting Other categories may also be available, depending on the modules installed.
3.2
Default Login
When the system is first installed, the gateway can be access with the following credentials:
Username: admin Password: password
As mentioned above, it is strongly suggested that you quickly change these default settings to something more secure. See the Managing Users section for more information.
3.3
3.3.1
Basics
Basic Gateway Settings
The basic gateway settings are found under Configuration > Gateway Settings. They define high-level settings that apply to the entire gateway. System Name A unique name for this Ignition installation. It is used to distinguish between this server and others on the network when working with multiple Ignition installations. System Authentication Profile The authentication profile used to secure access to the Gateway, as well as to the Designer. Gateway Config Roles
Gateway Configuration
75
A comma-separated list of roles, one of which will be required in order to log into the Gateway's configuration section. These roles roles should be defined in the System Authentication Profile. Status Page Roles Required roles to access the Gateway's status section. Leave blank to remove security restrictions for this section. Home Page Roles Required roles to access the Gateway's home section. Leave blank to remove security restrictions for this section. Note that this is only used to limit access to the homepage itself, each project will have its own authentication profile for limiting access to the runtimes. Designer Roles The roles that will be granted access for logging into the Designer. Use SSL Forces the clients to use SSL encrypted communication when talking to the gateway. It is recommended that you purchase and install a genuine SSL certificate if you use this option. See the guide in the Deployment section of this manual. Persist Alerts Whether or not alert properties such as acknowledgment should be persisted across Gateway restarts. Launch Link Script Policy Controls how the HTML that launches Clients and Designer functions. If set to JavaScript, the links will use javascript to attempt to launch directly using the Java browser plugin. If set to Direct, the links will be direct links to the *.jnlp files that launch the Client or Designer. Allowed JREs Which versions of the Java Runtime Environment will be allowed to web-launch clients and designers. Designer Memory The maximum memory that the designer may use. Disable Direct3D / Disable DirectDraw These advanced properties affect launched Clients and Designers on Windows OS only. These flags control whether or not the Java Swing windowing subsystem may use Direct3D and/or DirectDraw. Disabling these features may incur a performance penalty, but might be required for some video cards that have faulty DirectX drivers. Scheduled Backups These 4 properties (enable, backup folder, backup times, and retention count) control the Gateway's scheduled backup system. This system is capable of automatically making a Gateway backup and storing it to a folder path, which may be a network path. When you enable this system, you must specify a destination folder. This may be a local folder, for example "C:\backups" or "/var/ backups" or a network path such as "\\fileserver\backups". The scheduled backup system works on a schedule that is specified using UNIX crontab syntax. This is a standard format for specifying a basic schedule. The format consists of five space-separated fields, one for minute, hour, day-of-month, month, and day-of-week. The special character * means "all". Slashes can be used to indicate that values should be stepped, for example, */5 in the minutes field means "every 5 minutes", or 0:00, 0;05, 0:10, etc. Some examples: 5 * * * * Once an hour, on the :05 minute. 0:05, 1:05, 2:05, etc. */15 * * * * Every 15 minutes, on the quarter-hour. 0:15, 0:30, 0:45; 1:00, 1:15, etc. 30 5 * * Mon Every Monday at 5:30am
2012 Inductive Automation
Gateway Configuration
76
* 6-14 * * * Every minute, but only between 6am and 2pm */5 8-17 * * 1-5 Every 5 minutes between 8am and 5pm but only during the week (1-5). 0=Sunday, 1=Monday, etc. 015** Once a month, on the 5th day at 1am If something is wrong with the scheduled backup system it will store error messages to the Gateway logs.
3.3.2
3.3.3
3.3.4
3.3.5
3.3.5.1
Activation
Online Activation All activation activity is performed in the gateway configuration portal under System > Licensing. The general topic of activation is described in the introduction under Licensing, Activation, and Trial Mode. If you have been issued a CD Key and wish to activate online: 1. Click on the "Purchase or activate..." link on the licensing page. 2. Click on "Activate" 3. Enter your CD Key 4. The request will be processed over the internet. If a connection is not available, you will be redirected to a page that allows you to perform an offline activation.
Gateway Configuration
77
3.3.5.2
Offline Activation Offline activation is used to activate servers when an internet connection isn't available. The process consists of generating a secure file, transferring it to Inductive Automation, and receiving back a corresponding license file. To activate off-line, follow the same steps as outlined in the Online Activation section. After entering your CD Key, you will be presented with a screen where you can download your activation request file.
3.3.5.3
Unactivation Only one Ignition gateway instance is allowed to be activated at a given time, for a given CD Key. If you would like to activate Ignition on a different server, you must first unactivate the previous server. To unactivate, go to System > Licensing. On that page you will see the currently installed license, with the option to "unactivate" at the bottom of the display. Clicking this link and following the instructions will initiate the unactivation procedure. Unactivation is virtually the exact opposite of Activation. In the process, an "unactivation request" will be generated. The software will be unactivated immediately, but a new activation will not be available until the unactivation request is received by Inductive Automation. There are both online and offline options for transferring the request, as with activation.
3.3.5.4
Updating the License If you wish to modify your license in order to add or remove modules, or change the level of a particular license, you will need to contact Inductive Automation. The modules will be adjusted for the CD Key, and you will then be able to re-activate the system using the same key. Once your new license file is installed, the Ignition server will be updated with the desired module licenses.
3.3.6
Gateway Console
The Gateway Console provides a wealth of information about the running state of the gateway. It is located under System > Console, in the gateway configuration portal. Most of the features in this section are for advanced troubleshooting, and are not often consulted in normal operation. Of all of the tabs in this section, the Log Viewer is the most useful for system administrators.
Log Viewer
The log viewer shows the most recent output of gateway "loggers"- units in the gateway application that output information.
2012 Inductive Automation
Gateway Configuration
78
Levels
The Levels tab shows all of the registered system loggers, and the level of detail that they should record.
Threads
This section shows the current state of all system threads.
Memory
Provides a breakdown of how memory is being used by Ignition.
Execution
Show a list of all registered "executors"- tasks that perform repeat operations.
Advanced
This section is the entry point to the Raw Settings Viewer. The Raw Settings Viewer allows advanced users to make queries against the internal database for advanced troubleshooting purposes. There is potential to really do some damage to the Ignition installation if one isn't careful. Use extreme caution when working directly with the internal database.
3.4
3.4.1
Projects
What is a Project?
An Ignition project is a unit of configuration that consists of: Windows Transaction Groups General Settings Security Settings Each runtime client or designer can operate on one project at a time. If a project contains viewable elements (windows, reports) a launch link for it will appear on the gateway homepage. Otherwise, the project will run in the gateway and will not have a client runtime. There is no limit to the number of projects that can be created on a gateway.
3.4.2
Project Management
Project management is performed under Configuration > Projects in the gateway. Some project management can also be performed through the designer. See Designer Project Properties for more information.
Gateway Configuration
79
To create a new project, click on "Create new project" from the project management page. To create a new project you'll define: Name - A unique name for the project in the system. Note: it is not advisable to change this after it's been created, instead, change the Title if you want to change how the project appears later. Description - Purely for informational purposes for the user. Title - How the project will appear to users. Additionally, there are a few crucial properties that dictate how the project is accessed and how elements inside of it act: Authentication Profile The profile to use for granting access to the project. For more information, see the Security section. Default Database All elements of the project will use this database connection unless explicitly specified otherwise. Default SQLTags Provider The primary SQLTags provider for the project. Most installations will likely only have one provider, but in situations where there are more than one, this is the provider that will be used by default.
Deleting Projects
Projects can be deleted by selecting the "Delete" option to the right of the project name in the list. Be aware that this action cannot be undone, and once a project is deleted it is gone forever (unless it can be recovered from a backup or auto-backup. See the Backups section for more information).
Copying Projects
Projects can be cloned easily using the "Copy" link next to the project's entry. This is useful for creating a "snapshot" of a project before starting major changes, or for creating a starting point for a new project based on an old one.
3.4.3
Project Versioning
Each project can have two distinct versions at once: the Staging version and the Published version. By default, a new project is configured to be in Auto publish mode, which means that the two versions are always identical. However, if you change a project to be in Manual publish mode, then you can explicitly publish a project in the Designer.
Published vs Staging
The general idea between having a published version and a staging version is to allow you to save a project, and then test out the changes before "publishing" those changes to a production environment. Under normal conditions, Vision module clients run the published version of a project. However, by launching a client in a special mode (from the Designer or from the Config section of the Gateway), you can launch a client that runs the staging version of that project. This staging client will receive updates on every save, where the production clients receive updates only on publish. This lets you test out your changes to the project in an actual client, which is more realistic than the Designer's preview mode. Not all aspects that comprise a project use this system. It is primarily intended for systems such as the Vision module's clients. Features that run persistently on the Gateway, such as SQLTags, the SQL Bridge's Transaction Groups, and Gateway-side scripting always run the most recently saved changes (the Staging version). Since these features by definition must run in exactly one place, they cannot be
Gateway Configuration
80
effectively "tested out" by simultaneously running a staging version alongside a published version.
Commit Messages
A project may be configured to prompt the user making changes to describe those changes, either on every publish event, or on every save and publish event. These messages, called commit messages, are used to describe the changes that have been made to the project. By inspecting the project's history and reading these commit messages, you can learn what changes have been made to the project, for what reason, and by whom. See also: Project General Properties
3.4.4
3.5
3.5.1
Modules
Module Management
All module configuration is performed under Configuration > Modules. Note that this section is used solely for adding, removing, and restarting modules. Modules integrate their settings into the gateway configuration tree, and therefore do not offer settings in this section.
Gateway Configuration
81
Modules are hot-swappable, so these actions can be performed while the system is running. Furthermore, the isolated nature of modules ensures that performing one of these actions will only affect that particular module, and any modules which depend on it. For example, uninstalling the SQL Bridge module will not affect any running Vision module clients.
Restarting a Module
Modules can be restarted by clicking the restart button next to their entries. As mentioned above, the isolated nature of modules means that the other modules will not be affected by the restart (unless they depend on that particular module).
Module Status
The installed module list also provides some basic information about the state of the module. The version, license and state are all displayed in the list. Module licensing is performed centrally in System > Licensing, so the values here are only for information purposes.
3.6
3.6.1
Databases
Databases Overview
Database access is at the heart of the Ignition platform, enabling you to create robust data-centric systems. Relational "SQL"-based databases are extremely common in modern companies, and offer a tremendous amount of power and flexibility in storing, calculating, and manipulating data. By connecting Ignition to one or more databases, you can leverage this power to create systems that expose data, store historical information, and more.
Gateway Configuration
82
3.6.2
Supported Databases
Ignition has been tested with the following databases, and can connect to them directly after installation. It is possible to connect to other databases by installing additional JDBC drivers (the Java database connection specification), which are often provided by database vendors.
Full support
Database MySQL Microsoft SQL Server Oracle PostgreSQL Version 5.0+ for full support. Ignition will connect to 4.x, but many features such as SQLTags have not been tested. 2005, 2008, full and express editions. Ignition will connect to 2000, but has not been fully tested. 10g, 11g, full and express. 8.0+
Limited support
Database Microsoft Access Other JDBC drivers Version Access support is very limited, and should only be used to integrate existing data into the project, not for storing new data. Due to variances in databases, some features may not work fully through other non-tested JDBC drivers. However, it is usually possible to get full functionality though the careful use of the database translator feature.
Choosing a database
If you are new to working with SQL databases and are trying to choose a vendor, there are several factors to weigh: Existing company usage - Many companies already use SQL databases for other purposes, and thus most IT departments already have a defined standard. Going along with your company's existing standard is usually recommended, as there will already be staff available who are knowledgeable about the system. Furthermore, you may be able to tie into your company's existing database system instead of maintaining your own. Price and Features - The fully supported databases above vary dramatically in price. Some systems can cost thousands of dollars, but may have a free "express" edition that will work perfectly well for your requirements. Others offer advanced features such as redundancy, which are either not offered or difficult to configure in the other systems. It is therefore important to clearly define the features and capabilities that you need. Most common among Inductive Automation users - choosing a database that is commonly used by
Gateway Configuration
83
Inductive Automation users means that you are more likely to find examples and help in the forum, among other benefits. The supported database list above is sorted according to our current user install base.
3.6.3
3.6.3.1
Database Connections
Creating and Editing Connections Database connections are managed in the gateway under Databases > Connections. To create a new connection, click the Create new Database Connection link below the connection table.
Select a driver
Select the appropriate database driver for the server that you'll be connecting to. If a suitable driver isn't present in the list, you may need to install a new JDBC driver.
Configure Connection
After selecting the driver, you'll configure the settings for the connection. Some settings, such as the Connect URL may be specific to the driver that you're using. Connection Settings Connect URL A string that instructs the driver how to connect to the database. This string will include the server address, and may include the port, instance name, database name, etc. The format and parameters will depend on the driver being used. Username The username to use when connecting. Some databases support other authentication methods, such as Windows authentication, in which case this field would not be used. Password The password to use for the given username. Failover Datasource The connection to use when this connection is not available. Failover Mode How to handle failover and recovery. See below for more information on failover.
Advanced Settings
There are a variety of advanced settings that should not need to be changed under normal circumstances. Their descriptions are shown on the settings page.
Gateway Configuration
84
3.6.3.3
Connecting to Microsoft SQL Server Microsoft SQL Server is a popular robust relational database produced by Microsoft. Ignition can connect to Microsoft SQL Server, however many users find difficulty in getting all of the settings and parameters correct. There are several different ways you can connect to Microsoft SQL Server (all using TCP/IP communication): Specifying a Port using Windows Authentication Specifying an Instance Name using Windows Authentication Specifying a Port using SQL Authentication Specifying an Instance Name using SQL Authentication The most common method, the one out of the box, is to connect using an Instance Name and Windows Authentication.
Gateway Configuration
85
4. To the right you will see all of the protocols the database supports. One of the protocols is TCP/IP. Make sure the status next to TCP/IP is set to Enabled. If not, double click on "TCP/IP" and choose Yes from the drop-down next to Enabled and press OK.
Gateway Configuration
86
Microsoft SQL Server Browser is running. As mentioned earlier, the Microsoft SQL Server Browser translates the instance name to a TCP/IP port in order for your application (Ignition) to connect to it. To check: 1. Open up the SQL Server Configuration Manager from Start > All Programs > Microsoft SQL Server Version # > Configuration Tools > SQL Server Configuration Manager. 2. Once it is open, select the "SQL Server Version # Services" section. 3. To the right you will see all of the services installed. One of the services is the "SQL Server Browser". Make sure this service is in fact running. If the service is not running, right click and select Start. Note: The service could be disabled so you may have to double click on it to enable the service before starting it up.
Gateway Configuration
87
Now that Microsoft SQL Server accepts SQL authentication we can move to configuring Ignition. Follow these steps: 1. Open and login into the Ignition Gateway configuration page from your web-browser. (http:// hostname:8088/main/web/config)
Gateway Configuration
88
2. Select Databases > Connections from the menu. 3. Click "Create new Database Connection" 4. Select the "Microsoft SQL Server JDBC Driver" and press next. 5. Give the connection a name like "SQL Server SQL Auth" 6. Set the "Connect URL" to: jdbc:sqlserver://Hostname\InstanceName Replace the "Hostname" with your databases IP address or hostname and replace the "InstanceName" with your databases instance name. Here are a couple of examples: jdbc:sqlserver://localhost\SQLEXPRESS jdbc:sqlserver://10.10.1.5\MSSQLSERVER 7. Set the username and password to a valid SQL authentication user. For example, "sa" is an administrator account you can use. To add your own user account open the "SQL Server Management Studio", expand the Security > Logins folder. There you can see all of the current logins. Right click on the Logins folder and click "New Login...". Choose the SQL Server authentication mode and type in a username and password. Note: You will also have to add permissions to your database by mapping "db_datareader" and "db_datawriter" to the new user in the "User Mapping" section. 8. Lastly, set the "Extra Connection Properties" to your database. For example: databaseName=test Replace "test" with your database name. 9. Press "Create New Database Connection" and the status should be Valid after a couple of seconds. If the connection is "Faulted" click on the "Database Connection Status" link to find out why. Typically the username/password is incorrect or the user doesn't have the right permissions.
Gateway Configuration
89
4. Now let's setup Ignition to logon using the right Windows account. Open the "Services Control Panel" from Start > Control Panel > Administrative Tools > Services. 5. Right click on the "Ignition" service and choose "Properties". 6. Select the "Log On" tab. 7. Choose "This Account" and enter in your Windows username and password. Press OK to save. 8. Restart the Ignition service by either clicking the restart button in the toolbar or stopping and starting from the right click menu.
Now we can move to configuring the database connection in Ignition. Follow these steps: 1. Open and login into the Ignition Gateway configuration page from your web-browser. (http:// hostname:8088/main/web/config) 2. Select Databases > Connections from the menu. 3. Click "Create new Database Connection" 4. Select the "Microsoft SQL Server JDBC Driver" and press next. 5. Give the connection a name like "SQL Server Windows Auth" 6. Set the "Connect URL" to: jdbc:sqlserver://Hostname\InstanceName Replace the "Hostname" with your databases IP address or hostname and replace the "InstanceName" with your databases instance name. Here are a couple of examples: jdbc:sqlserver://localhost\SQLEXPRESS jdbc:sqlserver://10.10.1.5\MSSQLSERVER 7. Leave the username and password blank. 8. Lastly, set the "Extra Connection Properties" to your database and set it to use "Integrated Security". For example: databaseName=test; integratedSecurity=true; Replace "test" with your database name. 9. Press "Create New Database Connection" and the status should be Valid after a couple of seconds. Again, if the connection is "Faulted" click on the "Database Connection Status" link to find out why.
Gateway Configuration
90
Common Problems
TCP/IP Communication Not Enabled SQL Server requires that you explicitly turn on TCP connectivity. To do this, use the SQL Server Configuration Manager, located in the Start menu under "Microsoft SQL Server>Configuration Tools". Under "SQL Server Network Configuration", select your instance, and then enable TCP/IP in the panel to the right. You will need to restart the server for the change to take affect. Window Firewall When connecting remotely, make sure that Windows Firewall is disabled, or set up to allow the necessary ports. Normally ports 1434 and 1433 must be open for TCP traffic, but other ports may be required based on configuration. SQL Server Browser Process Not Running To connect to a named instance, the "SQL Server Browser" service must be running. It is occasionally disabled by default, so you should verify that the service is not only running, but set to start automatically on bootup. The service can be found in the Windows Service Manager (Control Panel>Administrative Tools>Services). Mixed Mode Authentication Not Enabled Unless selected during setup, "mixed mode" or "SQL authentication" is not enabled by default. This mode of authentication is the "username/password" scheme that most users are used to. When not enabled, SQL Server only allows connections using Windows Authentication. Due to the ease of using SQL Authentication over Windows Authentication, we recommend enabling this option and defining a user account for Ignition. To enable this, open the SQL Server Management Studio and connect to the server. Right click on the instance and select "Properties". Under "Security", select "SQL Sever and Windows Authentication mode". 3.6.3.4 Connecting to MySQL
Gateway Configuration
91
Connect URL
MySQL uses the following URL format:
jdbc:mysql://hostaddress:3306/database
The hostaddress will be the address of the machine with MySQL installed, for example: localhost, 192.168.1.1, db-server, etc. The database parameter will dictate which database schema the connection will target. It's important to understand that a MySQL server can host many database files. The connection will target one database.
3.6.4
3.6.4.1
Database Drivers
What is JDBC? JDBC stands for the Java DataBase Connectivity API. It is a standardized way for Java-based applications to interact with a wide range of databases and data sources. A JDBC Driver enables Ignition to connect to, and use data from, a particular database system.
JDBC in Ignition
Ignition, being a Java based application, leverages JDBC in order to connect to a variety of data sources. This enables Ignition to offer a standardized set of functionality on a wide range of different systems and databases. This includes databases such as MySQL, Microsoft SQL Server, and Oracle, but additionally other lesser-known systems as well, provided the manufacturer offers a JDBC driver for the system.
Gateway Configuration
92
3.6.4.3
Adding a JDBC driver To add a new JDBC driver to Ignition, click the Create new JDBC Driver link from Databases > Drivers page. In order to install a new driver, you'll need the Java JAR file that contains it and any other required JARs, as well as the full name of the driver class. This name is provided in the manufacturer's documentation.
Main Properties
Classname JAR files The full name of the JDBC driver. Should be provided in the manufacturer's documentation. The core JAR file containing the driver, as well as any others required by it.
Translator Management
Database translators are managed in the gateway under Databases > Drivers > Translators (tab). Ignition comes pre-configured with translators for the major supported databases, but it is possible to edit and remove them, as well as create new translators. It should only be necessary to create a new translator when adding a new JDBC driver for a database that does not share syntax with any of the existing translators.
Gateway Configuration
93
Each field of the database translator will define a pattern that will be used, with special token markers to indicate places where other values will be placed. For example, the default Create Table entry looks as follows:
CREATE TABLE {tablename} ({creationdef}{primarykeydef})
In this example, tablename, creationdef, and primaryk eydef are all tokens that will be expanded. The token tablename will be replaced directly with the table, but creationdef will be a list of columns, and primaryk eydef will be the phrase created by the Primary Key Syntax entry in the translator. Many tokens only apply to certain entries. The possible tokens are as follows: Token Description tablename The name of the table being created. indexname The name of the index to create, when adding a column index to the table. primarykeydef A clause that will define a primary key for a new table. creationdef The list of columns to create in the table alterdef A list of columns to add/remove/modify in the table columnname The name of a column type The data type of a column limit The value of the limit clause
3.7
3.7.1
Gateway Configuration
94
Enhanced performance - By first buffering the data in memory, the store and forward system can optimize writes, and prevent the originating systems from blocking. This means that the system is less likely to lose data samples in the event of system slow downs.
3.7.2
Engine Configuration
Configuration of the store and forward engines is performed in the gateway under Databases > Store and Forward. Store and forward engines are directly correlated to database connections, and are automatically managed so that each connection has an engine defined. Tip: Create multiple database connections pointing to the same database if you wish to configure multiple store and forward engines for different purposes.
Gateway Configuration
95
Store Settings
These settings apply to the local disk storage cache. Enable Disk Cache Turn on the hard-disk cache. Data will be stored here if it cannot be forwarded in a timely manner. The cache also stores quarantined data (data with errors). Max Records The maximum size of the cache. After the max is reached, data will back up into the memory buffer, and once that is full, dropped. Write Size The number of records that should be accumulated in the memory store before written to the cache. Writing data in blocks can increase performance, but too large of a size increases the risk of data being lost in the event of a power outage or system failure. Write Time The max age of records in the memory buffer before they are stored to the cache. This setting is used in combination with the write size in order to give the forwarder the opportunity to retrieve data directly from the memory store and avoid the write to disk entirely.
Forward Settings
These settings govern when data will be forwarded to the database. The data will be pulled first from the local cache, and then from the memory store. When no data is present in the cache, it is pulled directly from the memory store. Write Size Same as disk cache setting above. Write Time Same as disk cache setting above. Schedule Pattern If enable schedule is selected, the forward engine will only be enabled during the times specified by the pattern. The pattern can specify specific times and ranges using a simple syntax. Schedule pattern syntax The schedule is specified as a comma separated list of times or time ranges. You may use the following formats: 24-hour times. Ie. "8:00-15:00, 21:00-24:00", for 8am through 3pm, 9pm through midnight. 12-hour with am/pm (if not specified, "12" is considered noon): "8am-3pm, 9pm-12am" Note: when the time period is over, any queued data will remain cached until the next execution period. That is, the forward engine does not run until all data is forwarded.
3.7.3
Gateway Configuration
96
database can accept it. This protects against network failures and database failures, as well. By setting the write size and write time of both the local cache and forwarder to low values, the data will spend less time in the memory buffer. While the memory buffer can be set to 0 in order to bypass it completely, this is not usually recommended, as the buffer is used to create a loose coupling between the history system and other parts of Ignition that report history. This disconnect improves performance and protects against temporary system slowdowns. In fact, it is recommended that for reliable logging this value be set to a high value, in order to allow the maximum possible amount of data to enter the system in the case of a storage slowdown.
Recommended Settings
These settings are merely a starting point, and should be adjusted to fit your goals. Memory Buffer Size 1000 or higher. While the data won't reside in here for long, a high value will allow the data to enter the store and forward system, as opposed to being lost if the maximum is hit. Disk Store - Enabled Max Records 500,000 or higher. Like the memory store, if the maximum is reached data will be lost, so it is best to set the value high to protect against long periods of time without database connectivity. Store Settings - Write Size Very low, in order to get data into the cache as quickly as possible. Moving from the memory buffer to the disk store does not use transactions as much as forwarding to the database, so a low value should not impact performance too dramatically. A value of 1 is possible, though that would force all data to go to the cache before going on to the database. A value of 10 would likely be a good starting point. Store Settings - Write Time This should be the controlling factor in trying to get the system to forward as quickly as possible, minimizing the time that data in the memory buffer. If the write size is 1, this setting will be of little consequence, but if the value is greater than one, careful consideration should be given to this value. Ultimately, this value should only be as large as what you would be willing to lose if there were a power failure. Forward Settings - Write Size This value should be set to a decent size to increase transaction throughput. 100 is a good value. Forward Settings - Write Time This setting should be less than the Store Write Time, in order to avoid writing to the store when the target database is available.
3.7.4
Gateway Configuration
97
Recommended Settings
Memory Buffer 500 or higher. It should be high enough to accommodate several bursts of data. For example, if you expect data to be logged at 100 ms burst for 10 seconds at a time, 100 records would be the minimum value. Data will be forwarded as it comes in, according to the forward settings, but you should not rely on any particular throughput in order to avoid data loss. Disk Store - Disabled Depending on your requirements, the disk store should be disabled, or at least set to have high write size/count settings. Writing and reading from the cache is much slower than memory, so it is desirable to avoid it. Of course, the cache should only be disabled if it is ok to lose some data, should the database connection be down for a period of time. Forward Settings - Write size Should be larger than the expected burst size. Burst data will be from the same source, and therefore will benefit heavily from the optimizations in the buffer. Forward Settings - Write Time Should be balanced in order to give the buffer time to received multiple records that can be optimized, as describe in Write Size above. However, it should not be so long that too much data becomes scheduled to write, which could cause a system slowdown/back up.
3.7.5
Statistics
Availability Shows the status of the engine, each store, and the database. Pending The number of records waiting to be forwarded in that section. Quarantined The number of quarantined records for the cache. Store and Forward Statistics Shows the throughput, number of transactions, and duration statistics. It is important to remember how the data flows when interpreting the statistics. The number of rows that have gone to the database will be the number forwarded from the local cache, and then the number forwarded from the memory buffer, minus those that entered the cache from there.
3.7.6
Data Quarantining
Quarantined data is data that has errored out multiple times during attempts to forward it. It has been removed from the forward queue in order to allow other data to pass. The most common reason for data quarantining is an invalid schema in the database for the data that is being stored.
Gateway Configuration
98
Quarantined data will be held indefinitely until it is either deleted or re-inserted into the queue manually. Quarantined data is controlled from the Quarantine Control tab under Databases > Store and Forward. The data is listed according to store and forward engine and the data format, with a description, the error that caused the quarantine, and the number of quarantined records. Next to the record, there are options to Delete and Retry. Delete Permanently delete the data in the selected row. All transactions of the selected type will be deleted. Retry Un-quarantine the data and place it back in the forward queue.
3.8
3.8.1
OPC
What is OPC?
OPC is a specification for the transport and use of industrial data. It is published and maintained by the OPC Foundation, an organization comprised of hundreds of member companies that strives to ensure interoperability on the plant floor and beyond.
History
The OPC-UA specification is the latest specification in a line spanning back to the mid '90s. The original OPC specifications used Microsoft DCOM technology to provide a uniform way for industrial applications to share data. There were several separate specifications that provided functions such as Data Access (OPC-DA), Alarms and Events (A&E), Historical data (HDA) and more. DCOM always proved difficult to work with, and by 2004 it was clear that a more modern solution was needed. Therefore, a new specification was developed that used common networking principals instead of DCOM, was platform independent, and combined the various separate specifications into one: OPCUA.
Technology
The OPC-UA specification offers a wide range of flexibility in choosing technologies, from the transport mechanism, to the way data is encoded, to the encryption used to secure the data. Ignition supports the UA/TCP transport with the UA/Binary encoding scheme for maximum performance.
Gateway Configuration
99
Additionally, Ignition supports all of the common encryption schemes. This means that Ignition connects to OPC-UA servers (and allows connections from clients) over TCP/IP, using encryption, and sends data by first encoding it into an efficient format defined by the OPC-UA specification. This is in contrast to other schemes outlined in the specification, which can use web services and XML encoding, and are not as efficient.
3.8.2
3.8.2.1
OPC Connections
Connecting to OPC-UA
OPC-UA Connection
An OPC-UA Connection is used to communicate with an OPC-UA compliant server, such as the one the OPC-UA module provides. To create a new connection, go to go OPC Connections>Servers and click "Create new OPC Server Connection". Select "OPC-UA Connection" from the list. OPC-UA connections communicate via TCP/IP so configuration is relatively straight-forward. Main Name Description A name used to identify this connection. Short description of this connection, i.e. "Connection to plant floor."
Connection Settings Host The host name or IP address of server. If the OPC-UA module is running on the same computer you are configuring this connection on then "localhost" will likely be sufficient. The port the OPC-UA server is running. The OPC-UA module defaults to running on port 4096 but can be changed on the OPCUA module settings page. A Security Policy is a set of security algorithms that will be used together during a security handshake. The OPC-UA server this connection is intended for must support the chosen security policy. The Message Security Mode and the Security Policy specify how to secure messages sent via this connection. None - No security is applied. Sign - Messages are signed but not encrypted. Sign And Encrypt - Messages are signed and encrypted. A connection can be set to Enabled or Disabled. Disabled connections have their settings preserved but no actual connection is made and the server will not show up in the OPC Server Browser.
Port
Security Policy
Enabled
Authentication If a username and password are specified then they will be used as a user identity token when connecting to the specified OPC-UA server.
2012 Inductive Automation
Gateway Configuration
100
The internal OPC-UA server provided by the OPC-UA module uses an Ignition security profile to govern who can connect to it. This can be configured in the OPC-UA module settings section. 3.8.2.2 Connecting to OPC Classic (COM)
Important
Classic OPC is based on COM, which is a technology in Microsoft Windows. Therefore, the information in this section only applies to Ignition gateways installed on Windows. For other operating systems, OPC-UA must be used.
Introduction
The OPC-COM module provides the ability to connect to OPC servers that only communicate using the older COM based OPC-DA standard. If you have an OPC server that is not capable of accepting OPCUA connections and you need to talk to a PLC for which Ignition has no supported driver, then you'll have to use the OPC-COM module to make your device data available in Ignition. Connections to OPC servers will be held open while the Ignition gateway is running. All subscriptions to the server will use the same connection. This section provides a brief walk-through of how to set-up a new Local or Remote OPC-DA server connection using the COM module. Due to the complications that Windows DCOM security settings can cause, this set-up guide is followed by the Troubleshooting OPC-COM Connections section that deals with an overview of how to deal with a faulted server connection due to DCOM security settings as well as other possibilities.
Gateway Configuration
101
6. All of the settings for the server connection are rather straight forward and each property has a description of its functionality. Most of these settings should be fine when left at their default values. The only setting that could possibly give you some trouble is the ProgId. If you selected your OPC server from the list on the Choose OPC-DA Server page then this will be filled in for you. However, if for whatever reason your server wasn't listed and you chose the Other Server option then you will have to know the ProgId for your server and specify it here. The ProgId is used to look up the CLSID of the OPC Server in the Windows Registry and without this a connection cannot be made. 7. When you are finished fine tuning these settings click Create New OPC Server Connection. You
Gateway Configuration
102
will be redirected to the OPC Server Connections page and your new server connection should be listed. The status of your connection will read Connected if Ignition was able to successfully connect to the third party OPC server. Connection is Faulted In the case where your connection status is reporting Faulted, the troubleshooting process begins. As previously stated, configuring the DCOM settings on your machine can be a headache. The Troubleshooting OPC-COM Connection section is an attempt to ease the process of determining why your connection is faulted and how to go about fixing the issue. If after exhausting the options presented to you there you are still having issues getting you server connection up, give our Inductive Automation tech support line a call and one of our representatives will be happy to assist you.
3.8.2.3
Troubleshooting OPC-COM Connections This section is aimed at providing you with a list of common OPC-COM connection problems with their possible solutions. It would be impossible to give an exhaustive list of everything that can go wrong but this should give you a good start on the troubleshooting process. If you do not see your problem listed and your connection status is faulted, try following the steps outlined in the "Ignition Server DCOM Settings and OPC Server DCOM Settings sections. Common Problems: OPC server is not listed in Choose OPC-DA Server list when first creating a connection There are some cases in which an OPC Server that is installed will not show up in the generated list. This list is generated by the OPC Server Enumerator which is part of the OPC Core Components, so when a server you have installed on the machine does not appear in this list it is likely due to the OPC Core Components not being installed correctly. Try reinstalling the Core Components and going through the process of creating a new server connection in Ignition again. If the server still does not appear and you have the ProgId (or the CLSID for a remote connection) for the OPC server, you can just select the Other Server option and then click Next. In this situation you will have to enter the ProgId manually on the New OPCDA Server page. With all the correct information about the OPC server we can sometimes still make a valid connection to the OPC Server even when it is not detected automatically. This however is rare. Most of the time when the server is not detected, any connection attempts Ignition makes will fail.
Connection status is Connected but data quality is bad or the connection goes Faulted after trying to read tag data Usually this occurs when the DCOM settings for the machine on which Ignition is running are not correctly configured. DCOM connections go in both directions. Ignition must be able to send requests to the OPC server and the OPC server must also be able to callback to Ignition. If the DCOM settings on the Ignition server are not configured correctly those callbacks will fail and the server connection that initially had a status of Connected will either fault or all the tags that you have configured will come back with bad quality.
2012 Inductive Automation
Gateway Configuration
103
This is a problem that can affect both local and remote server connections. Follow the steps outlined in the Ignition Server DCOM Settings section to ensure that you have correctly configured the DCOM security settings on the Ignition server machine.
Ignition launches second instance of an already running OPC server and is unable to see any data It is important to note that Ignition runs as a service under the Windows System account. This can cause some issues with OPC servers that are meant to run interactively, meaning they run under the user account that is currently logged on. When Ignition attempts to make a connection to the OPC server it will attempt to find an instance running under the same account and if it doesn't find one it will launch its own instance under the System account. Even if there are other instances running, Ignition will choose the one that was launched under the System account for its connection. Many OPC servers maintain an instance running under the interactive user account that has been configured by the user and maintains all of the device connection information. When Ignition launches a new instance, this configuration information is lacking and none of the desired data can be seen or accessed. To get around this problem you must specify in the DCOM settings for the OPC server that it always identify itself with the interactive user. Essentially this will force Ignition to use the currently running instance of the OPC server. Setting OPC server to run as Interactive User: 1. The DCOM settings are found in the Component Services manager. Right click the entry for your OPC server under the DCOM Config folder and select properties from the popup menu. 2. Select the Identity tab, select the option that reads The interactive user then click OK. 3. Close out of component services and kill any extra instances of the OPC server you see running in the Task Manager 4. Go edit and save the OPC server connection in the Ignition Gateway.
Faulted status with E_CLASSNOTREG error reported on OPC connections status page This is almost always caused by the OPC Core Components not being installed correctly. Download and install the correct version(s) for your system(s) from the OPC Foundation (www. opcfoundation.org). Remember, if you are making a remote connection you must install these components on both the Ignition server as well as the machine on which the OPC server is running.
DCOM Settings: Ignition Server DCOM Settings Follow these steps to open up the DCOM security settings on the machine that is running Ignition. 1. Open up Windows Component Services, located in the Administrative Tools section of the Control panel. 2. Browse down through the Component Services tree until you see My Computer, right click and
Gateway Configuration
104
select Properties. 3. We want to focus on the COM Security tab. There are two sections, Access Permissions and Launch and Activation Permissions. Each section has an Edit Limits... and Edit Defaults... button. You must add the ANONYMOUS and Everyone accounts under each of the four areas making sure that the Allow option is checked for each of the permission settings. If you skip adding both of these to either the limits or defaults areas under either of the two sections there is a good chance your connection will not be successful. 4. You can also try setting the Default Authentication Level to None and the Default Impersonation Level to Identify on the Default Properties tab. This isn't always necessary but it can sometimes help.
OPC Server DCOM Settings Follow these steps to open up the DCOM security settings on the machine that is running the OPC server 1. Open up Windows Component Services, located in the Administrative Tools section of the Control panel. 2. Browse down through the Component Services tree until get to the DCOM Config folder. Locate the entry for your OPC server that you wish to make a connection to, right click and select properties. 3. Click the Security tab and you will see three sections, Launch and Activation Permissions, Access Permissions, and Configuration Permissions. There are two options to choose from for each section. If you already added the ANONYMOUS and Everyone accounts to the COM Security section from the Ignition Server DCOM Settings section then you can go ahead and just select the Use Default option for each of the three areas. The second option is to edit each of the groups that have Customize selected. You will have to add both the ANONYMOUS and Everyone accounts with all privileges. 4. Now select the Identity tab. You will notice that you can choose which account you want to run the OPC server under. Select the Interactive User option. This ensures that if Ignition launches an instance of the OPC server that it will be run under whichever user is currently logged into the system.
3.8.3
Gateway Configuration
105
3.8.4
3.8.4.1
Authentication
Authentication Profile Allowed Roles The Authentication Profile that the OPC-UA module will use to authenticate incoming connections against. Roles within the given Authentication Profile that are allowed to connect to the server. Multiple roles should be separated by a comma, for example, Administrator,user,manager. If checked this will allow anonymous connections to the server.
Server
Server Port Endpoint Address The port the OPC-UA module runs on. Overrides the address that will be returned in the endpoint URL during a GetEndpointsRequest from a client. This is useful if the server machine has a VPN connection or multiple adapters and is returning the wrong address. 3.8.4.2 Adding a New Device To add a new Device go to the "Devices" section of the OPC-UA module configuration in the Ignition Gateway. Click "Add a Device..." and you will be taken to a page where you can select the driver to use. Choose your driver and click the "Next" button. "General" settings common to all devices are as follows: Device Name The user-defined name for this Device. The name chosen will show up in OPC Item Paths and under the "Devices" folder on the OPCUA server. The Device Name must be alphanumeric. Amount of time (in milliseconds) before a browse operation on this device times out. Amount of time (in milliseconds) before a read operation on this device times out. Amount of time (in milliseconds) before a write operation on this device times out. Only devices that are enabled will appear in the "Devices" folder of the OPC-UA server and thus have their tags available for use.
3.8.4.3
Verifying Device Connectivity Device connectivity can be verified either in the "Devices" section under the OPC-UA Server section, The Overview section of the Status page in the "Device Connections" bubble, or in the OPC-UA Server section of the Status page.
Gateway Configuration
106
3.8.4.4
Drivers
Communication Timeout
Concurrent Requests
Gateway Configuration
107
Communication Timeout
Communication Timeout
Connection Path
Gateway Configuration
108
Communication Timeout
Connection Path
Gateway Configuration
109
Module User Manual for more information. Connection Path Format: 1,<1756-DHRIO slot number>,<1756-DHRIO channel>,<DH+ node number> The valid range for the 1756-DHRIO slot number is between 0 and 16 but depends on the chassis size. The 1756-DHRIO channel is either 2 for channel A or 3 for channel B. The DH+ node number range is from 00 to 77 octal. For a more in depth explanation of connection paths please read: Allen Bradley Connection Paths Explained
Connections to ControlLogix, CompactLogix, PLC-5, MicroLogix and SLC Allen-Bradley processors through a ControlLogix Gateway require a connection path. The connection path is unique to your setup and is dependent on what modules the connection is being routed through. With there being nearly an endless number of ways to route your connection from device to device it is impossible to give an example of every possible connection path, but in general there is a pattern to how the connection path is specified.
Gateway Configuration
110
are using. You can only move in two directions once you are "in" a module: out to the back plane, or out through the module port/channel. Ethernet modules have ethernet ports and an IP address; ControlNet modules have ControlNet Ports and ControlNet addresses; DHRIO modules have channels and station numbers. Below is a list of different kinds of modules and what numbers you specify in the connection path when you are exiting or entering those modules. When in a module, an entry of 1 will always take you to the backplane. ENET, ENBT, and EN2T: Exiting 1 = Backplane 2 = Ethernet Port Entering IP Address CNB: Exiting 1 = Backplane 2 = ControlNet Port Entering ControlNet Address DHRIO Exiting 1 = Backplane 2 = DH+ Channel A 3 = DH+ Channel B Entering DH+ Station Number (an octal value between 0-77) You use these numbers to specify how to move out of the module, then you specify where you are moving to by either specifying the DH+ station number, ControlNet address, or the IP address of another ethernet module. Your connection path will always be an even number of entries due to the fact that you always move in two steps: out of a module and then in to another module. So if your connection path ends up with an odd number of entries you have missed a step somewhere and you'll have to go back and trace the path again. Some examples have been included to help illustrate the process of tracing a connection path. The first three examples illustrate how to build your connection path when going from one ControlLogix Gateway to another. The last example shows connecting through a ControlLogix Gateway to 3 different SLC 5/04 devices via DH+.
ControlNet Example
Gateway Configuration
111
ENBT Example
Gateway Configuration
112
DHRIO Example
Gateway Configuration
113
Gateway Configuration
114
The generic simulator provides a variety of tags that offer different data types and value generation styles. For example, there are ramps, sine waves, and random values. Additionally, there is a set of static writable tags whose values will persist while the device is running. There are no configurable settings for the generic simulator.
Simulator tags
ReadOnly - static values that do not change for read only purpose ReadOnlyBoolean1 - false ReadOnlyBoolean2 - true ReadOnlyShort1 - 1
Gateway Configuration
115
ReadOnlyShort2 - 2 ReadOnlyInteger1 - 1 ReadOnlyInteger2 - 2 ReadOnlyLong1 - 1 ReadOnlyLong2 - 2 ReadOnlyFloat1 - 1.1 ReadOnlyFloat2 - 1.2 ReadOnlyDouble1 - 1.1 ReadOnlyDouble2 - 1.2 ReadOnlyString1 - "ABCDEFG" ReadOnlyString2 - "ZYXWVUT" Writeable - static values that you can read/write to, initial values below WriteableBoolean1 - false WriteableBoolean2 - false WriteableShort1 - 0 WriteableShort2 - 0 WriteableInteger1 - 0 WriteableInteger2 - 0 WriteableLong1 - 0 WriteableLong2 - 0 WriteableFloat1 - 0 WriteableFloat2 - 0 WriteableDouble1 - 0 WriteableDouble2 - 0 WriteableString1 - "" (empty string) WriteableString2 - "" (empty string) Random - Random values updating at some rate, they follow Java Random(rate) - rate is the seed RandomBoolean1 - 10 sec RandomShort1 - 5 sec RandomInteger1 - 1 sec RandomLong1 - 2 sec RandomFloat1 - 10 sec RandomDouble1 - 10 sec Sine - Different sine waves with frequency, amplitude and offset (listed in that order) Sine1 - 0.1, 100.0, 0.0 Sine2 - 0.01, 50.0, -25.0 Sine3 - 0.02, 10.0, 10.0
Gateway Configuration
116
Sine4 - 0.04, 100.0, 0.0 Sine5 - 0.08, 100.0, 0.0 Ramp - Ramp signals starting from 0 going up to some value at the specified rate. When they reach their upper limit, they are reset to zero. Ramp1 - 0 - 100 @ 10 ms Ramp2 - 25 - 75 @ 100 ms Ramp3 - 0 - 100 @ 50 ms Ramp4 - 0 - 100 @ 25 ms Ramp5 - 0 - 100 @ 12.5 ms Realistic - Values determined by adding a random number (between -1 and 1) to the current value. Realistic1 - -50 - 50 @ 500 ms Realistic2 - -50 - 50 @ 1000 ms Realistic3 - -50 - 50 @ 1500 ms Realistic4 - -50 - 50 @ 2000 ms Realistic5 - -50 - 50 @ 2500 ms
The SLC simulator driver creates a simple device whose address structure mimics a basic SLC structure. There are currently no configurable parameters.
3.8.4.4.3 Modbus Drivers 3.8.4.4.3.1 Modbus Ethernet
The generic Modbus driver allows the Ignition OPC-UA server to communicate with any device that supports Modbus TCP protocol. The Modbus driver can connect directly to devices that support Ethernet communications. It can also connect to Modbus devices through a gateway. It is important to only add one Modbus device in the Ignition Device List per IP address. When communicating to multiple Modbus devices through a gateway each with a unique unit ID, either include the unit ID in the Modbus specific address or set it in the address mapping for the device. See below for more information of each method.
Properties
Hostname The Hostname value is the IP Address of the Modbus device.
Communication Timeout After sending a request to the Modbus device, the Communication Timeout setting is the amount of time in milliseconds to wait for a response before treating it as a failure. TCP Port The TCP port to use when connecting to a Modbus device. The Modbus TCP port specified in the Modbus specification is 502, but it can be changed to a different port.
Gateway Configuration
117
Maximum Holding Registers per Request Maximum Input Registers per Request Maximum Discrete Inputs per Request Maximum Coils per Request Use Zero Based Addressing
Some Modbus devices cannot handle the default of requesting 125 Holding Registers in one request. To accommodate this limitation change this setting to the maximum number of Holding Registers the device can handle. Some Modbus devices cannot handle the default of requesting 125 Input Registers in one request. To accommodate this limitation change this setting to the maximum number of Input Registers the device can handle. Some Modbus devices cannot handle the default of requesting 2000 Discrete Inputs in one request. To accommodate this limitation change this setting to the maximum number of Discrete Inputs the device can handle. Some Modbus devices cannot handle the default of requesting 2000 Coils in one request. To accommodate this limitation change this setting to the maximum number of Coils the device can handle.
The Modbus specification states that Modbus addresses are to be zero based. Meaning Modbus addresses start at 0 instead of 1 and to read a value from Modbus address 1024, 1023 is sent to the device. When connecting to devices that do not adhere to zero based addressing, make sure this option is not selected. This will cause 1024 to be sent to the device to read Modbus address 1024. Reverse Numeric Word When reading and writing 32bit values from/to a Modbus device, the low word Order comes before the high word. By checking this option, the high word will come before the low word. The Modbus specification does not include a section for reading and writing 32bit values and as a result device manufacturers have implemented both methods. Reverse String Byte When reading and writing string values from/to a Modbus device, the low byte Order comes before the high byte. By checking this option the high byte will come before the low byte. If reading a string value from a device should read ABCD but BADC appears in Ignition then check this option. Right Justify Strings Strings stored in a Modbus device may contain leading spaces or trailing spaces. This can produce unwanted results so that Modbus driver removes spaces or zeros when reading string values. By default, left justify string handling will be used when reading and writing strings. By checking this option, right justify string handling will be used.
Gateway Configuration
118
the device and convert data from decimal to BCD when writing to the device. HRBCD for Holding Register with BCD conversion HRBCD32 for 2 consecutive Holding Registers with BCD conversion IRBCD for Input Register with BCD conversion IRBCD32 for 2 consecutive Input Registers with BCD conversion To accommodate other data encoding commonly used by Modbus supported devices, the following designators are available for Modbus specific addressing. HRF for 2 consecutive Holding Register with Float conversion. HRI for 2 consecutive Holding Register with 32 bit integer conversion. HRUI for 2 consecutive Holding Register with 32 bit unsigned integer conversion. HRUS for Holding Register with 16 bit unsigned integer conversion. IRF for 2 consecutive Input Register with Float conversion. IRI for 2 consecutive Input Register with 32 bit integer conversion. IRUI for 2 consecutive Input Register with 32 bit unsigned integer conversion. IRUS for Input Register with 16 bit unsigned integer conversion. To read or write string values from/to a Modbus device, the following designation is available for Modbus specific addressing. HRS read or write consecutive Holding Registers as a string value. Note that there are 2 characters for each word and the order of which character comes first is controlled by the Reverse String Byte Order device setting as described above. Because two characters are stored in a word, the string length must be an even number of characters. HRS FORMAT: HRS<Modbus address>:<length> Examples:
[DL240]HR1024 Read 16bit integer value from Holding Register 1024. [DL240]HRBCD1024 Read 16bit BCD value from Holding Register 1024. [DL240]IR512 Read 16bit integer value from Input Register 512. [DL240]C3072 Read bit value from Coil 3072. [DL240]IR0 Read 16bit integer value from Input Register 0. [DL240]HRS1024:20 Read 20 character string value starting at Holding Register 1024.
The Modbus unit ID can also be specified by prepending it to the Modbus address. For example, to access Modbus unit ID 3 and read HR1024 the full OPC path is [DL240]3.HR1024. The Modbus specification does not support bit level addressing but it can be specified in the OPC Item Path. Please note that this only applies to reading bits of words and does not apply to writing bit values. Example:
[DL240,bit=7]HR1024
Address Mapping
Because it can be very tedious manual entering OPC Tag information one-by-one, the driver has an
2012 Inductive Automation
Gateway Configuration
119
address mapping feature. This allows entering blocks of common addresses and the driver will create the individual addresses and display them in the OPC browser. Another benefit of address mapping is the addresses inside a device can have a different numbering scheme than the Modbus address. The Direct Automation DL240 is a perfect example of this. Address V2000, capable of holding a 16 bit integer, is Modbus Holding Register 1024. In addition, the DL240 addressing is in octal meaning there are no 8 or 9s. The sequence of addresses go: V2000, V2001, V2002, V2003, V2004, V2005, V2006, V2007, V2010, V2011.... V3777. This is not very straight forward. Below details how to map the DL240 address range V2000 to V3777 in octal to Modbus Holding Register addresses 1024 to 2047. Also, notice the Radix setting that in this example being equal to 8 causes the addresses to be in octal (also known as base 8). Note that mappings for string data types cannot be entered. Strings can only be read or written using Modbus Specific Addressing. See above for more details.
Once this mapping has been entered and saved, the OPC browser or the Quick Client will show all the DL240 addresses from V2000 to V3777 in octal.
Gateway Configuration
120
Example
Gateway Configuration
121
When communicating to multiple devices through a Modbus gateway where the gateway only has one IP address, it is not recommended to add multiple Modbus devices with the same IP address. Only one Modbus device should be added to the Ignition OPC-UA Server device list for the gateway and to specify the different unit IDs in teh address mapping. The unit ID is specified for each entry in the address mapping for the Modbus device. Notice in the example address mapping below, that the Prefix, Start, End, Modbus Type and Modbus Address can be the same for two entries provided that the Unit IDs are different.
Gateway Configuration
122
Now when browsing the Modbus device, the unit ID will show as a folder and The OPC tag path will include the unit ID as shown below. This only happens when more than one unit ID is specified in the address mapping else the unit ID will be eliminated.
Modbus doesn't support reading and writing to any other memory types other than bits and 16 bit words. This is not very useful when reading from or writing to float point or 32 bit integers. To get around this the Modbus driver has been designed to read 2 consecutive 16 bit words and encode it into the desired data
Gateway Configuration
123
type. The Modbus address mapping below details how to map float point addresses starting at 1024 and ending at 1030. With the Step check box selected, the addresses on the Ignition side will be index by 2. In this case R1024, R1026, R1028 and R1030 will be created. Because the Modbus Type of Holding Register (Float) is selected, the driver will read two consecutive 16 bit words and convert it to a floating point value. It will also index the Modbus Address by 2 for each entry. In this case, R1024 will read from Modbus addresses 1024 and 1025 and convert them into a floating point value. When writing, the reverse of converting a floating point value into two 16 bits words is done before sending them to the device.
This shows what appears in the OPC Browser. Notice that the numbering is index by two and that it matches the Modbus address. With some devices, this will allow the addresses appearing in the OPC Browser to match the addresses in the device.
Gateway Configuration
124
The UDP and TCP drivers are strictly passive listeners. The UDP driver is configured to listen to one or more ports on a given IP address. The TCP driver is configured to connect to one or more ports on a given IP address.
Gateway Configuration
125
Rules are configured that dictate how the incoming data is interpreted.
Properties
General Device Name Browse Timeout Read Timeout Write Timeout Enable Device The name to give to the device using this driver. This is will appear in the Devices folder when browsing the OPC-UA server. Amount of time before a browse operation times out. Amount of time before a read operation times out. Amount of time before a write operation times out. Whether or not this device is currently enabled. Disabled devices will not make a connection attempt.
Connectivity Ports On the UDP driver this will be the port(s) to listen on. On the TCP driver this will be the port(s) to connect to. Separate multiple ports with a comma. On the UDP driver this will be the IP address to listen to. On the TCP driver this will be the IP address to connect to.
IP Address
Message Message Delimiter Sets the method used to determine how much or what data length constitues a full Type "message". Packet Based - Assumes that whatever arrives in one packet, regardless if length or content, is the message. Character Based - Content is appended to a message buffer until the given character arrives, at which point the contents of the buffer are considered the message.
Gateway Configuration
126
Fixed Size - Content is appended to a message buffer until some fixed number of bytes is received, at which point the contents of the buffer are considered the message. Message Delimiter If the message delimiter type is "Character Based" then this shall be the character used to identify a message. If the type is "Fixed Size" than this shall be the size used to identify a message. The number of fields within a message must be fixed. This property dictates how many fields will be present in each message. When the number of fields received does not match the designated count all nodes will receive quality BAD_CONFIG_ERROR. The character(s) that are to be used as field delimiters. For example, the message "a|b|c|d" with a field delimiter of "|" (no quotes) would be split into four fields: "a", "b", "c", and "d". The field count would have to be set at 4.
3.8.4.4.5 Siemens Drivers 3.8.4.4.5.1 Overview
Field Count
Field Delimiter
The Siemens Drivers Module provides support for connecting to S7-300, S7-400, and S7-1200 PLCs via TCP/IP using the S7 protocol. For more information on configuring tags see Addressing.
3.8.4.4.5.2 Addressing
The S7 protocol does not support browsing so all tags from the device must be configured as SQLTags in the Ignition designer. This can be done either manually, as needed, or by importing in bulk using the SQLTags CSV import functionality. When creating a tag, the "OPC Item Path" field will be of the format: "[device_name]address", without the quotes, where device_name is the name given to the device during configuration and address is an S7 address, the format of which is described in the following text.
Tag addresses are made up of three different components: Area, DataType, and Offset. Area DataBlock s Inputs Outputs Flags Timers Counters DataType Bit Byte Char Word Syntax DBn, I Q M T C Syntax X B C W Signedness N/A Unsigned Signed Unsigned
Gateway Configuration
127
To form an address you combine the desired Area and DataType with an Offset into that area. Examples: IB0 IW0 DB500,DI8 ISTRING24.50 Inputs area. IX20.3 T0 Timers). C0 Counters). Byte at Offset 0 in the Inputs area. Word at Offset 0 in the Inputs area. DInt at Offset 8 in DataBlock 500. A String of length 50 starting at offset 24 in the Bit 3 of the Byte at Offset 20 in the Inputs area. Timer at offset 0 (No DataType is specified for Counter at offset 0 (No DataType is specified for
It is important to note that offsets are absolute. IW0 and IW1 share a byte. To get 2 consecutive, nonoverlapping words you would need to address IW0 and IW2. Bits Bits are addressed by using the Bit DataType (X) and appending .bit to the end, where bit is in the range [0-7]. When addressing a Bit at a given offset, that offset is always treated as a Byte.
Strings Strings are assumed to be in the S7 string format and have a max length of 210.
Timers Timers are scaled up to a DWord and converted from S5 time format so they can represent the time in milliseconds without requiring any multipliers. When you write to a timer it is automatically converted from milliseconds into S5 time format for you. A DataType is not specified when accessing Timers.
Counters Counters in the PLC are stored in BCD. The driver automatically converts to/from BCD for you and exposes any counter tags as UInt16 values. A DataType is not specified when accessing Counters.
3.9
3.9.1
SQLTags
SQLTags Configuration Overview
While the goal of SQLTags is to create an easy yet powerful tag model, the variety of options and terminology can sometimes make configuration confusing. The goal of this chapter is to provide a clear overview of the SQLTags landscape, and provide a clear guide to the configuration of various
Gateway Configuration
128
architectures. It will be useful to have a working knowledge of what SQLTags are and how they executed, described in the section What is a SQLTag? in the Project Design chapter.
Gateway Configuration
129
Internal SQLTags Provider As mentioned above, the internal SQLTags provider stores the tag configurations in the Ignition gateway. The tags cannot be accessed outside of that particular gateway, but in return the efficiency is much greater, as values do not need to be written to the database and polled. It is possible to create multiple internal providers per gateway.
3.9.2
3.9.3
3.9.3.1
Settings
The internal tag provider only has one additional setting: Default Database The database connection that will be used anytime a tag needs to access the database, such as executing a SQL Query based Expression tag. 3.9.3.2 Database Provider The database provider stores SQLTags in an open format in the specified database. This provider type does not execute tags- it simply models tags and monitors values driven by a different tag provider elsewhere, such as an Ignition gateway using the database driving provider or FactorySQL.
Settings
Database The database connection where the SQLTags configuration is stored. Poll rate The rate (in milliseconds) at which to poll the tag database for changes in tag value or configuration. Poll overlap The amount of time to overlap polls by. If set to 0, the config scan will look for changes only since the last execution. However, on databases that do not support millisecond resolution or are performing less-than-optimally, this could result in missed changes. This setting will expand the window in order to avoid missing these changes.
3.9.3.3
Database Driving Provider The database driving provider extends the database provider adding the ability to execute tags. The values will be stored to the SQLTags tag database in the specified database.
Gateway Configuration
130
Availability
The database driving provider is a feature of the SQL Bridge module. It is only available when the module is installed.
Settings
The driving provider shares most of the settings of the database provider. However, it adds some key properties for driving and browsing. Driver name The unique name of this driver. Since the tags are stored in a central database, there may be multiple providers and drivers operating on them. This name will be used to identify this driver instance, and the tags that it executes. While the driving provider will read all of the tags stored in the database, it will only execute those tags that are assigned to it. Enable browsing (of OPC servers) Allows remote browsing of the OPC servers available to this driver over TCP/IP. This allows other gateways to remotely browse and add tags assigned to this driver into the central database. Browse port The port to listen on for remote connections. This port must not be in use by any other entity on the machine. Also, each driving provider that wishes to support browsing must have its own port. Browse address The IP address/network name that remote gateways will use when browsing. Therefore, care must be taken that the address is available from the gateways that will try to connect. Also, since it is used for access by remote systems, it should not be the loopback address (localhost or 127.0.0.1). The browse address and port will be stored in the SQLTags database so that other gateways can easily look them up. After the settings are configured, you should immediately see the driver name in the OPC browse list for the external provider on other systems looking at the same database. Note: When using remote browsing, make sure that the local firewall has an exception for the port that is used to listen. Otherwise, remote machines will not be allowed to connect.
3.9.3.4
Important
The information provided here requires an understanding of SQLTags and how they work. It is an advanced reference to how the tables of external SQLTags providers are structured and an overview of the concepts of tag execution. If you are a new user it is suggested that you read the SQLTags section that resides in the Project Design area of the Ignition user manual first.
Gateway Configuration
131
1. sqlt_core - The core tag information table, has one entry per tag. Defines fundamental properties like data type, as well as the current value of the tag. Is monitored by the provider to determine value and configuration changes. 2. sqlt_meta - Provides additional properties for tags. Only consulted when tag configuration has changed. 3. sqlt_as - Provides alert state configuration for tags which utilize alerting. 4. sqlt_perm - Provides custom permission settings for tags set to use them.
Operations Tables 5. sqlt_sc - Contains the definitions of scam classes, which distate how tags are executed. 6. sqlt_sci - Contains an entry for each scan class from sqlt_sc, for each driver currently driving tags. Used to verify that drivers are properly executing. 7. sqlt_drv - Contains an entry for each SQLTags driver. Only really used for browsing tags. 8. sqlt_err - Contains errors that have occurred executing tags. 9. sqlt_wq - The "write queue". All write requests are entered into this table, where the driver will detect and execute them. The result will be written back by the driver, and will be noticed by the provider.
Gateway Configuration
132
selecting the tag values (or any information desired) from the appropriate table where one of the indexed timestamp columns is greater than the last checked time. The provider/driver will then store that time in memory as the last check, and will use it in the next poll.
Table Reference
The following is a reference list for the table structures of all the tables listed above. In general, all integer time values are in milliseconds. sqlt_core Column id name path drivername tagtype datatype enabled accessrights scanclass intvalue float value stringvalue datevalue dataintegrity deleted valuechange configchange sqlt_meta Column tagid name intval floatval stringval sqlt_as Column id statename
Data Type integer string string string integer / TagType enum integer / DataType enum integer (0 or 1) integer / AccessRights enum integer integer double string datetime integer (0 or 1) datetime datetime
Notes Auto-incrementing, unique id for the tag Name of tag Folder path, in form of "path/to/" Name of driver responsible for executing tags The type of tag - ie. OPC, DB, etc. The type of data provided by the tag Whether the tag is enabled for execution Access permissions for the tag ID of the scan class for the tag Value column used if tag has integer data Value column for float/real data Value column for string data Value column for date data Whether the tag is deleted or not The last time that the value changed The last time that the tag's config changed
Notes ID of tag that the property belongs to The well-known property name Value, if property has integer type Value if property has float type Value, if property has string type
Gateway Configuration
133
Column severity low high flags lotagpath hitagpath timedeadband timedbunits sqlt_perm Column tagid rolename accessrights
Data Type integer / Severity enum double double integer / Alert Flags string string double integer / TimeUnits enum
Notes Low setpoint High setpoint Flags that dictate how the state acts. Path to tag that provides low setpoint, if low driven flag is set Path to tag that Provides high setpoint, if high driven flag is set Time deadband value Time deadband units
Notes ID of tag that the permission belongs to Name of the role that this permission is applied to Access rights for the given role on the given tag
sqlt_drv Column name ipaddr port sqlt_sc Column id name lorate hirate drivingtagpath comparison comparevalue mode staletimeout leaseexpire configchange
Notes Name of the tag driver Address of browse server, blank or null if browsing isn't available Port of browse server
Notes Auto-incrementing unique id Name of the scan class The slower rate to run at, in milliseconds. Only rate used if scan class mode is direct Higher rate, in ms. Only used if scan class is driver or leased Path to tag to watch if mode is driven Value to compare driving tag to for driven mode
integer / Comparison enum Operation to apply to driving tag in driven mode integer / Scan class mode The mode of the scan class enum integer datetime datetime Time, in milliseconds, before scan class is determined to not be running The time that the lease should expire, if using leased mode The last time that the scan class has been modified
Gateway Configuration
134
Notes The id of the scan class represented The driver executing this instance Last time that the scan class executed The rate of the scan class at last execution Time, in ms, that the scan class took to execute Writes to OPC performed during last execution Value updates from OPC processed in last execution Writes to DB performed during last execution Value updates from the database processed during the last execution The delay between when the scan class should have ran and when it actually ran for the last execution The average duration time of the scan class, in ms The number of times the scan class has executed The next time that the scan class should execute
lastexecopcwrites integer lastexecopcreads integer lastexecdbwrites integer lastexecdbreads lastecexdelay avgexecduration execcount nextexec sqlt_wq Column id tagid intvalue fload value stringvalue datevalue responsecode responsemsg t_stamp sqlt_err Column objectid objectype lifecycleid msgtype integer integer integer integer datetime
Data Type integer integer integer double string datetime integer / Write Response enum string datetime
Notes Auto-incrementing unique id for the write operation ID of the tag to write to Value, if tag has integer data type Value, if tag has float or real data type Value, if tag has string data type Value, if tag has date data type The state of the write request. When created, the response code should be set to 2 - Pending Write error if operation failed The time that the write request was created
Data Type integer integer / Object Type enum integer / Lifecycle enum integer / Message Type enum
Notes ID of the object with the error The type of object. Used with objectid to identify the item that caused the message When the message was generated
Gateway Configuration
135
Notes The primary message Additional error ingormation When the message was generated
Enum Reference
Enums are well-known values that are stored as integers in the database Tag Type 0 OPC Tag 1 2 6 DB Tag Client Tag Folder Tag
Data Type 0 Int1 1 2 3 4 5 6 7 8 9 Int2 Int4 Int8 Float4 Float8 Boolean String DateTime DataSet
Data Quality 0 Bad Data from OPC 4 8 12 16 20 24 28 32 64 68 80 84 CONFIG_ERROR NOT_CONNECTED DEVICE_FAILURE SENSOR_FAILURE Bad, showing last value COMM_FAIL OUT_OF_SERVICE WAITING UNCERTAIN UNCERTAIN showing last value SENSOR_BAD LIMIT_EXCEEDED
Gateway Configuration
136
88 28 192 216 256 300 301 310 330 340 403 404 410 500 600 700
SUB_NORMAL SERVER_DOWN Good Data Good, with local override OPC_UNKNOWN Config Error Comm Error Expr Eval Error Tag exec error (fsql) Type conversion error Access Denied Not Found Disabled Stale Unknown (loading) Write Pending
Comparison Mode 0 Equal 1 2 3 4 5 Not Equal Less Than Less Than Equal Greater Than Greater Than Equal
Alert Flags 0x01 Low Exclusive 0x02 Low Infinite 0x04 High Exclusive 0x08 High Infinite 0x10 Any Change 0x20 Low Driven 0x40 High Driven
Gateway Configuration
137
3.9.4
3.9.4.1
SQLTags Historian
How SQLTags Historian Works SQLTags Historian gives you the ability to quickly and easily store historical data for your tags, and provides efficient querying of that data. Options for partitioning and deleting old data help ensure that the system stays properly maintained with minimal extra work. This section describes various aspects of how SQLTags Historian stores and queries data.
Historian Providers
The settings for SQLTags Historian providers are set in the gateway under SQLTags > Historian. Historian providers are automatically created and removed according to the configured database connections. By default they will be created with a one month partition size, and will not delete old data.
Data storage
As mentioned, the historical SQLTags values pass through the store and forward engine before ultimately being stored in the database connection associated with the historian provider. The data is stored according to its datatype directly to a table in the SQL database, with its quality and a millisecond resolution timestamp. The data is only stored on-change, according to the value mode and deadband settings on each tag, thereby avoiding duplicate and unnecessary data storage. The storage of scan class execution statistics ensures the integrity of the data. While advanced users may change the table according to their database to be more efficient (for example, using a compressed engine), Ignition does not perform binary compression or encrypt the data in any way. Table Partitioning Ignition has the ability to automatically break up data into different tables of fixed duration. This can help make data maintenance easier, by preventing tables from becoming too large. Tables can easily be deleted in order to prune old data, and the database is able to better optimize access to frequently retrieved rows. The built-in partitioning feature can be used with any database. It is important to note the difference between this feature and any partitioning options that the database might provide. Most modern databases offer their own faculties for defining "partitions", offering similar and greater benefits. While Ignition cannot use these features directly, advanced users may choose to
Gateway Configuration
138
apply these features on top of what Ignition currently offers. Data Compression As mentioned above, Ignition does not perform any binary compression on the data. That is, values are stored directly in standard database tables. However, in order to reduce the number of values stored, Ignition offers two different algorithms for pre-compressing the data (trimming unnecessary values). The two modes correspond to the value mode property of the tag: Discrete, and Analog. Discrete: The value uses a simple deadband, and is only stored when a new value is +/- the deadband value away from the previously stored value. Analog: The deadband is used to form a corridor along the trajectory of the value. A new value is only stored when it falls outside the previous corridor. When this occurs, the trajectory is recalculated, and a new corridor formed. See Historian Properties for more information about the difference between discrete and analog values.
Querying
While the data is stored openly in the database, the format does not lend itself well to direct querying. Instead, the Ignition platform offers a range of querying options that offer a tremendous amount of power and flexibility. In addition to simple on-change querying, the system can perform advanced functions such as querying many tags from multiple providers, calculating their quality, interpolating their values, and coordinating their timestamps to provide fixed resolution returns. Querying can be performed on tables and charts through the Historical Binding, and through scripting. 3.9.4.2 Configuring SQLTags Historian SQLTag Historian providers are configured at SQLTags > Historian. A historian provider is created automatically for each database connection, and will be removed if the connection is removed. Although enabled by default, the providers won't interact with the database unless data is logged to them.
General Settings
Enabled Whether the provider will be turned on and accept tag history data. If disabled, any data that is logged to the provider will error out and be quarantined by the store and forward engine, if possible.
Data Partitioning
SQLTags Historian can partition the data based on time in order to improve query performance. Partitions will only be queried if the query time range includes their data, thereby avoiding partitions that aren't applicable and reducing database processing. On the other hand, the system must execute a query per partition. It is therefore best to avoid both very large partitions, and partitions that are too small and fragment the data too much. When choosing a partition size, it is also useful to examine the most common time span of queries. Partition Length and Units The size of each partition. The default is one month. Many systems whose primary goal is to show only recent data might use smaller values, such as a week, or even a day.
Data Pruning
Gateway Configuration
139
The data prune feature will delete partitions with data older than a specific age. It is not enabled by default. Enable Monitor the partitions and drop those whose data is older than the specified age. Prune Age and Units The maximum age of data. As mentioned, the data is deleted by the partition, and could therefore surpass this threshold by quite a bit before all of the data in the partition is old enough to be dropped.
3.10
Security
Ignition uses the concept of role-based security throughout. Role-based security is the concept that each user may be assigned to various roles. Security policies are then defined in terms of these roles, rather than defined for specific users. This allows users to be reassigned, removed, and added without affecting the logic of the security policy. The users and their roles are defined in authentication profiles. An Ignition Gateway may have many different authentication profiles defined, each governing the security of different aspects of the Gateway. For example, logging into the Gateway configuration web interface might be governed by one authentication profile, while the security for a project is governed by another. There are many different types of authentication profiles that offer various features. For example, the Internal authentication profile offers the ultimate in ease-of-use: you simple define the users, their passwords, and the roles within the Ignition Gateway configuration web interface. In contrast, the ActiveDirectory authentication profile offers the power of integrating Ignition with a corporate security infrastructure. Users, passwords, and roles would be managed centrally by the IT department. Security policies can be defined for many different parts of the system. For example: You can alter the roles required to log into the Gateway configuration section You can define roles required to write to or even read from a SQLTag You can define roles required to view a Component. You can access the security system in a script to restrict the operation of the script to authorized users.
Gateway Configuration
140
automatically create the appropriate tables through your database connection. This is usually a good idea, as it makes the setup very easy. To administer the users and their roles, you'll have to interface directly with the database. This type of authentication profile is best when the ability to administer users from within a running client is a requirement. 3.10.2.3 Active Directory Authentication Profile The active directory profile type will communicate with a Microsoft Active Directory server through the LDAP protocol. Administration of the users and roles must be done through Active Directory's management tools. This authentication profile is a good choice when integration with a corporate authentication scheme is a requirement. To set up an active directory authentication profile, you must specify the host that is acting as your primary domain controller. You can also use a secondary domain controller in case the primary is unavailable. You'll also need to specify the name of the domain and credentials for the Gateway itself to use for authentication for when it queries the list of roles.
3.10.2.4 AD/Internal Authentication Profile The active directory/internal hybrid profile type combines the internal profile for role management, but uses Active Directory for authentication. This means that for any username/password combination, Active Directory gets to decide whether that user is a valid user, and if they are considered valid, then the Ignition Gateway looks internally for their list of roles. This type of authentication profile is very handy for projects that are required to integrate with IT's centrally managed security, but negotiating the management of roles with IT would be too cumbersome. 3.10.2.5 AD/Database Authentication Profile The active directory/database hybrid profile type uses the database authentication profile for role management, but uses Active Directory for authentication. This means that for any username/password combination, Active Directory gets to decide whether that user is a valid user, and if they are considered valid, then the roles for that user are retrieved from an external database connection. This type of authentication profile is very handy for projects that are required to integrate with IT's centrally managed security, but negotiating the management of roles with IT would be too cumbersome. The main reason one would choose this profile type over the AD/Internal profile is that by storing the roles in an external database, they can be managed outside of the Ignition Gateway's web configuration interface. Specifically, one can create screens using the Vision Module for role management, thus allowing security management from within a running Client.
Gateway Configuration
141
2. To manage users and passwords for logging into the Designer, you follow the same steps as in #1, except that you need to look at the Designer Role(s) field to see what roles are allowed to log into the designer. 3. To manage users and passwords for logging into a Vision Client, you go to the Configuration > Projects section. Look at the project in question and you can find its authentication profile listed there. 4. Now that you know what authentication profile you need to manage, you can find out what kind it is under the Security > Authentication section.
Now that you know what kind of authentication profile you're dealing with, you can learn how to manage the users, passwords, and roles for each. 1. Internal authentication profiles are the easiest to manage, because you do it all from within the Gateway's web configuration interface. Simply click on the manage users link to the right of the profile, and you can use the interface to add users, roles, and assign users to the various roles. 2. Database authentication profiles are typically used because you want to be able to manage the users and roles externally by reading and writing to an external database. Because this is the kind of thing a Vision Client does so well, this authentication profile type is often used for projects that require user management from within the Client application itself. 3. Active Directory authentication profiles are chosen because it is I.T.'s role to manage the users and groups. They have tools to do so, and this cannot be done from within Ignition. 4. AD/Internal Hybrid authentication profiles are a compromise between Active Directory and Internal profile types. Users and passwords are handled by Active Directory - a user must be able to authenticate correctly with the Active Directory service in order to log in. Roles, however, are managed internally, just like in the Internal profile type by clicking on the manage users link. To assign roles to a user, you add a user with the same username that Active Directory would authenticate with, and then assign any roles to them. 5. AD/Database Hybrid authentication profiles are a compromise between Active Directory and Database profile types. Just like the AD/Internal hybrid - active directory is used to handle the username and password verification. If a user authenticates correctly against active directory, their roles are retrieved from an external database connection, just like in the Database authentication profile type.
Gateway Configuration
142
3.11
Alerting
Alerting (also occasionally referred to as 'alarming'), is a core feature of the Ignition platform. Alerts are conditions that are evaluated with respect to a specific numeric datapoint. Most commonly, alerts are configured on a SQLTag or a Transaction Group item. Any given datapoint can have multiple conditions that might cause it to be considered "in alert". For example, you might configure an analog tag to be in alert if its value exceeds 50.0, or you might configure a discrete tag to be in alert if its value non-zero. Analog values can have multiple alert states configured for them. Each alert state defines a numeric range where it is considered active, and has a name and a severity. An alert state becomes active when the value of the datapoint falls within the range of the state. The alert state is said to clear when the datapoint moves outside of the range by at least the alert deadband, if the deadband is configured. When an alert state becomes active or clear, a message is generated and will be consumed by any configured alert storage profiles and alert notification profiles. The job of an alert storage profile is to store the record of when an alert state for a datapoint became active, when it cleared, and whether or not it has been acknowledged. Typically, this is done by recording the event as a row in an external database. An alert notification profile takes the messages from the alerting system and uses them to notify people of the event. This is typically done via sending an email. There are several types of alert notification profiles that provide different mechanisms for controlling how notifications are sent to various sets of users. Information about configuring alerts conditions can be found in Alert Properties under SQLTag configuration.
Filters
Both notification and storage profiles offer the ability to filter alert messages on a few basic parameters. Multiple profiles of each type can be created and configured differently in order to filter out different sets of alerts, if desired. The three text based filters, System, Path and State Name, can include wildcard parameters * (any characters) and ? (any single character).
Gateway Configuration
143
compressor system to a certain group of maintenance personnel, while alerts involving product temperature might go to a group of QC personnel. Or, you could differentiate recipients based upon the time of day to notify the personnel in the correct shift. The distribution list profile maintains a list of contacts and a list of groups. Each contact is a name, an email address, and a mapping of which groups the user belongs to. Each group defines an expression, which shares the syntax of other Ignition expressions, but can refer to properties of the alert. It is evaluated for each alert event that occurs, and messages that evaluate to TRUE are sent to the corresponding users.
3.12
Redundancy
Redundancy is an advanced feature of Ignition that provides a higher degree of fault-tolerance and protection from downtime due to machine failure. Using redundancy, two Ignition installations can be linked together, so that when one fails, the other takes over and continues executing. All of the clients connected will be redirected to the backup machine, and historical data will continue to be logged. There are a variety of design decisions that come into play when setting up redundant systems, so it is important to understand the available options, and how the pieces of the system function in a redundant setting. This chapter will start with key terminology that will be used heavily, and will then proceed to explain how the main parts of the system function. It will then explain the various settings available, and will finish up with an examination of a few common setups.
Gateway Configuration
144
Terminology
Here are some of the most common terms used in relation to redundancy. Activity Level The activity level describes what the Ignition installation is currently "doing". A node in a redundant pair will operate at one of three levels: Cold, Warm, or Active. In "cold", the system is doing a minimal amount of work. In "Warm", the system is nearly running at full level, in order to switch over quickly. Both of these levels imply that the other node is currently active. In "active", the system is the primary system, responsible for running all sub-systems. Node A node is an Ignition installation, set to be part of the redundant pair. There can be a master node, and a backup node. Active Node The active node is the Ignition installation that is currently at the "active" level, and is responsible for running. It is also described occasionally as the "responsible node". It can be either the master or backup node, even when both are available. For example, if the backup node becomes active after the master node fails, and the master comes back up but is set to manual recovery mode, the backup will continue to be active until it fails or the user switches responsibility back to the master. Master Node The node that is responsible for managing the configuration state. It is also generally expected to be the active node when available, though this is dependent on settings. It is therefore import to separate the ideas of the master node and the active node. Backup Node The node that communicates with the master and takes over when that node is no longer available.
Node Communication
The master and backup nodes communicate over TCP/IP. Therefore, they must be able to see each other over the network, through any firewalls that might be in place. All communication goes from the backup to the master node, by default on port 8750. Therefore, that port must allow TCP listening on the master machine. The port can be changed in the gateway redundancy settings page.
Configuration Synchronization
The master node maintains the official version of the system configuration. All changes to the system must be made on the master- the gateway on the backup will not allow you to edit properties. Similarly, the designer will only connect to the master node. When changes are made on the master, they are queued up to be sent to the backup node. When the backup connects, it retrieves these updates, or downloads a full system backup if it is too far out of date. If the master node has modules that aren't present on the backup, they will be sent across. Both types of backup transfers- "data only" and "full"- will trigger the gateway to perform a soft reboot.
Gateway Configuration
145
Status Monitoring
Once connected, the nodes will begin monitoring each other for liveliness and configuration changes. While the master is up, the backup runs according to the standby activity level in the settings. When the master cannot be contacted by the backup for the specified amount of time, it is determined to be down, and the backup assumes responsibility. When the master becomes available again, responsibility will be dictated by the recovery mode, and the master will either take over immediately, or wait for user interaction.
System Activity
When a node is active, it runs fully, connecting to any configured OPC servers, and communicating with devices. When it is not active, its activity level is dictated by the settings, either warm or cold. In "warm" standby, the system will run as if it were active, with the exception of logging data or writing to devices, allowing for faster fail-over. In "cold" standby, the system does not subscribe to tag values, and does not communicate with any device. This allows the system to standby without putting additional load on the devices and network. Fail-over will take slightly longer, as tags must be subscribed and initialized.
Historical Logging
Historical data presents a unique challenge when working with redundancy, due to the fact that it is never possible for the backup node to know whether the master is truly down, or simply unreachable. If the master was running but unreachable due to a network failure, the backup node would become active, and would begin to log history at the same time as the master, who is still active. In some cases this is OK because the immediate availability of the data is more important than the fact that duplicate entries are logged, but in other cases, it's desirable to avoid duplicates, even at the cost of not having the data available until information about the master state is available. Ignition redundancy provides for both of these cases, with the backup history level, which can be either "Partial" or "Full". In "full" mode, the backup node logs data directly to the database. In "partial" mode, however, all historical data is cached until a connection is reestablished with the master. At that time, the backup and master communicate about the uptime of the master, and only the data that was collected while the master was truly down is forwarded to the database.
Client Fail-over
All Vision clients connect to the active node. When this system fails and is no longer available, they will automatically retarget to the other node. The reconnection and session establishment procedures are handled automatically, but the user will be notified that they have been transferred to a different node, so that they can notify the system administrator that they system may need attention.
Gateway Configuration
146
1. It is best to start with a fresh install for the backup node. The current configuration of the backup node will be overwritten, so make sure that it does not contain anything valuable in it when enabling redundancy. 2. All system configuration relative to the master node must also resolve on the backup node. For example, OPC-UA connections and database connections must use addresses that resolve from both nodes, any OPC-COM servers must be installed and configured identically on both nodes, etc. With that in mind, setting up redundancy is fairly simple. Follow these steps to set up your redundant pair: 1. Turn off firewalls between the redundancy nodes. Redundant systems need TCP connectivity between each other on a variety of ports. Turning off software firewalls or adding special exception rules for each others' addresses is required. Specifically, The master node must be able to receive data on TCP/IP port 8750 (changeable in settings), and the backup node must be able to send outgoing data on that port. 2. Configure the master node. 2.1. Set mode to 'Master' under the Configuration > Redundancy in the gateway configuration. 2.2. It is advisable to turn off 'Auto-detect network interface' and to manually specify the address of the NIC (network interface card) to use for communication. 2.3. The addition settings are described in the next section, redundancy settings. 3. Configure the backup node 3.1. On the desired backup system, set the mode to 'Backup'. 3.2. Under 'Backup Node Settings', specify the address of the master node. Also verify that the port is correct under 'Network Settings'. 3.3. After saving, the system will connect to the master and will download a system backup, which will trigger a restart. After the restart is complete, the backup node should now be synchronized and in communication with the master. 4. Verify Redundancy Setup with the System Map. When you go to the status section of the gateway, the system map should show both connected nodes and should show their current states.
Redundancy Settings
Mode Independent - Redundancy is not enabled and this Ignition system runs as an independent node. Master - This is the master node, who listens for a connection from the backup node, and is in charge of managing system synchronization. Backup - This is the backup node, who will connect to the master and receive system updates. Standby Activity Level How the node operates when it is not the "active" node.
Gateway Configuration
147
Cold - perform minimal activities, do not connect to devices, etc. Purpose: minimize the load on the network and on devices. Warm - Connect to devices, subscribe to tags and set up all executing objects. Purpose: minimize fail-over time. Fail-over Timeout The time, in milliseconds, before the opposite node is determined to be unavailable and this node takes over. Startup Connection Allowance The time, in milliseconds, to wait on initial startup for a connection to be established before making a decision on the node's activity level. This is used to prevent unnecessary switch over caused by a node starting as active, only to connect and find that the other node is active, resulting in one of the nodes being de-activated. It is important to note that this setting can interfere with the Master Recovery Mode- if the master is active, it will always request the backup to de-activate. If this setting is low, or 0, the master will always become active before connecting to the backup, and thus "manual recovery" will not be possible.
Network Settings
Port For the master, the port to listen on. For the backup, the port to connect to on the master. Auto-detect Network Interface If true, the system will automatically select which network interface to use on the machine. If false, the system will bind itself to the interface of the specified address. Network Bind Interface The address to bind to if Auto-detect is false. Auto-detect HTTP Address When clients are launched, they are provided with a list of addresses that they may connect to. If this option is true, the list will be generated automatically. If false, they will be provided with the list specified. HTTP Addresses The list of addresses to give to the clients if auto-detect is turned off. These are the addresses that the clients will attempt to connect to, so the HTTP and HTTPS ports must match the configuration of the system in the Gateway Control Utility.
Gateway Configuration
148
Database Architectures
Single Shared Server
2012 Inductive Automation
Gateway Configuration
149
A single database server is used. The Ignition gateways will both use it, so it is expected to be available even when one of the nodes is not. For that reason, it almost always resides externally, on a separate server machine. This arrangement is the easiest to use with Ignition. A single database connection configured on the master will be replicated to the backup, and both nodes will use the connection as necessary. Clustered/Replicated Database Servers There is a wide variety of capabilities supported by the different brands of database servers. To obtain fault-tolerance on the database front, it is usually necessary to have some sort of cluster/replication system in place. However, it can be very import to examine how Ignition is using the databases, and what capabilities the clustering solution provides. For example, in many replication scenarios, the master database copies data to the backup. The backup can be used for read purposes, but new data inserted will not be replicated back to the master. Therefore, it is possible to have a failover connection to the backup database, so that clients will continue to receive data, but it would be necessary to run in partial history mode, so that the historical data was cached and inserted only to the master database. The failover connection would be set to standard mode, so the primary connection would be used when possible. In a more complete cluster environment, where writes to either node would be replicated, a stick y failover connection could be used with full history mode.
Pertinent Settings
When working with various database architectures, there are a few settings in various parts of the system that are important. Database connection settings - Failover Datasource Any database connection can have a failover datasource. If the main connection is unavailable, any queries executed on it will pass through to the secondary connection. In this way, a secondary database can be used when the first is not available, and the system will continue to function. It is important to note that everything passed through to the failover will function normally- no special considerations will be made. For example, the system won't cache data for the primary connection, it will forward it to the secondary. In cases where you want to allow reading from the secondary database, but not writing, you can set up another connection directly to the first database, with no failover, and set all of your write operations to use that. Clustering settings - History Mode The history mode dictates how history will be treated when the node is not active. If partial, the data will be cached, and only forwarded when the master node is available. This mode can be used to prevent data from being inserted into a backup database in some cases.
Gateway Configuration
150
If using system names (or domain names), verify that the name is resolving to the correct address by performing a ping. Verify that the firewall on the master is set to allow TCP traffic to the designated port. Verify that the backup is not connecting and then immediately disconnected for some reason. Viewing the error log in the gateway console section should show this. If errors are occurring at regular intervals, look at the message for an indication of what is happening. An example of a potential problem is when the failover time is set too low for the given network, which results in many socket read timeout exceptions, which in turn leads to many disconnect/reconnect attempts. If errors are occurring, but the cause isn't clear, contact Inductive Automation support.
Advanced Troubleshooting
A variety of loggers can be found under the gateway console section by going to "Levels" and searching for "Redundancy". By setting these loggers to a finer level, more information will be logged to the console. This is generally only useful under the guidance of Inductive Automation support personnel, though more advanced users may find the additional logged information helpful.
3.13
Mobile Module
There is very little setup involved with the mobile module. Usually the default settings should suffice with the exception of the Server Address setting.
Settings
Java Path This is the path to the Java executable on the Ignition Gateway server machine. The Java 6 JRE is required for the mobile module; it is NOT compatible with Java 7. A default value of java assumes that Java 6 is on the path and can be invoked merely with the java keyword. Client Memory The amount of space allowed for each mobile client that is launched. Mobile clients are virtual clients that are launched on the server. All of the work is done on the server and transmitted to the mobile device so keep in mind that more mobile clients means more memory and CPU consumption on the server. JVM Options Command-line JVM options to use when launching mobile client VM's. Multiple options are separated with spaces. This option is made available mostly for troubleshooting by technical support staff, but if you are familiar with java and comfortable with command-line arguments then you can specify ones you may find useful here. Environment Variables Here you can specify any environment variables in the format of NAME=VALUE. Idle VMs The number of client VMs to startup and wait for incoming mobile connections. These will start when the gateway is started and sit idle until a mobile connection is made. This should be left at the default value of 0 unless it is taking a long time to launch a mobile client. It's important to note that the VMs that are sitting idle are not connected to a project so it will still take time to load the selected project. Server Address This is the address to use when launching from the QR code on the launch page. This is a setting that
2012 Inductive Automation
Gateway Configuration
151
often causes confusion. Initially this value is blank by default which results in the QR code pointing to the address of http://localhost:8088. Since Ignition is not running on your mobile device this address will not actually launch the mobile homepage. This should be set to the Ignition server address that can be reached by the mobile device.
Networking
Callback Port The port that the VMs use to communicate to the Gateway on. By default this is set to 45900, but if this port is already in use then change this to an available port. Callback Interface The interface that mobile client VMs should use to communicate back to the Gateway on. By default this is localhost and makes use of the loopback adapter, however if this host doesn't have a loopback adapter or if there are two network cards, set this to the IP address of the NIC that should be used for local loopback. Ajax Timeout The max time, in milliseconds, that each request has to complete. The default is 10,000 (10sec).
Advanced Properties
The Mobile Module also has an option to allow VNC connections. This allows certain thin clients that do not support the Java Runtime Environment and also do not have an HTML 5 compatible browser to launch Ignition clients. The settings listed under the advanced properties section all have to do with configuring the VNC connection. Enable VNC Allows direct thin-client connection over VNC. VNC Port The port used for the VNC connection Project Name The Mobile Module only allows one of the projects on the Ignition gateway to be viewed through VNC so you have to specify that project here. Unlike the normal mobile launch screen that allows you to choose a project, the project that you specify in this setting will be automatically launched when you connect via a VNC viewer application. Project Width The width of the project when it's launched Project Height The height of the project when it is launched
Project Design
Part IV
Project Design
153
4
4.1
Project Design
Designer Introduction
The Ignition Designer is where the majority of configuration and design work is done in Ignition. It is used to configure Projects, which are the major unit of design. Projects contain various resources, such as windows and transaction groups. A project may contain a variety of different types of resources, depending on the goal of the project and the modules installed. Common First Steps Create some SQLTags Create a Window Create a Transaction Group See also: Launching the Designer What is a Project?
4.2
4.2.1
4.2.2
4.2.3
Designer UI Overview
The Designer is organized around a central work space. The workspace changes based on the type of resource that you are currently editing. For example, if you are editing a Window, then your workspace will be the Window Designer. If you are editing a Transaction Group, your workspace will be the Transaction Group Editor, etc. There are many dock able panels that surround the workspace, as well as the familiar menu bars and toolbars. The dockable panels may be rearranged to your liking. Each type of workspace may have panels that are only valid when that workspace is active. Each workspace remembers its own perspective, which is the docking arrangement of the panels around it. If you have closed a panel and want to get it back, re-enable it in the View > Panels submenu.
Project Design
154
4.2.4
4.2.5
Communication Modes
The Designer has three communication modes that affect data flow to and from the Gateway: Off: All database query traffic and tag subscriptions and writes will be blocked. Read-Only: tag subscriptions and SELECT queries will work, but tag writes and UPDATE/INSERT/ DELETE queries will be blocked. Read/Write: All data will be passed through to the Gateway. The mode can be switched at any time via the tri-state toggle selection in the main toolbar, or the radio buttons in the Project menu. The Designer starts up in Read-Only mode as a safety mechanism, so that you don't inadvertently write to a tag as you are designing. You can customize the designer's startup mode, see the Designer General Properties section.
A common beginner mistake is to forget to switch the mode to Read/Write when attempting to test a window's functionality in preview mode.
A com ponent w ith the GW_COMM_OFF quality overlay
Experts often use the Off mode while designing a window to temporarily shut off data flow so that they can manipulate components' bound properties without the values being overwritten by the data bindings. This is useful to set the values that they want to serialize into the window. This can be important for windows with large datasets; clearing the datasets before saving the window can significantly reduce the size of the window, improving performance. Note: This setting does not affect the execution of a project's transaction groups. This is because
Project Design
155
4.2.6
4.2.6.1
Designer Tools
Output Console The Output Console is the script-writers best friend. It is a dockable panel, and can be opened via the Tools > Console menu or the Ctrl-Shift-C keyboard shortcut. The output console is most frequently used to test and debug Python scripts in Ignition. By using the print keyword in your script, you can observe the inner workings of your script as it executes. For example, if you executed the following script:
# A function that intercepts tag writes, printing out the previous value first def writeToTag(path, value): import system prevValue = system.tag.getTagValue(path) print "Writing value '%s' to %s, was previously '%s'" % (value, path, prevValue) system.tag.writeToTag(path, value) writeToTag("Compressor/HOA", 2) writeToTag("Compressor/HOA", 1)
Note that the output console is also available in the Vision Client, via the Diagnostics window. See also: About Python Diagnostics Window 4.2.6.2 Diagnostics Window The Diagnostics window, which is available in both the Designer and the Vision Client, contains a number of useful troubleshooting features. It features a number of tabs, some of which are initially hidden. Right-click on any of the visible tabs to show or hide other tabs. Performance Displays a number of small realtime charts that display various aspects of the currently executing Designer or Client's performance. These charts can be very useful to help troubleshoot performance issues, especially slow queries. One of the most common causes of query slowdown is simply running too many queries too frequently, and the # of Select Queries / Second chart can help identify when this is occurring. Console Displays the Output Console. Log Viewer Displays the logged events for the current Designer or Client session. Whenever errors occur, they will be logged and displayed in this tab. This is a good place to go when troubleshooting an issue, as any errors shown here may illuminate the cause of the problem. To view entries across all categories chronologically, uncheck the Group Categories checkbox. Logging Levels
Project Design
156
Determines the verbosity of a host of internal loggers. Most users will not use this tab unless prompted by a technical support representative. Thread Viewer Shows information about the currently running threads. Most users will not use this tab unless prompted by a technical support representative. 4.2.6.3 Find / Replace The Find / Replace tool is a very handy tool. It can be used to search an entire project for where a tag gets used. The replace feature can also be used to to make mass changes to a project with very little effort. To open the Find/Replace dialog box, choose the menu item under the Edit menu or use the shortcut Ctrl-F.
Finding
To search through your project, simply type what you're searching for in the text field at the top and press the Find button. You can use the wildcard character (*) which will match anything, and the singlecharacter wildcard character (?). For example, to find all references to a tag that include the string "Motor", you'd search for "Motor*". This would match things like "Motor15", "MotorHOA", etc, whereas the search query "Valve? Status" would match "Valve1Status" but not "Valve38Status"
Target Scope
To narrow down your search, it is often useful to specify a narrow search target. The Find / Replace system searches through many different parts of a project, and through SQLTags as well. The target settings let you specify exactly what to search through. By unchecking boxes in the target section, you can avoid search results that you aren't interested in.
Results
When you execute a search, all matching items appear in the search results section. You can doubleclick on an item in the results table to bring that item into editing focus in the Designer.
Replace
To use the replace feature, select a result entry after doing a search. You'll see the current value with the matching area in bold-face font. Enter the text you'd like to use as a replacement in the Replace textbox, and you'll be shown a preview of the new value in the preview box. Hit the Replace button to execute the replace. This will move your selection down in the results table so that you can rapidly execute multiple replacements. If you're satisfied that you'd like to make the identical replacement to many items, select them all in the results table in hit the Replace All button. 4.2.6.4 Image Manager The Image Manager is available from the Tools > Image Management menu. This tool is a dragand-drop browser that helps manage the images that are stored on the Gateway. It is important to realize that these images are shared across all projects: they are not stored inside a project itself. Use the toolbar at the top to do common tasks like uploading new images and creating folders. You can drag images from your computer's desktop or hard drive into this window to easily upload new images to
2012 Inductive Automation
Project Design
157
the Gateway. You can also get to this tool by putting an Image component on a window, and using the browse button on the image's Image Path property. See also: Image Component 4.2.6.5 Symbol Factory If you have the Symbol Factory module installed, you'll be able to open the symbol browser under the Tools menu in the Designer. You can browse through the symbols or use the convenient search function to find the symbol you need. Once you find a symbol, you can drag-and-drop it into a window. Each symbol will be dropped as a shape group. You will be able to un-group it or double-click into the group just as if you had drawn the symbol yourself using fundamental shapes. This means that you can alter the shape if you need to, or bind any colors inside the shape to a tag to make the shape dynamic. 4.2.6.6 Query Browser The Query Browser is a very convenient tool that lets you interact with all of the databases that you have configured connections for. Because Ignition is so heavily integrated with databases, it is very common in the course of project design to need to inspect the database directly, or to experiment with a SQL query to get it just right. You can use the auto-refresh option in the Query Browser to monitor a database table for changes. This is often convenient when designing Transaction Groups. As the group runs, you can view the table that it is targeting with auto-refresh turned on to watch how the group is altering the table. The Query Browser is a convenient way to make simple edits in a database table as well. If you execute a SELECT query that includes the table's primary k ey(s), then you may activate edit mode by selecting the Edit button. While in edit mode, you can alter the values in the result set. Make sure to hit Apply when you are done to commit your edits, or press Discard to back out. Note that this feature depends on the applicable JDBC driver's ability to detect the table's primary keys. See also: Creating a Database Connection
4.3
4.3.1
SQLTags
What is a SQLTag?
A SQLTag, in many ways, is what is simply considered a "tag" in other systems. They are points of data, and may have static values or dynamic values that come from an OPC address, an expression, or a SQL query. They also offer scaling, alarming, and meta information facilities. SQLTags provide a consistent data model throughout Ignition, and offer the easiest way to get up and running creating status, control, and simple history systems. Despite their low initial learning curve, however, SQLTags offer a great amount of power in system design and configuration. The ability to aggregate tags from a variety of installations in a central SQL database means that you can build widely distributed SCADA systems more easily than ever before, with a high level of performance and relatively easy configuration. SQLTag User Defined Types (UDTs) provide an object-oriented approach to tag building, allowing you to define parameterized data types, extend and override types, and then rapidly generate instances. A change to the type definition is then inherited by all instances, drastically saving
Project Design
158
time when making routine changes. The UDT data types are fully supported by Vision templates, which means you can configure templates for your custom data types and take advantage of drag-and-drop binding to rapidly build complex screens. For more information about the benefits of SQLTags, see the SQLTags Overview in the Architecture chapter.
Tag Execution
SQLTags are executed by scan classes inside of a tag provider. In a typical system there will be one or two tag providers (the internal provider, which keeps the tag configuration in the project, and possibly an external tag provider in which tag configuration and values are stored in a database), and a number of scan classes. SQLTags stored in an external provider will be available to all Ignition installations that have access to that database. One of the installations will be specified as the tag's driver. The driving system will have a copy of the scan class that it executes, which in turn evaluates the tag. The value will be stored to the database, and all of the other installations will be notified of the new value. For more information about providers, see SQLTags in the gateway configuration section.
4.3.2
Types of SQLTags
There are several types of SQLTags. While in discussing "SQLTags" we commonly mean gateway executed tags, system and client tags can play an important role in the overall design of a project.
Project Design
159
and allows mathematical operations, references to other tags, logic operations and more. SQL Query Tags These tags execute a SQL Query, whose result provides the value for the tag. Like SQL binding in Vision, SQL Query tags can reference other tags to build dynamic queries. Complex Tags (UDTs) Complex tags are created out of standard tag types, but offer a variety of additional features. In simple terms, you can think of them as a way to create "data templates", where a particular structure of tags is defined, and can then be created as if it were a single tag.
System Tags
System tags provide status about the system, such as memory usage, performance metrics, etc. They exist for the client and the gateway. Gateway system tags can be modified by the user to use alerting, history, and scaling, while client tags cannot.
Client Tags
Client tags, as the name implies, are only available for use in clients. This means that their values are isolated to a client runtime, and even though they are created in the designer, each client will create their own instances. This makes them very useful as in-project variables, for passing information between screens, and between other parts of the clients, such as scripting. Client tags are a hybrid of memory, expression, and sql query tags. However, they do not have a scan class. When set to run as an expression or query, a poll rate is specified dictating how often the value should be calculated.
4.3.3
Creating SQLTags
Creating From OPC Tags
The easiest and most common way to create SQLTags is to drag tags into the SQLTags Browser window from the OPC Browser . After browsing OPC and finding the tags that you want, simply drag and drop them onto the correct tag provider, and the system will create OPC SQLTags for each.
Re-naming SQLTags
Tags can be named anything (inside the rules of allowed characters). In other words, it is not necessary that tag's name be related at all to its underlying data source (opc path, for instance). This provides a level of indirection that is convenient for systems whose underlying data storage changes, or for system with many repeat tag structures. By providing tags with meaningful names and arranging them in
2012 Inductive Automation
Project Design
160
hierarchical folders, indirect binding can be used to create robust screens that can be used for multiple systems. Valid characters for SQLTag names include spaces and the following: 1234567890_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
4.3.4
4.3.4.1
Numeric Properties The numerical properties are available to OPC, DB, and Client tags whose data types are numeric. Property Binding Name Description Scale mode ScaleMode If and how the tag value will be scaled between the source, and what is reported for the tag. Deadband Deadband A floating point value used to prevent unnecessary updates for tags whose
2012 Inductive Automation
Project Design
161
Scaling Settings
Property Raw Lo Raw Hi Scaled Lo Scaled Hi Clamp Mode Binding Name RawLow RawHigh ScaledLow ScaledHigh ClampMode Description Start of the "raw" value range End of the "raw" value range Start of "scaled" value range. Raw low will map to Scaled low for the tag. End of "scaled" value range. Raw high will map to Scaled high for the tag. How values that fall outside of the ranges will be treated. "Clamped" values will be adjusted to the low/high scaled value as appropriate.
Linear Scaling The value will be scaled linearly between the low and high values, and clamped as appropriate. The linear equation is:
ScaledValue = S * (Value-R L)/R + S L
Square root Scaling The equation for square root scaling is:
ScaledValue = (S * (Value-R L)/R) + S L
... where S is (ScaledHigh-ScaledLow), R is (RawHigh - RawLow), RL is RawLow, and SL is ScaledLow 4.3.4.3 Metadata Properties The metadata properties provide informational properties for a tag. The values of these fields can be read and modified through scripting, or bound to properties such as range, tooltips, etc. Property Format Description How the value should be formatted when converted to a string (only applies to numerical data types) EngUnit Eng. Units The engineering units of the value EngLow Eng. Low The lowest expected value of the tag. EngHigh Eng. High The highest expected value of the tag Tooltip Tooltip The tooltip provides a hint to visual components as to what should be displayed when the user hovers their mouse cursor over the component that is being driven by the value of this tag. Documentation Documentation A freeform text property for information about the tag 4.3.4.4 Permission Properties By default, a tag's Access Mode property is set to Read/Write, which means that any user may read the value of the tag and may write to the tag. Read-only mode makes the tag non-writeable for all users. Custom mode allows the tag to assign read/write or read-only privileges to individual roles. Any roles not explicitly granted a right by using the custom permissions editor will not be able to read the tag's value or write to the tag. Binding Name FormatString
Project Design
162
4.3.4.5
History Properties The properties on the History tab detail if and how the tag's history will be stored in the SQLTags Historian system. Property Binding Name Store History HistoryEnabled Description Whether the tag will report its history to the SQLTags Historian system. PrimaryHistoryPr Which SQLTags Historian data store the tag will target. A particular History ovider Provider tag can only target one history store. HistoricalScancl The scan class to use to evaluate tag history. This allows the tag's Historical Scan Class ass history to be stored at a slower rate than the status is updated at. HistoricalDeadba A deadband that applies only to historical evaluation. Historical nd Deadband Value Mode InterpolationMod How interpolation will be handled for the tag in querying. See below e for more information. HistoryMaxAgeMod The maximum amount of time that can pass before a new record is Max Time e / Between logged for the tag. HistoryMaxAge Records Timestamp HistoryTimestamp Which timestamp is used for the value of the tag. Source Source
Value Mode
The value mode, analog or discrete, dictates the type of value that the tag represents, and will affect how the deadband is applied to values, and how interpolation should be performed when querying. Interpolation is the method in which the SQLTags Historian query system generates values for a tag when the desired time does not fall directly on a sample timestamp. Discrete Storage - The deadband will be applied directly to the value. That is, a new value (V1) will only be stored when: |V1-V0| >= Deadband. Interpolation - The value will not be interpolated. The value returned will be the previous known value, up until the point at which the next value was recorded. Analog Storage - The deadband is used to form a corridor along the trajectory of the value. A new value is only stored when it falls outside the previous corridor. When this occurs, the trajectory is recalculated, and a new corridor formed. See below for an example. Interpolation - The value will be interpolated linearly between the last value and the next value. For example, if the value at Time0 was 1, and the value at Time2 is 3, selecting Time1 will return 2.
Project Design
163
Timestamp Source
When a SQLTag executes, there are two possible timestamps that can be observed: the time associated with the data, and the time that the tag was evaluated. The first case is generally only interesting when the value is provided by an OPC server. In most cases, the time provided by OPC, which in Ignition is referred to as the "Value" time, will be very close to the system time. Some servers, however, either due to their location or how they function (history playback, for example), will provide times that are very different than the current time. It is generally desirable to store the System time, as it is the time that the value was actually observed by the system, and it creates a uniform timeframe for all realtime data. However, in the later case described above, it is necessary to store the time provided by the OPC server. Using the Value timestamp source has several consequences: the system is no longer able to validate the tag quality against the scan class' execution, and tag value interpolation will behave differently. The validation of the scan class execution is generally not a concern when recording historical playback data. Interpolation only occurs when the value mode is Analog, and when there is not a value for every time window. Using System time, the value is only interpolated during the last "scan class execution window", that is, one scan class timeframe before the next value. Using Value time, however, the value is interpolated for the entire time between two data points.
In this image, an analog value has been stored. The graph has been zoomed in to show detail; the value changes often and ranges over time +/- 10 points from around 1490.0. The compressed value was stored using a deadband value of 1.0, which is only about .06% of the raw value, or about 5% of the effective range. The raw value was stored using the Analog tag mode, but with a deadband of 0.0. While not exactly pertinent to the explanation of the algorithm, it is worth noting that the data size of the compressed value, in this instance, was 54% less than that of the raw value.
Project Design
164
By looking at one specific sequence, we can see how the algorithm works:
The sequence starts with the second stored compressed value on the chart. 1. A value is stored. No further action is taken. 2. The next value arrives. A line is made through the value, with the size of the specified deadband value. A line is projected from the last stored value to the upper (line U1), and lower (line L1), bounds of this new value line. This establishes the initial corridor. 3. A new value arrives. The same procedure is taken, and new lines are created. However, only lines that are more restrictive than the previous are used. In this case, that means only line U2, the new upper line. 4. Another value arrives, causing a new lower line (L3) to be used. 5. Finally, a value arrives that falls outside of our corridor. The last received value (value 4) is stored, and a the process is started again from that point. 4.3.4.6 Alerting Properties SQLTags have the ability to define both digital and analog alerts- conditions of particular interest that can be used to generate emails, store records in the database, and more.
Digital Alerts
Digital alerts define a specific value that represents the "active" state, as opposed to Analog alerts, which define a range. Alert Name The name of the digital "state". Will be shown in the alert log and status systems. Severity The relative "importance" of the alert. Can be used for filtering purposes later. Value Mode - Equal/Not equal Alert is active when the tag's value matches the specified value. Value Mode - Any change Alert occurs any time the tag's value changes, subject to the alert deadband. "Any Change" alerts are instantly clear, as well, as there is no defined clear state. Time Deadband The alert is only considered active once the "active state" has been true for the given amount of time. If the state changes before the time deadband clears, no alert is generated.
Project Design
165
Analog Alerts
Analog alerts define any number of "states" - each of which defines a range, severity and name. The settings for a state are similar to those for a digital alert, with a few differences: Low and High Setpoints Define the range in which the alert state is considered "active". Outside of the range the state is "clear". May be "infinite" in order to have unbounded state ranges. For example, an alert state range with a lower bound of 50.0 and an upper bound of infinite will be active for any value greater than 50.0. Setpoint Mode Dictates how the state acts when the value is on the boundary of the state. "Inclusive" means the setpoint is included in the range of possible values, and the state will be active if the tag's value equals the setpoint value. "Exclusive" excludes the setpoint value from the range. Tag Driven Both the low and high setpoint values can be driven by a separate tag. The values of the referenced tags will be latched each time the state is evaluated, and will otherwise act like static values. Alert on any change An alert will be generated for any value change while the value is inside the boundaries of the state.
General Settings
Ack Mode Dictates how acknowledgement works for the alarm. Unused - Acknowledgement will not be used for this tag, and any alert that is generated will automatically be marked as acknowledged. Auto - The alert is acknowledged automatically when the alert state becomes cleared. Manual - The alert is never set to acknowledged by the system, and it is up to the user to manually acknowledge alerts. Timestamp Source Specifies which timestamp should be reported for the active/clear times- the time coming from the system, or the time coming from the tag value. System - The timestamp will be the current system time when the alert event occurs. Value - The timestamp used will be the timestamp associated with the value that caused the event. Alert Deadband Defines a deadband that is only used when evaluating the alerts. This setting is used primarily with analog alerts to prevent many alerts from occurring for analog values that constantly "float". An alert with a deadband will become active immediately after the tag's value crosses the active threshold. The tag will not clear, however, until after the alert has gone outside of the active range by more than the deadband. In most cases, the deadband is added or subtracted to/from the setpoint to determine clear. In any change mode, the tag will only generate a new alert when the value has changed by more than the deadband from the last alerted value. Time Deadband Defines an amount of time that the tag value must remain in the numeric region considered "active" before the alert is considered active. Once the alert has become active (after the time deadband
Project Design
166
specified has elapsed and the value is still in active range), the alert will clear as soon as the value leaves the active region. For example, suppose you had a digital alert that became active when the tag value is 5 with a 1 minute time deadband. Suppose the tag's value becomes 5 at 3:15 pm. The tag's alert will only be considered active at 3:16 pm, as long as the value remained 5 that entire time. Display Path This is an arbitrary path that can be used for querying and display purposes later. For example, if this path is not empty, it will be used by default to identify the alert by the Vision module's built-in alert status table instead of the path to the tag itself. Notes Freeform text field that can be used to record information about the alert. Can be used for display purposes later.
Notification Settings
These settings are used for sending email alerts in association with Alert Notification Profiles that are configured in the Gateway. Send Clear Indicates that a message should be send when the alert clears, in addition to when it becomes active. Message Mode How the message should be generated for the alert. Auto Generated - The system will create a basic message describing the alert condition. Custom - The provided message will be used. Custom Subject The subject of the email that will be sent for the alert. Can include references to other tags and alert properties, as outlined below for the message. Custom Message The message to be sent for the alert. Custom messages can reference other tags, and several properties of the alert. The following alert properties may be referenced: TIME VALUE STATE_NAME ALARM_FLAGS - Numeric representation of the current message. Can be a combination of the following: 0x1 - Register - Indicates that the tag has just been loaded and is being registered with the system. 0x2 - Active - The alert is active 0x4 - Cleared - The alert is clear 0x8 - Acknowledged - The alert has been acknowledged 0x10 - Deregister - The alert is being de-registered, likely due to tag deletion. ALARM_TYPE - User friendly alert state message, either "active", "clear", or "acknowledged". ITEM_PATH SEVERITY
2012 Inductive Automation
Project Design
167
DISPLAY_PATH NOTES SYSTEM To reference a property, put the name inside of square brackets, inside of the curly braces normally used for references. For example, {[ALARM_TYPE]} To reference a tag, use the standard curly brace syntax. For example, {North Area/ Compressor1/State}. The path may be wrapped in square brackets as well, if using formatting as described below. Referenced value number formatting Values referenced in the subject or message can be formatted for display. To do this, the variable name or tag path must be followed by a pipe "|" symbol and a format pattern. The format pattern can be for a date or a number (as described in the documentation for dateFormat and numberFormat, respectively). In order to use formatting with tag references, tag paths must be enclosed by square brackets. For example, the following would display only two decimal places: {[North Area/Compressor1/Amps|#0.00]} To format a date tag: {[North Area/Compressor1/LastChange|MMM d, yyyy]} Default Messages If not using custom messages, the default will have the following format: Subject: {[ITEM_PATH]} {[ALARM_TYPE]} Body: Alert {[ALARM_TYPE]} {[TIME]} - {[ITEM_PATH]} {[STATE_NAME]} {[VALUE]} 4.3.4.7 Expression/SQL Properties DBTags have the ability to use an expression or a SQL query as their value instead of an OPC item path. This can be used to select information from the database or create your own formulas to manipulate other tag values .
Expression
In expression mode, the tag can use all of the features available in the expression language. It can refer to other tags, and use operators and functions to calculate a value for the tag. See also: Expressions Overview
SQL Query
In this mode, the tag's value will be the result of the specified SQL query. The query can be any valid query, but should result in only one value. Note that insert and update queries can be used, and will often result in an integer value, so the tag's data type should be set accordingly. Like SQL Query bindings in the Vision module, the queries for tags can refer to other tag values. The values of referenced tags will inserted as literal text in the query before being sent to the database.
Project Design
168
4.3.5
4.3.5.1
Primary Features
Central Definition - Once you define your data type, you can then create instances of it. If at a later time you want to change some aspect of the tag, you can simply edit the type definition, and all instances will be automatically updated. Parameterized Settings - Define custom parameters on your data type, and then reference them inside your member tags. When it comes time to create instances, you can simply modify their parameter values in order to change where the underlying data comes from. Extendable - Data types can inherit from other data types in order to add additional members, or override settings. Instances can also override settings, allowing for flexibility for dealing with irregular data and corner cases.
Terminology
Many terms are frequently used when discussing complex tags: UDT or UDDT - User Defined Type or User Defined Data Type. The definition of the data type: its structure, tags, attributes and settings. Instances - Running copies of a data type, with concrete data for all members. Instances are linked to their parent types, and are reloaded when their parent type changes. Besides specifically overridden settings, all settings are inherited from the type definition. Parameters - Custom properties on data types that can be used inside the type or instance definition to create parameterized data templates. For example, if a data type consists of 3 OPC tags that only differ by a number in the path, a parameter can be used for the "base address", allowing instances to be created with only 1 setting. Members - The tags inside of a data type or instance. 4.3.5.2 Defining Data Types Creating a new data type is very similar to creating standard tags. Simply select New Data Type from the tag creation menu to open the editor. When editing complex tags, the tag edit window appears a bit differently. The member structure is presented in the upper left. By selecting a member, the tag property categories are displayed below, and the editor for the selected category appears to the right.
Adding Members
To add members to a data type, simply select the type of tag from the toolbar above the member tree. Data types can contain standard tags like OPC and DB, as well as folders and instance of other
2012 Inductive Automation
Project Design
169
complex types.
Adding Parameters
Parameters, which can be used for property expansion in member tags, can be added by selecting the data type in the member tree. If a data type contains other complex types in it, there may be various points in the tree with custom parameters. While a data type can override the parameter values inherited from a parent, new parameters can only be added to the root node of the new data type.
Project Design
170
form "DataPoint001", in order to stay consistent up to "DataPoint999". This can be accommodated using number formatting in the reference: Member 1: DataPoint{BaseAddress+0|000} Member 2: DataPoint{BaseAddress+1|000} Member 3: DataPoint{BaseAddress+2|000} This format of three zeros means "three required digits". If our instance has a base address of 98, the resulting paths will be "DataPoint098, DataPoint099, DataPoint100". Properties that can be parameterized The following tag properties can reference parameters: Value (for string data type only) OPC Server OPC Item Path Tooltip Documentation Expression/SQL Query Alert Notes Alert Display Path Alert State Name Alert Subject/Message Analog alert driving tag paths
Overriding Properties
Sub types and instances can override the properties defined in parent types. To do this, simply select the override control (the small grey ball) next to the property to override in the member editor. Conversely, to remove the override, simply unselect the control. Custom parameters can be overridden as well, but it is not require to specify that the value is an override. Simply provide a new value for the property. For inherited parameters, the "delete" button next to the parameter table will simply remove the override. The parameter can only truly be delete from the type that defines it.
Project Design
171
If you have data types defined in your PLC (or OPC server), you can short-cut the conversion step outlined above by simply dragging the tags (or the folder for the type) from the OPC Browser directly onto the Data Types folder, and selecting "Create Type" from the subsequent dialog. 4.3.5.3 Creating Instances Creating instances of complex types is virtually identical to creating other types of tags using the New Tag menu. Unlike standard tags, it is likely that you'll have to modify attribute values or override certain member properties in order to make the instance unique. The process for doing this is equal to that used when creating data types. Once created, instances run very much like standard SQLTags. If the parent data type is updated, the instance will automatically receive the updates and refresh.
As mentioned, the size of the pattern will dictate how many tags will be created. If some patterns are smaller than others, the last value will be repeated for the other tags. Tag Names The names of the generated instances can be specified using a system similar to that of the parameter patterns. If you just want to use sequential names, you don't need to specify a pattern, as values will be generated automatically starting at one. You can also set the pattern to simply be the starting number to generate sequential names from there.
2012 Inductive Automation
Project Design
172
Base Name - A string base for the tag name. This can also be a list of names, in which case the names will be used directly, and the name pattern won't be used. Name Pattern - A pattern that will be used to generate values that will be appended to the base name. At any time, you can use the preview button to view the tag names and parameters that will be created. Once you are satisfied, click ok to generate the tags under the selected folder in the tag provider.
4.3.6
Scan Classes
Scan classes dictate the execution of SQLTags, and therefore play a crucial role in the design of large, high-performance systems. It will often make sense to have more than one scan class. Usually not all of your tags will need to be subscribed at the same rate. Some tags you may wish to see updated at 250-500ms, while others may not be so crucial and may only need to be subscribed at 1500ms. Creating different scan classes allow you to organize your tags into groups that subscribe at different rates. It is good practice to put some forethought and planning into the organization of your SQLTags and scan classes.
Note on rates: If the rate is set to 0, the scan class will not be executed. It is common for leased and driven modes to use 0 as a slow rate in order to achieve an "on/off" effect.
Project Design
173
The rate of the scan class is based on the value of a driving tag. The condition is a simple comparison between an a tag value and a number. If the condition is true, the scan class will execute at the fast rate. If false, it will run at the slow rate. There are two exceptions to this: the any change operator, and one-shot mode. Using either of these, the scan class will not run at a rate. Instead, it will be triggered by a change in the driving tag's value. "Any Change" will execute each time the value changes, and "one shot" will execute once when the comparison condition is true, and not again until the condition become false, and subsequently true. It's useful to keep in mind that the driving tag can be an Expression tag that performs complex calculations and references other tags. In this way, it's possible to create robust scan class triggering.
Advanced Properties
OPC Data Mode This mode dictates how OPC values are obtained. The default mode, "Subscription", is generally recommended. Subscribed - All OPC tags in the scan class will be subscribed according to the scan class rate. Values will come in asynchronously as they change. Read - Tags will not be subscribed, but will instead be synchronously read each time the scan class executes. This operation is less efficient, but allows more precise control over when values are obtained. This mode is particularly useful when collecting data over a slow or expensive connection for display. When combined with the "one-shot" execution mode above, and a static tag tied to a momentary button, it's easy to create a manual refresh button on a screen that pulls data on-demand.
4.3.7
Tag Paths
Tags and their properties can be referenced by a string based path. Each has a unique absolute path, and will often have many equivalent relative paths when referenced from other tags. You will most often generate these by browsing or through drag and drop. However, it's a good idea to understand how tag paths work, particularly if you get into indirect tag binding or scripting. A tag path will look something like this: [Source]folder/path/tag.property The italicized portion of the path may contain the following: A tag Any number of nested folders followed by a tag, separated by forward slashes (/). A period (.) followed by a property name after the tag. Omitting this is equivalent to using the .Value property.
Project Design
174
Now consider the [Source] (portion surrounded by square braces) Source Option [Tag Provider Name] [] or not specified [.] [~] [Client] [System] Meaning Applicability The name of the tag provider that OPC and Expression tags hosts the tag The default tag provider for the OPC, Expression tags current project. Relative to the folder of the tag thatExpression, Client tags is being bound. Relative to the tag provider of the Expression, Client tags tag that is being bound (root node) Refers to a client tag Client Refers to a system tag System
Relative Paths
Paths that begin with [.] or [~] are known as relative paths. The are used inside SQLTags that bind to other tags, and are relative to the host tag's path. Using the relative path syntax helps avoid problems cause by moving tags and renaming providers. [~] refers to the tag's provider root. It can replace the explicit provider name, and thus protect against provider renames and importing/exporting/moving tags between different providers. [.] refers to the tag's current folder. By using [.], tags can be moved from folder to folder without problem (provided that all of the applicable tags are moved together).
4.3.8
Data Quality
Data Quality is the measure of how reliable a particular SQLTag's data is. If a tag's quality is not Good, the value generally should not be trusted. There are a wide variety of causes of bad data, from network disconnections to software failure, to invalid tag configuration. The quality is a property of the tag ( Quality), and can be seen in the SQLTags browser. Additionally, bad tag qualities will be reflected in components bound to tags through the quality overlay system. The following table outlines the primary data qualities. There are more values, but these represent the most common: Quality Good Bad Stale Meaning The data has met all criteria for being considered reliable. The data is not reliable, further data isn't available. The tag has not been evaluated within the expected time frame. There is likely a deeper problem with the tag provider. Config_Error There is a problem with the tag's configuration. The error log may provide more information as to the exact problem. Comm_Error There is a problem in communication somewhere between the tag and its data source. Tag_Exec_Error There was an error evaluating the tag. Expression_Eval_ErrThe expression in the tag generated an error during execution. The error log should or provide more information on the error. Type_Conversion_Er The value of the tag could not be converted to the requested data type. Check the ror assigned data type of the tag. OPC_Not_Connecte The OPC server driving the tag is not currently connected OR a value has not yet d been received by the tag from the server. Not_Found The tag, or a tag referenced from inside of it, could not be found (incorrect reference path). Driver_Demo_Timeo The system driving the tag is operating in demo mode and has timed out.
2012 Inductive Automation
Project Design
175
When viewing SQLTags in the designer, the tags will have this value if communication with the gateway is turned off from the toolbar. The tag permission settings do not allow the current user to view the tag. The tag's "enabled" property has been set to false.
4.3.9
CSV Format
The SQLTags CSV format consists of a fixed set of column headers. Generally the columns are self explanatory, in that they correspond to standard tag properties, and contain simple values. However, several columns have specially formatted values. Alert States Alert states are written as a semi-colon separated list of properties, with multiple states separated by a dollar sign ($). The properties, in order, are: "name, severity, low limit, high limit, flags, low tag path, high tag path, time deadband, time deadband units". Flags - Bit mask defining properties of the state 1 - Low Exclusive 2 - Low Infinite 4 - High Exclusive 8 - High Infinite 16 - Any change 32 - Low setpoint is tag driven 64 - High setpoint is tag driven Time deadband units - "MS, SEC, MIN, HOUR, DAY" Custom Permissions If using custom permissions for the tag, the set of role/permission mappings are written in the format "role;{RO|RW}$". For example, two read only roles and one read/write role would be written like: "Operators;RO$Vendors;RO$Admins;RW$"
Complex Types
Complex types are supported by the CSV format, and are generally straight forward. There are only a
Project Design
176
few special considerations for data types: 1. The path column is relative to the root of the data type. 2. Parameters are listed as separate entities, with a tag type of 11, no path, and the Owner set to the defining type. 3. Overrides are stored as separate lines, with the path set to the relative path under the data type, and the owner set to the instance to which the override belongs. All columns that are not empty are considered overridden properties. 4. The order of the tags in the CSV is important- types should be defined before sub types and instances that use them. Instances should be defined before the overrides that they contain.
4.4
4.4.1
Project Properties
Project General Properties
A project's general properties apply to the project as a whole, across all module functionality. You can edit a project's general properties in the Designer by double-clicking on the Configuration > Properties node in the Project Browser, or by navigating to the Project > Properties menu. Note that a few properties of a project, such as its name, description, and title are set in the Gateway by clicking on the edit link next to a project under the Configuration > Projects section. Important Concept: Defaults Project General Properties is where you set the project's Default Database and its Default SQLTags Provider. It is important to understand how to use defaults effectively for proper project design. Wherever you use a database connection or a SQLTag in a project, you are always given the option to use the project's default, or an explicitly named connection or provider. If your project is like most typical projects, it primarily uses a single database and a single SQLTags provider. By consistently using the "default" option, you make your project more resilient to change. For example, suppose you have designed a project, and it has a database connection called "Production_DB". Now you want to adapt the project to a new, similar plant, while leaving the existing project intact. You copy the project and create a new database connection, called "New_DB". If your project consistently used it's default database connection, the switchover will be as simple as changing the copied project's default database. However, if you used the explicit "Production_DB" connection in your groups and screens, you will need to laboriously switch the bindings over to "New_DB". SQLTags Settings The SQLTags provider chosen here will act as the project's default provider. To use the default provider, simply omit the source section of a tag path, or leave it blank, for example: Path/To/ MyTag or []Path/To/MyTag. The client poll rate is the rate at which a Vision Client or Ignition Designer polls the Gateway for updates to its subscribed SQLTags. Database Settings The default database connection to use for this project. To use the default database connection, use the special <default> connection, or in scripting, the empty-string connection "". Security Settings Choose the authentication profile that governs this project's security. This profile will be used for client logins. You may also optionally specify a list of roles that are required for a user to log into this project. Use commas to separate the roles. Users must have all of the roles in order to log in. If no roles are specifed, the user only needs to correctly authenticate with the authentication profile in order to log in. Auditing Settings If auditing is enabled, audit events will be stored that relate to this project in the chosen audit profile.
2012 Inductive Automation
Project Design
177
Publishing Settings This is where you configure whether or not a project is split into separate staging and published versions. By choosing "Manual" publish mode, pressing Save in the the Designer will alter the Staging version of the project. The Published version of the project will only be updated when you hit the "Publish" button. If you are in "Auto" publish mode, each save acts like a save followed by a publish, so the two versions are always the same. You can also specify here whether or not commit messages are required, and if so, under what conditions. See also: Project Management Tag Paths Security Overview Project Versioning
4.4.2
4.4.3
4.4.4
Project Design
178
The Vision Client can emulate any timezone. By default, it will appear to be in the same timezone as the Gateway. This has the effect of all clients behaving the same, regardless of the timezone setting on the Client's host operating system. Depending on your project's requirements, this may not be optimal. You may have the Client use the host's timezone by choosing the "Client Timezone" option, or you may specify an explicit timezone for all Clients to emulate. Publish Mode This setting affects how clients receive updates when the project is saved. The default is Notify, which means that all running Clients will display a yellow information bar at the top of their display that notifies the operator that an update is available. The update will be installed when the operator clicks on the yellow bar. You may choose Push mode to have updates automatically pushed to all running clients with no operator interaction. This is often desirable when a client is running in a situation where keyword and mouse access is inconvenient, such as in a large overhead display. Touch Screen All clients can operate in touch-screen mode. When in this mode, clicking on numeric and text entry boxes will pop up on-screen keyboards that can be used for data entry. By enabling touch-screen mode, an operator is given the opportunity to activate the mode on the startup screen. You have the opportunity to control whether or not clients start up with touch-screen mode active by default or not as well. These settings are helpful for mixed-use projects, i.e. those that are launched on both touchscreen devices and traditional computers and laptops. Data - Tag History Cache The clients normally maintain a cache of data retrieved from SQLTags History, improving repeat operations on graphs and tables. When this option is disabled, no data is cached, and the full queries execute against the gateway each time data is required.
4.4.5
Project Design
179
checking the "Hide Exit Button" checkbox. Applet Properties These properties affect how the project appears when launched as a browser applet. Client Memory These properties govern how the client uses RAM resources on its host machine. The initial memory setting is how much memory the client will require on startup. While this is typically left alone, boosting it a bit can improve performance somewhat. The maximum memory setting sets a cap on how much memory the Java VM is allowed to use. This setting can be important for clients that require very large charts, tables and reports. Even if you have launched a client on a machine with plenty of RAM, you'll also need to boost this setting to allow the client to use more RAM. See also: Image Management Launching Clients
4.4.6
4.4.7
4.4.8
Project Design
180
Vision workspace. Whenever the usable space shrinks smaller than these bounds, scrollbars will appear, capping the width and height to these minimums. This defaults to 800x600. Client Background Color This option allows you to specify the color of the Vision workspace, which will be visible when not obscured by windows. Client Menu These options allow you to alter the appearance, or remove completely, the menu bar that appears in a running Vision Client. See also: Component Layout Menu Bar Scripts
4.5
4.5.1
Whats up with that "import system" call? Frequently in Ignition, your scripts get system (the built-in library package in Ignition) and app (your project's global script modules) imported for you automatically. Whenever you define a new scope (which you've done with def), we can no longer do this for you, and you'll need to import them manually. See also: About Python Scope and Import
Project Design
181
4.5.2
4.5.2.1
Event Scripts
Overview Projects may use scripting to react to a variety of events and actions that occur within the project's lifecycle. There are two major scopes for scripting: Gateway scripts and Client scripts. Gateway scripts execute on the Ignition Gateway, which means that they always execute in one place. Client scripts execute in the client, which means that they may never execute (if no clients are running), or they may execute many times. Client scripts will also execute in the Designer, but only in Preview Mode. Note that these project global event scripts are not to be confused with the component event handler scripts.
4.5.2.2
Startup and Shutdown Scripts These script types are available in both Gateway and Client scopes. These scripts will be run when the project starts up or shuts down. In the Gateway scripting scope, this means that the script will run when the Gateway starts up or is shut down, and whenever the scripting configuration changes via a Designer save action. This means that while designing, the startup and shutdown events may happen frequently. In the Client scripting scope, these scripts run after a user successfully logs in or out, or when the client is closed.
4.5.2.3
Shutdown Intercept Script This script type is only available in the Client scope. This is a special script that will be called when the user tries to exit or close the client. This script is run with a special event variable in its namespace. When the script terminates, if event.cancel is 1, then the shutdown will be aborted, and the client will remain open. Otherwise, the normal shutdown script will be called, and the client will close. Example
if "SuperUser" not in system.security.getRoles(): system.gui.warningBox("Exit not allowed for non-admin user.") event.cancel=1
4.5.2.4
Keystroke Scripts Keystroke scripts are only available in the Client scope. These are scripts that run on a certain key combination. You may add as many keystroke scripts as you'd like, as long as each one has a unique key combination. When choosing a keystroke, you may choose any number of modifiers, which are keys or mouse buttons that must be down to activate the keystroke. You can also choose whether or not the keystroke is on the pressed or released event of a keyboard key, or upon the typing of a character. Special keys like the F-keys, ESC, etc, are only available in the pressed and released actions.
4.5.2.5
Timer Scripts Timer scripts are available in both Gateway and Client scopes. These scripts execute periodically on a fixed delay or rate. Remember that Client timer scripts may never execute (if no clients are open) or may execute many times (once per open client). If you need scripting logic that occurs centrally, make sure you use Gateway scoped scripts. Fixed delay or fixed rate? A fixed delay timer script (the default) waits for the given delay between each script invocation. This
Project Design
182
means that the script's rate will actually be the delay plus the amount of time it takes to execute the script. This is the safest option since it prevents a script from mistakenly running continuously because it takes longer to execute the script than the delay. Fixed rate scripts attempt to run the script at a fixed rate relative to the first execution. If they script takes too long, or there is too much background process, this may not be possible. See the documentation for java.util.Timer.scheduleAtFixedRate() for more details. Shared thread or dedicated thread? All timer scripts for a given project that choose "Run in shared thread" will all execute in the same thread. This is usually desirable, to prevent creating lots of unnecessary threads. However, if your script takes a long time to run, it will block other timer tasks on the shared thread. The rule of thumb here is that quick-running tasks should run in the shared thread, and long-running tasks should get their own thread. 4.5.2.6 Tag Change Scripts Tag Change scripts are available in both Gateway and Client scopes. Each tag change script can be given a list of tag paths. Whenever one of these tags changes, the tag change script will execute. They will also get an initial execution whenever the scripting system starts up. Each tag change script can be given a name for organizational purposes. To specify multiple tag for a given script, enter them one per line in the tag paths text area. To quickly import many tags, you can drag-and-drop tags from the SQLTags Browser window onto this text area. These scripts receive three special variables in their namespace when they are run: event, initialChange and newValue. The intialChange variable is a flag (0 or 1) that indicates whether or not this event is due to initially subscribing or not. The event variable is a TagChangeEvent object, which itself contains the properties: tag, tagPath, and tagProperty. The third, newValue, is the new value for the tag property that is subscribed. These values are objects themselves that contain a value, quality, and timestamp. The following example script should be a good starting point. Example
print "Received tag change event for %s" % event.tagPath value = newValue.value quality = newValue.quality timestamp = newValue.timestamp print "value=%s, quality=%s, timestamp=%s" %(value, quality, timestamp)
Tip: The TagPath object that you access via event.tagPath is itself a complex object. You can turn it into a string if you want the whole tag path by using the str() function. You can also access individual parts of the tag path. The most useful is usually the itemName property, which is the name of the tag represented by the path. To get the name of the tag, you can use event.tagPath.itemName . 4.5.2.7 Menu Bar Scripts The Client's menu bar is configured through the Client Event Scripts dialog box. Each node in the menu bar that does not have children executes a script when the user presses it. Most commonly, these scripts will execute navigation actions; opening or swapping a window. See also: Typical Navigation Strategy
2012 Inductive Automation
Project Design
183
4.6
4.6.1
Transaction Groups
Introduction
Transaction Groups are the heart of the SQL Bridge module. They are units of execution that perform a variety of actions, such as storing data historically, synchronizing database values to OPC, or loading recipe values. A variety of group types, items types, and options means that Transaction Groups can be configured to accomplish almost any task. The Transaction Group Workspace Transaction groups are edited through the Ignition designer. When a group is selected, you will be presented with the transaction group workspace. The workspace is broken into several parts: 1) Title bar - Shows the name of the currently selected group, as well as options to set it as Enabled or Disable, and to Pause, if it's currently executing. 2) Item configuration - Shows all of the items configured in the selected group. Many settings can be modified directly through the display, the rest by double-clicking the item, or selecting "edit" in the context menu. 3) Action / Trigger / Options tabs - Define how and when a group executes. Holds most of the options that apply to the group in general, such as the update rate, and which data connection it uses. 4) Status / Events tabs - Provides information about the executing group, including the most recent messages that have been generated. Enabling Group Execution In order for groups to be evaluated, they must first be enabled. This is done by selecting "enabled" in the group title bar, and then saving the project. The group executing can be stopped by reversing the procedure and selecting "disabled" before saving. If you want to quickly and temporarily stop the group's evaluation, toggle the "pause" button. This will prevent execution until the group is un-paused, or until the system is restarted. Editing Group Settings Group settings may be modified at any time, regardless of whether or not the group is executing. Modifications will be applied when the project is saved, and the group will be started or stopped as required. Some changes such as modifying items may cause features like live values to appear to be incorrect. It is therefore important to note the modified icon that appears next to the group, and to save often. If you would prefer to stop the group before making edits you can simply pause the group. Execution will begin again after the project is saved. How Groups Execute Generally speaking, groups work on a timer. They are set to run at a certain rate, and at that rate, the check the rest of the settings. If the trigger conditions pass, the group is executed fully. The following section provides a fuller outline of the execution cycle.
Project Design
184
4.6.2
Execution Cycle
All of the groups follow a similar execution cycle. The core evaluation may differ, but the general cycle is the same. 1) Timer executes, group enters execution 2) Is the group paused? Break execution. 3) Is the Gateway part of a redundant pair? If so, is it active? If not active, break execution. Groups only execute on the active node. 4) Evaluate "run-always" items: OPC items, SQLTag references, and Expression items set to ignore the trigger (or placed in the "run always" section of the configuration window). 5) Is trigger set/active? If there is a trigger defined, but it is not active, break execution. 6) Evaluate "triggered" expression items. 7) If applicable, read values from the database 8) Execute a comparison between items and their targets 9) Execute any writes to other Tags or the Database that result from execution. 10) Report alerts 11) Acknowledge the trigger, if applicable. 12) Write handshake value, if applicable. If an error occurs at any stage besides the last stage, execution will break and the failure handshake will be written if configured. The group will attempt execution again after the next update rate period.
4.6.3
4.6.3.1
Anatomy of a Group
Action Settings The action settings of a group define how often the group will be evaluated, as well as important settings that apply to the group as a whole. They are found on the tab labeled "Action", the first of the tabs on the right side of the Transaction Group workspace. Common Settings The settings vary for the different types of groups, but a few setting are common to most of them: Execution scheduling How often the group is evaluated. For a number of reasons, the group may not execute during the evaluation. The most common reason is the trigger, but see Execution Cycle for more possible reasons why evaluation will exit. The data connection to use for the group. Can be "Default", which will use the default connection for the project. For groups that support it, sets the default for how items are compared to their targets. Stores a timestamp along with the data any time the group executes. Stores an aggregate quality for the group along with the regular data. The aggregate quality is a bit-wise AND of the qualities of the items in the group.
Project Design
185
Execution Scheduling
There are two ways to specify when the group should execute: timer mode, and schedule mode. Timer Mode In this mode, the group is evaluated regularly at the provided rate. As mentioned in the previous sections, due to trigger settings, full execution may not occur, but the trigger will at least be evaluated at this rate. Schedule Mode With schedule mode, you are providing a list of time (or time ranges) that the group should run at. If the pattern specified includes a time range, at rate must be provided, and the group will execute as in timer mode during that period. The schedule pattern The schedule is specified as a comma separated list of times or time ranges. You may use the following formats: 24-hour times. Ie. "8:00, 15:00, 21:00", for execution at 8am, 3pm, and 9pm. 12-hour with am/pm (if not specified, "12" is considered noon): "8am, 3pm, 9pm" Ranges, "8am-11am, 3pm-5pm" Notes It is allowed for time ranges to span over midnight, such as "9pm - 8am" When using ranges, the execution times will be aligned to the start time. For example, if you specify a schedule of "9am - 5pm" with a rate of "30 minutes", the group will execute at 9, 9:30, 10, etc., regardless of when it was started. This is a useful difference compared to the Timer Mode, which runs based on when the group was started. For example, if you wanted a group that ran every hour, on the hour, you could specify a 1 hour rate with a range of "0-24". 4.6.3.2 Trigger and Handshake Settings The trigger settings determine when a group will actually execute. They are examined each time the group evaluates (according to the update rate of the group). If they pass, the group will run and perform its action against the database. The trigger settings are the same for all group types. They are found on the second tab (labeled "Trigger"), in the right side of the Transaction Group workspace. Only execute when value have changed (asynchronous trigger) These settings are evaluated first. If set, the group will examine whether the values in the specified tags have changed, and if not, will exit evaluation. It is possible to monitor all Run-Always tags in the group, or only specific ones. Execute this group on a trigger Enables trigger on a specific item in the group. The trigger item can be any Run-Always item, such as an OPC item, SQLTag reference, or an Expression item set to "Run-Always" mode. In addition to the numeric settings that define the trigger, there are several other options:
Project Design
186
Only execute once while trigger is active - The group will only execute once when the trigger goes into an active state, and will not execute again until the trigger goes inactive first. If unselected, the group will execute each time the trigger conditions evaluate to true. Reset trigger after execution - If using the ">0" or "=0" trigger modes, the trigger can be set to write an opposite value after the group has executed successfully. This is useful for relaying the execution back to the PLC. Prevent trigger caused by group start - If selected, the group will not execute if the trigger is active on the first evaluation of the group. In the course of designing a group, it is common to stop and start it many times, and sometimes it is not desirable to have the group execute as a result of this. Selecting this option will prevent these executions, as well as executions caused by system restarts. Handshake Settings Group handshakes are also defined on the trigger tab. It is possible to specify both a success and failure handshake. The success handshake will write the specified value to the given item when the group has finished all other triggered execution without error. The failure handshake, on the other hand, will be written when the group execution is cut short due to an error, such as an error writing to the database or an item. 4.6.3.3 Advanced Settings Transaction groups offer several advanced settings that affect how execution occurs. These settings can be found under the Options tab for a group. OPC Data Mode This setting modifies how the group receives data from OPC. Subscribe - Data points are registered with the OPC server, and data is received by the group "onchange". This is the default setting and generally offers the best performance, as it reduces unnecessary data flow and allows the OPC server to optimize reads. However, it's important to note that data is received by the group asynchronously, meaning that it can arrive at any time. When the group executes, it "snapshots" the last values received and uses those during evaluation. If some values arrive after execution begins, they will not be used until the following execution cycle. Read - Each time the group executes it will first read the values of OPC items from the server. This operation takes more time and involves more overhead than subscribed evaluation, but ensures that all values are updated together with the latest values. It is therefore commonly used with batching situations, where all of the data depends on each other and must be updated together. It's worth noting that when using an OPC item as the trigger, the item will be subscribed, and the rest of the values read when the trigger condition occurs. Note: This option was previously referred to as "polled reads" in earlier versions of the software. Bypass Store and Forward System Only applicable to groups that insert rows into the database. Causes groups to target the database directly instead of going through the store-and-forward system. If the connection becomes unavailable, the group will report errors instead of logging data to the cache. Override OPC Subscription Rate Specifies the rate at which OPC items in the group will be subscribed. These items are normally subscribed at the rate of the group, but by modifying this setting it is possible to request updates at a
2012 Inductive Automation
Project Design
187
4.6.3.4.1 Overview
Items are the core elements of a group. They are executed, and the values are then used by the group for logic purposes, by other items, and to write to the database. They can be written to from the database or from other items. Type of Item OPC Item Description Directly subscribed to an OPC server at the rate of the group. Executed by the group, so alerts are evaluated when the group is executed. These items are executed even when the trigger isn't active. Run-Always Expression Much like an expression SQLTag, can be either a static value, an Item expression, or a database query. Run-Always expression items are evaluated at each group interval, before the trigger state is evaluated. Triggered Expression Item Same as Run-Always expression items, except that they are only executed after the trigger has been evaluated and is active. SQLTag Reference A reference to a SQLTag. Allows a SQLTag to be used in a group like any other item type, except that the tag is evaluated by its scan class instead of by the group. See SQLTags vs. OPC Items below for more information.
Execution Order
Items generally aren't executed in a reliable order, with the exception of Expression items. Expression items can be ordered using the up and down arrows located to the right of the list where the items are displayed. This can be crucial for performing complex operations that require a specific sequence.
Project Design
188
OPC Items are the backbone of a group. They get their values from PLCs and the values are then used by other items the group and/or to write to the database. They are directly subscribed to an OPC server at the rate of the group and are executed by the group so their alerts are evaluated when the group is executed. These items are executed even when the trigger isn't active.
Project Design
189
group is run. Target Name - The name of the column in the database that this Item will write to when the group executes. The Target Name list will populate with all the column names from the Group's target table if the Target Type is Database field.
Alerting:
Alerting settings for the OPC items. See SQLTags Alerting for a full explanation.
4.6.3.4.3 Expression Item
Expression Items are used for executing comparisons, simple math and querying additional database tables. They get their values from an expression made up of static values or other items, or from SQL Queries. They can have alerts and can be executed when the trigger is active or every time the group executes.
Project Design
190
Write Target Target Type - This is the selection for what the Item will write to when the group executes. 1) None, read-only item - Do not write this value to the database. 2) Database field - Write the Item value to the specified column in the database table. 3) Other tag - Write the Expression Item's value back to an OPC item or SQLTag Reference. Target Name - The name of the column in the database that this Item will write to when the group executes. The Target Name list will populate with all the OPC Item and SQLTag Reference names from this Group, or the column names from the Group's target table depending on the Target Type selected.
Numeric:
Numeric properties for Expression Items. See SQLTags Numeric Properties for a full explanation.
Alerting:
Alerting settings for the OPC items. See SQLTags Alerting for a full explanation.
Expression:
Expression/SQLQuery options for Expression Items. See SQLTags Expression/SQL Properties for a full explanation.
4.6.3.4.4 SQLTag Reference
SQLTag References are used just like OPC Items, adding the convenience of using a SQLTag that has already been set up with scaling and alarm data.
Project Design
191
Mode - Options for displaying values based on the Item value. 1) Direct Value - Item value 2) Hour Meter - Record the amount of time the Item value is non-zero. This accumulation will reset to zero when the item value goes to zero. The datatype should be set to integer or float when using an Hour Meter regardless of the OPC Item type. On Zero - Use a zero value to accumulate time instead of a non-zero value Retentive - Retain the Hour Meter value when it is not accumulating. Units - The time units to display. 3) Event Meter - Record the number or times the Item value is non-zero. The datatype should be set to integer when using an Event Meter regardless of the OPC Item type. On Zero - Use a zero value to accumulate events instead of a non-zero value Write Target Mode - Changes the items directional read/write option. This is only editable when the target Type is set to Database field. 1) Use group's mode - Inherit the Update Mode from the Item's Group. 2) OPC to DB - Only read from the OPC server and write to the database. 3) DB to OPC - Only read from the database and write to the OPC Server. 4) Bi-directional OPC wins - Read and Write to both the database and OPC Server. On group start, write OPC Server values to the database. 5) Bi-directional DB wins - Read and Write to both the database and OPC Server. On group start, write database values to the database. Target Type - This is the selection for what the Item will write to when the group executes. 1) None, read-only item - Do not write this value to the database. 2) Database field - Write the Item value to the specified column in the database table. Target Name - The name of the column in the database that this Item will write to when the group executes. The Target Name list will populate with all the column names from the Group's target table if the Target Type is Database field.
4.6.4
4.6.4.1
Types Of Groups
Standard Group The standard group is called such because it's a flexible, general use group that can be adapted to a variety of situations. The data model is row based, with items mapping to columns and the data corresponding to a specific row of a table. General Description The standard group contains items, which may be mapped to the database, or used internally for features such as triggering or handshakes. Items that are mapped to the database target a specific column of a single specific row, chosen according to the group settings. Items can be mapped in a one-way fashion, or bi-directionally, in which the value of the database and the item will be synchronized. The group may also insert new rows instead of updating a specific row. In this manner, data can be inserted for historical purposes based on a timer, with an optional trigger. Group Settings The standard group uses a timer-based execution model shared by all groups, and the normal trigger settings.
Project Design
192
Additionally, there are several settings specific to the group type: Automatically create table - If the target table does not exist, or does not have all of the required columns, it will be created/modified on group startup. If not selected and the table doesn't match, an error will be generated on startup. Store timestamp - Specifies whether or not to store a timestamp with the record, and the target column. The timestamp will be generated by the group during execution. For groups that update a row, the timestamp will only be written if any of the values in the group is also written. Store quality code - If selected, stores an aggregate quality for the group to the specified column. The aggregate quality is the combined quality of all of the items that write to the table. For more information about quality values, see Data Quality Delete records older than - If selected, records in the target table will be deleted after they reach the specified age. This setting is useful for preventing tables from growing in an unbounded manner, which can cause disk space and performance problems over time. Table action - This section details how the group interacts with the table. The group can insert a new row each execution, or update the first, last or custom record. A custom update clause is essentially the where clause of the SQL query that will be generated to read and write the group. In addition to standard SQL syntax, you can bind to items in the group in order to inject dynamic values. Typical Uses Standard groups can be used any time you want to work with a single row of data. This can include: Historical logging - set the group to insert new records, and log data historically either on a timer, or as the result of a trigger. Flexible trigger settings and handshakes make it possible to create robust transactions. Maintain status tables - Keep a row in the database updated with the current status values. Once in the database, your process data is now available for use by any application that can access a database, dramatically opening up possibilities. Manage recipes - Store recipe settings in the database, where you have a virtually unlimited amount of memory. Then, load them into the PLC by mapping DB-to-OPC using a custom where clause with an item binding in order to dynamically select the desired recipe. Sync PLCs - Items in the group can be set to target other items, both for one-way and bidirectional syncing. By adding items from multiple PLCs to the group, you can set the items of one PLC to sync with the others. By creating expression items that map from one PLC item to the other, you can manipulate the value before passing it on. 4.6.4.2 Block Group The block group is so named because it writes "blocks" of data to a database table, consisting of multiple rows and columns. General Description A block group contains one or more block items. Each block item maps to a column in the group's table, and then defines any number of values (OPC or SQLTag items) that will be written vertically as rows under that column. The values may be defined in the block item in two modes. The first, List mode, lets a list of value-defining items to be entered. These value items may either by OPC items, SQLTag items, or static values. The second mode, Pattern mode, can be useful when OPC item paths or SQLTag paths contain an incrementing number. You may provide a pattern for the item's
Project Design
193
path, using the wildcard marker {?} to indicate where the number should be inserted. Block groups are very efficient, and can be used to store massive amounts of data to the database (for example, 100 columns each with 100 rows- 10,000 data points- will often take only a few hundred milliseconds to write, depending on the database). They are also particularly useful for mirroring array values in the database, as each element will appear under a single column, and share the same data type. Like the standard group, the block group can insert a new block, or update the first, last or a custom block. Additionally, the group can be set to only insert rows that have changed in the block. In addition to block items, the group can have other OPC items, SQLTag references, and Expression items. These items can be used for triggers, handshakes, etc. They may also target a column to be written, and will write their single value to all rows in the block. Group Settings Beyond the differences in the data, namely that the block group works with multiple rows instead of just 1, this group type shares many similarities with the Standard Group. The unique settings are: Store row id - Each row will be assigned a numeric id, starting at 0. If selected, this id will also be stored with the data. Store block id - If selected, an incremental block id will be stored along with the data. This number will be 1 greater than the previous block id in the table. Insert new block vs. Insert changed rows - If "insert new block" is selected, each row of the block will be inserted when the group executes, even if the data has not changed. By contrast, "insert changed rows" will only insert the rows that have new data. The latter mode is particularly useful for recording history for many data points on a "on change" basis, provided there is a unique id column defined. The "store row id" feature is useful for this, as well as the ability to reference the item path in an item's value property. Update Custom block - Like standard groups, this setting allows you to target a specific section of the table, using SQL where clause syntax, with the ability to bind to dynamic item values. Unlike standard groups, however, the where clause specified should result in enough rows to cover the block. Excess rows will not be written to, but fewer rows will result in a group warning indicating that some data could not be written.
Typical Uses Block groups are useful in a number of situation where you need to deal with a lot of data efficiently. Mirroring/Synchronizing array values to DB - Arrays are often best stored vertically, which makes them perfect for block groups. Pattern mode makes configuration a breeze by allowing to you specify the array as a pattern, and set the bounds. Recipe management - Like standard groups, but when set points are better stored vertically than horizontally. Vertical history tables - Group data points by data type (int, float, string), create a copy of the item that stores item path, and then use the insert changed rows option to create your own vertically storing historical tables. Create additional copies of the block item that refer to quality
Project Design
194
and timestamp in order to get further information about the data point. 4.6.4.3 Historical Group The historical group makes it easy to quickly log data historically to a SQL database. General Description The historical group inserts records of data into a SQL database, mapping items to columns. Full support for triggering, expression items, hour & event meters and more means that you can also set up complex historical transactions. Unlike the standard group, the historical group cannot update rows, only insert. It also cannot write back to items (besides trigger resets and handshakes). Group Settings The settings of the historical group are identical to the settings in the Standard Group, but limited to inserting rows. Typical Uses Basic historical logging - Recording data to a SQL database gives you incredible storage and querying capabilities, and makes your process data available to any application that has DB access. Shift tracking - Use an expression item to track the current shift based on time, and then trigger off of it to record summary values from the PLC. Use a handshake to tell the PLC to reset the values. 4.6.4.4 Stored Procedure Group The stored procedure group lets you quickly map values bi-directionally to the parameters of a stored procedure. General Description The stored procedure group is similar to the other groups in terms of execution, triggering, and item configuration. The primary difference is that unlike the other group types, the target is not a database table, but instead a stored procedure. Items in the group can be mapped to input (or inout) parameters of the procedure. They also can be bound to output parameters, in which case the value returned from the procedure will be written to the item. Items can be bound to both an input and output at the same time. Group Settings The stored procedure group's settings look and act the same as those of the Historical Group. The primary difference, of course, is that instead of specifying a table name and column names, you'll specify parameter names. Parameters may be specified using either parameter names or numerical index. That is, in any location where you can specify a parameter, you can either use the name defined in the database, or a 0-indexed value specifying the parameter's place in the function call. Important: You cannot mix names and indices. That is, you must consistently use one or the other. If using parameter names, the names should not include any particular identifying character (for
Project Design
195
example, "?" or "@", which are used by some databases to specify a parameter). Typical Uses Call stored procedures - The stored procedure group is the obvious choice when you want to bind values to a stored procedure. It can also be used to call procedures that take no parameters (though this can also be accomplished from Expression Items/SQLTags. Replace RSSQL - The stored procedure group is very popular among users switching from RSSQL, given that application's heavy use of stored procedures. Known Issues When using Oracle, you must use indexed parameters.
4.7
4.7.1
Project Design
196
version of the project if the project is in Push update mode. To alter this behavior, you can put your project in manual publish mode. See Project Versioning for more information.
Preview Mode
The window workspace operates in two distinct modes: design mode and preview mode. You may switch between these modes with the play/stop buttons in the toolbar or the Project > Preview Mode menu item. You may also use the F5 key to toggle between the two modes. In design mode, your mouse is used to manipulate components in a window. You can select, drag, and resize them. You may alter data bindings and event script configuration. Data bindings are active in design mode, but event handlers are not. In preview mode, you are interacting with a "live" version of the window. Property bindings and event handlers will run, just like in the Client. Preview mode is useful for a quick check of the operation of a window, but it becomes cumbersome when trying to test a whole project. For that, we recommend having a launched Client up as well, and doing testing in the true Client. You can quickly launch a client in one of the three launch modes via the Tools > Launch Project menu.
4.7.2
4.7.2.1
Windows
Windows Overview
Creating Windows
Creating windows is a easy as pressing the New Window button in the toolbar, or by navigating to the File > New > Window menu. There are three types of windows you can create: a main window, a popup window, or a docked window. These three windows are described in the typical navigation strategy page.
Window Notes
Through the right-click menu on a window in the Project Browser you can access the window's notes. This free-form text field is provided to let the designer document the purpose and any technical information about how the window works.
Project Design
197
Windows are the top-level unit of design for Vision projects. A window is identified by its path, which is the name of all its parent folders plus its name, with forward slashes (/) in between. For example, the path to a window in the top level called MainWindow would simply be its name, whereas the path to a window named UserOptions under a folder called OptionsWindows would be: OptionsWindows/ UserOptions.
Root Container
Inside a window is always the root container. This is a normal container component except that it cannot be deleted or resized - its size is always set to fill the entire window. The root container is where you will place all of your components in the window. 4.7.2.3 Window Types Windows come in three flavors. By manipulating a window's properties, you can transform any window into various configurations. You can alter a window's Dock Position, Border Display Policy, Titlebar Display Policy, and Start Maximized properties to change it into one of three categories. Main Windows A "main window" window is one that is set to start maximized, and has its border and titlebar display policies set to When Not Maximized or Never. This will make the window take up all available space (minus space used by any "docked" windows). This makes the window act much like a typical "HMI screen." There can by many main windows in a project, but only one should be open at any time. Popup Windows A "popup window" is a window whose Dock Position is set to Floating and is not maximized. Its border and titlebar display policies are usually set to When Not Maximized or Always, so that they can be manipulated by the end-user. These windows are often opened by components in a main window, and are meant to be on top of the screen. To this end, they may have their Layer property set to a number higher than zero so they don't get lost behind the main window. To get a window to pop-up at a specific position, edit the Window's Starting Location property. Popup windows are often parameterized so they can be re-used. Docked Windows A "docked window" is one whose Dock Position is set to anything but Floating. This will make the window stick to one side of the screen, and nothing can overlap it. It will also typically have its border and titlebar display policies set to Never. This makes the "docked" window appear to be joined seamlessly with the current "screen" window. These screens are usually tall and skinny or short and wide, depending on the side they're docked to. The purpose of a docked window is to make some information always available; typically navigation controls and overall status information. Using docked windows can help eliminate repetitive design elements from being copied to each screen, making maintenance easier.
Project Design
198
See also: Typical Navigation Strategy Parameterized Windows 4.7.2.4 Window Properties
Special Properties
Windows have some special properties that you can edit while the window is closed. These properties are modified by right-clicking on the window in the Project Browser. Name Open on Startup "About" Window The name of the window. Must be unique in its folder. Windows with this property set to true will be opened when the project starts up in the Vision Client. At most one window per project may specify an "about" window. This will cause an "About this Application" menu item to appear in the "Help" menu in the Client, which opens the appropriate window.
Dynamic Startup Windows Sometimes a project needs to alter its startup windows depending on who logged in, what security roles the have, or what computer the client is launched on. In these cases, simply set no startup windows, and write a Client Startup Script that uses the system.nav library to open the correct windows.
Standard Properties
These properties are modified in the Property Editor panel, just like a component's properties. Simply select the window either by clicking on its title bar, or clicking on the window's node in the Project Browser while it is open to select it in the Property Editor.
2012 Inductive Automation
Project Design
199
Titlebar Height
Titlebar Font
Behavior Dock Position Determines the position this window is docked to, or if it is floating.
Scripting name Data type Values dockPosition int 0 Floating 3 West 4 South 2 East 1 North
Closable
Determines whether or not to draw the close (X) button in the upper right corner.
Scripting name Data type closable boolean
Maximizable
Determines whether or not to draw the maximize button in the upper right corner.
Scripting name Data type maximizable boolean
Resizeable
Start Maximized
When set to true, the window will become maximized when it is opened.
Scripting name Data type startMaximized boolean
Project Design
200
Cache Policy
By default this property is set to Auto, which keeps a window in a memory cache for a while after it is closed, so that if it is opened again it will be quick. The window isn't "active" while it is closed: all of its bindings and scripts are shut down. Setting this property to Never causes a fresh copy of the window to be deserialized every time it is opened. This is a performance hit, but it also is a convenient way to "clear out" the values of the window from the last time it was opened, which can be helpful in data-entry screens. Setting the property to Always will trade memory for higher performance, causing the window to always remain cached after the first time it is opened. This means the window will open very fast, but your Client will need lots of memory if you do this to a large amount of windows.
Scripting name Data type Flags Values cachePolicy int expert 0 Auto 1 Never 2 Alw ays
Layout Location The location that this window will open up at. Only applicable to floating windows that are not set to start maximized. Also, you must un-check the "Center Window" checkbox on the open-window navigation action in order for this location to take effect
Scripting name Data type startingLocation Point
Size
The dimensions of the window. This can be manipulated by selecting the window and dragging the resize handles along the windows right and bottom edges.
Scripting name Data type size Dimension
Minimum Size
The minimum size that this window will allow itself to be resized to.
Scripting name Data type Flags minimumSize Dimension expert
Maximum Size
The maximum size that this window will allow itself to be resized to.
Scripting name Data type Flags maximumSize Dimension expert
Layer
Sets the layer that this window is in. Default layer is 0, which is the bottom layer. Windows in higher layers will always be shown on top of windows in layers beneath them.
Scripting name Data type Flags layer int expert
Project Design
201
4.7.2.5
Window Security You can configure security settings that control who can and who can't open a window. While the window is open, select it by clicking on the title bar or selecting its node in the Project Browser. Then navigate to the Component > Component Security menu. Window security is configured the same way that Component Security is configured.
4.7.2.6
Typical Navigation Strategy Make sure you understand the Window Types topic before reading this topic. The typical navigation strategy for a Vision project is to have a "docked" window or two (usually docked north and/or west), and then have a single main window visible at a time. Swap navigation is used to swap between the main windows. This ensures that only one main window is open at a time. Standard open navigation is then used to open various "popup" windows as necessary. This style of project is so common, that the default operation of the Tab Strip component expects it. When it is in its default automatic operation, it expects that each tab represents a "screen" window, and will automatically swap from the current screen to the desired screen. Furthermore, the [System]/ Client/User/CurrentWindow tag is calculated based upon this strategy: its value is the name of the current maximized window. This navigation strategy is used in the "ExampleProject" that you can download from our website.
4.7.2.7
Swapping vs Opening There are two primary window navigation operations: swapping and opening.
Swapping
In general, swapping involves closing one window, and then opening another window in its place. This operation can be performed on window in any state: docked or floating, maximized or not. The Start Maximized and Dock Position properties of the window that is being swapped in will be ignored - it will take the dock and maximized state of the window that it is replacing. This operation is so common in the typical navigation strategy that there is even a version of swapping dedicated to it, the swapTo function. This function eliminates the need to specify the window to swap from - you only need to specify the window to swap to. It will take the current "screen" window - that is, the current maximized window - as the window to swap from. See also: system.nav.openWindow system.nav.swapWindow system.nav.swapTo
Project Design
202
4.7.2.8
Open Windows and Performance While a window is open, its query bindings are running, its tag bindings are keeping tags subscribed, and its event scripts are being executed. This means that an open window is actively using system resources, both on the Client's host machine, and on the Gateway's server machine as its queries and tag subscriptions must be handled. For these reasons, it is important that you properly implement a navigation strategy that prevents windows that are no longer being used from being held open. The most common mistake that will cause windows to stay open unintentionally is to implement a swapping navigation system using the swapTo function on windows that are not maximized. When you do this, the swapTo function cannot calculate the window to swap from, thereby simply opening the window, and not closing any windows. It is easy to check the Windows menu to see what windows are currently open. If there are more windows listed there than you can currently see, there is a problem in your navigation logic that is failing to close windows properly.
4.7.2.9
Parameterized Windows It is often useful to create a parameterized window that can be re-used for multiple purposes, depending on the values that were passed into it when it was opened. For example, suppose you have 10 compressors, and the tags that represent them are predictable based upon the compressor number. Compressors/ C1/ HOA Amps C2/ HOA Amps ... C10 HOA Amps You could make a single compressor status & control screen, and simply pass the relevant compressor number to it when you open it. Passing Parameters Any custom property on the root container of a window can be used as a window parameter. Simply specify the names of the custom properties to set in the call to openWindow to use them as parameters. Then, use the custom property to create indirect property bindings that bind to the appropriate spot. For example, let's suppose that you had a window called CompressorPopup that you wanted to use to control all 10 compressors. You'd put a custom property on your compressor control window called compNum. You would use compNum in your tag bindings for the controls on your screen using indirect tag bindings. For example, you might bind the control and indicator properties of a Multi-State Button to an indirect tag binding like: Compressors/C{1}/HOA where the {1} paremeter is bound to the property path: Root Container.compNum You could use a similar indirect binding to display the amperage in an analog Meter component. Now, when opening the window, you could use a script like this to open it to control compressor #6. Of
2012 Inductive Automation
Project Design
203
course, you probably wouldn't write this script by hand, you'd use the navigation script builder. But it is useful to know what the script would look like.
system.nav.openWindow("CompressorPopup", {"compNum":6})
Opening Many Copies By default, opening a window will only ever open one copy of any given window. If the window is already open, it simply brings it to the front. Normally this is the desired behavior. For example, if you opened the compressor popup window for compressor #6, and then opened it for compressor #4, the window that had been controlling #6 will switch to controlling #4. Sometimes you may want to open a separate popup, one for #6, and one for #4, both at the same time. If this is the case, use the system.nav.openWindowInstance function call to open your window.
4.7.3
4.7.3.1
Components
Introduction Components are what fill up your windows with useful content. Anyone familiar with computers should already understand the basic concept of a component - they are the widgets that you deal with every day - buttons, text areas, dropdowns, charts, etc. The Vision module comes with a host of useful components out of the box, many of which are specialized for industrial controls use. Other modules, like the Reporting module, add more components for specialty purposes. Configuring components will likely be the bulk of a designer's work when designing a Vision project. The basic workflow is to take a component from the palette and drop it into a container on a window. From there, you can use the mouse to drag and resize the component into the correct position. While the component is selected, you can use the Property Editor panel to alter the component's properties, which changes the component's appearance and behavior. Shapes are components too. Each shape may be individually selected, named, and has its own properties. Shapes have some additional capabilities that other components don't have, such as the ability to be rotated. Shapes are created using the shape tools, not dragged from the component palette. To make the component do something useful, like display dynamic information or control a device register, you configure property bindings for the component. To make the component react to user interaction, you configure event handlers for it.
4.7.3.2
Create a component
There are two primary mechanisms for creating components: 1. Select the component in the palette, and then use the mouse to draw a rectangle in a container.
Project Design
204
While a component is selected in a palette, the mouse curser will be a crosshair ( ) when hovering over a container that the component can be dropped in. Draw a rectangle in the container to specify where the component should be placed and what size it should be. 2. Drag a component's icon from a palette onto a container. The component will be placed where you dropped it at its default size. It can then be resized.
4.7.3.2.2 Shape Tools
Shapes such as lines, rectangles and circles are created using the shape tools. By default the shape toolbar appears alongside the right-hand edge of the Designer window, but you can drag it to wherever you prefer. There are a number of tools here for your use, and each one makes the window editing workspace act differently when active. Shape tools allow you to create various shapes as well as edit them after they are created. Click on the tool's icon to make it the active tool. You can also double-click on a shape to change to that shape's native tool. When a shape tool is active, a toolbar will appear that has specific actions and settings for that tool. After a shape is created, you can change it's fill color, stroke color, and stroke style. See Fill and Stroke for more. All shapes can be treated as paths and be used with composite geometry functions to alter or create other shapes. See Geometry and Paths for more. Selection Tool Normally the selection tool ( ) is active. When this tool is active, you can select shapes and components. Selected components can be moved, resized, and rotated. For more on using the selection tool to manipulate components and shapes, see Manipulating Components. Rectangle Tool The rectangle tool ( ) creates and edits rectangle shapes. To create a rectangle, select the tool and drag inside a window to create a new rectangle. Hold down ctrl to make it a perfect square. Once a rectangle is created, you can use the square handles to change the rectangle's height and width. This is important because it is the only way to resize a rotated rectangle and let it remain a rectangle. If you resize a non-orthogonally rotated rectangle using the selection tool, it will skew and become a parallelogram, but if you double-click on it so that the rectangle tool is active, you can change the rectangle's width and height using the tool-specific handles. There are also small circle handles that allow you to alter the rectangle's corner rounding radius. Simply drag the circle down the side of the selected rectangle to make it a rounded rectangle. Hold down control to drag each rounding handle independently if you want non-symmetric corner rounding. You can use the Mak e Straight button in the rectangle tool's toolbar ( ) to return a rounded rectangle to be a standard, straight-corner rectangle. Ellipse Tool The ellipse tool ( ) creates and edits circles and ellipses. It is used in much the same way as the rectangle tool. While it is the active tool, you can drag inside a window to create a new ellipse. Hold down ctrl to make it a perfect circle. When an ellipse is selected, use the width and height handles to alter the shape. Polygon / Star Tool The polygon tool ( ) is used to create polygons and stars. Use the toolbar that becomes visible when
2012 Inductive Automation
Project Design
205
this tool is active to alter the settings of the shape that is created when you drag to create a polygon. This tool can be used to make any polygon with 3 corners (a triangle) or more. Once created, you can use the center square handle to move the polygon around, and the diamond handles to alter the size and angle of the polygon. Hold down ctrl to keep the polygon's rotation an even multiple of 15. Arrow Tool The arrow tool ( ) is used to create single or double-sided arrow shapes. When it is active, simply drag to create a new arrow. Use the checkbox on the toolbar to choose a single or double-sided arrow. To alter the arrow, use the diamond handles to change the two ends of the arrow, and the circle handles to change the size of the shaft and the head. When changing the arrow's direction, you may hold down ctrl to snap the arrow to 15 increments. Pencil Tool The pencil tool ( ) is used to draw freehand lines and shapes. When this tool is selected, you can draw directly on a window by holding down the mouse button. Release the mouse button to end the path. If you stop drawing inside the small square that is placed at the shape's origin, then you will create a closed path, otherwise you'll create an open path (line). On the pencil tool's toolbar, there are options for simplification and smoothing, as well as a toggle between creating straight line segments or curved line segments. The simplification parameter is a size in pixels that will be used to decrease the number of points used when creating the line. Points will be in general as far apart as this setting. If you find the line isn't accurate enough, decrease this setting. If you choose to create curved segments, then the segments between points will be Bzier curves instead of straight lines. The smoothing function controls how curvy these segments are allowed to get. Line Tool The line tool ( ) can be used to draw lines, arbitrary polygons, or curved paths. Unlike all of the other tools, you don't drag to create new paths with the line tool. Instead, you click for each vertex you'd like to add to your path. To draw a straight line, simply click once where you want the line to start, and double-click where you want the line to end. To make a multi-vertex path, click for each vertex and then double click, press enter, or make a vertex inside the origin box to end the path. As you draw the line, "locked-in" sections are drawn in green and the next segment is drawn in red. Hold down ctrl at any time to snap the next segment to 15 increments. On the line tool's toolbar, you can choose between three modes: normal line mode, perpendicular mode, and curve mode. Perpendicular mode is just like line mode except that each segment is restricted to either horizontal or vertical. Curve mode will create a Bzier curve path by attempting to draw a smooth curve between the previous two vertices and the new vertex. Path Tool All shapes and paths can be edited directly by using the path tool. This tool lets you directly modify the nodes in the path, adding new nodes, removing nodes, and toggling segments between straight or curved. Learn more about paths in the Geometry and Paths section. Gradient Tool The gradient tool is used to affect the orientation and extent of any gradient paints. Learn more about gradients in the Fill and Stroke section.
Project Design
206
Eyedropper Tool The eyedropper tool is used to set the selected shape(s) and/or component(s) foreground/background or stroke/fill colors by pulling the colors from somewhere else in the window. When this tool is active, leftclick to set the selection's fill or background, and right-click to set the selection's stroke or foreground. Note that this tool works on most components as well as shapes. For example, right-clicking will set the font color on a Button, or left-clicking will set the background color.
4.7.3.2.3 Custom Palettes
Custom palettes are like expanded copy/paste clipboards. They allow you to put customized components or groups of components into a palette for quick access. To create a custom palette, right click on a tab in the tabbed palette or a header in the collapsible palette, and choose New Custom Palette. Your custom palette will appear as the last palette. Your custom palette has one special button in it, the capture button ( ). To add components to your palette, select them and press the capture button. This effectively does a copy, and stores the captured components as a new item in the clipboard. You can then use that item much like a normal component, and add multiple copies of it to your windows. Note that these are simple copies, and are not linked back to the custom palette. Re-capturing that palette item will not update all uses of that item across your windows.
4.7.3.2.4 SQLTags Drag-n-Drop
Components can also be created by simply dragging a SQLTag onto a container. Depending on the datatype of the tag, you will get a popup menu prompting you to select an appropriate type of component to display or control that tag. For example, suppose you have an Int4 type tag, If you drag the tag from the SQLTags Browser panel onto a component, you will be prompted either to display or control the tag with a variety of labels, level indicators, numeric entry fields, and control buttons. This technique is great for beginners and for rapid application design. By dropping a SQLTag into a container and choosing a component type, a few steps are happening: The component that you chose is created at the position you dropped it. A variety of property bindings are created automatically. The bindings depend on what kind of tag was dropped and what kind of component was created. For example, lets suppose you have a Float8 point that represents a setpoint, and you want to set it. Drop the tag onto a container and choose to control it with a Numeric Text Field. The following bindings will be set up automatically o The text field's doubleValue property gets a bidirectional tag binding to the tag's Value property. o The text field's minimum and maximum properties get tag bindings to the tag's EngLow and EngHigh properties, respectively. o The text field's decimalFormat property gets a tag binding to the tag's FormatString property. o The text field's toolTipText property gets a tag binding to the tag's Tooltip property It is important to realize that multiple property bindings are created when creating components this way. These bindings not only use the tag's value, but much of the tag's metadata as well. Using the tags metadata in this way can greatly improve a project's maintainability. For example, if you decide that the setpoint needs 3 decimal places of precision, you can simply alter the tag's FormatString to be #, ##0.000, and anywhere you used that tag will start displaying the correct precision because of the metadata bindings.
Project Design
207
See also: Property Binding Overview SQLTag Metadata Properties 4.7.3.3 Selecting Components There are a number of different ways to select components within a window, each of which have their own advantages.
Mouse Selection
Using the mouse is the most common way to select components. Make sure that the selection tool ( ) is the active tool. Simply click on a component to select it. If the component you want to select is obscured by other components, hold down alt and keep clicking, the selection will step down through the z-order. You can also select components using window-selection. Click-and-drag in a container to draw a selection rectangle. If you drag the window left-to-right, it will select all components that are contained within the rectangle. If you drag the window right-to-left, it uses window-crossing selection. This will select all components that are contained within the rectangle or intersect the edge of the rectangle. Lastly, you can start dragging a window selection and then hold down the alt key to use touchselection. This will draw a line as you drag, and any components that the line touches will become selected. As you're using these techniques, components that are about to become selected will be given a yellow highlight border.
Tree Selection
By selecting nodes in the project browser tree you can manipulate the current selection. This is a handy way to select the current window itself, which is hard to click on since it is behind the root container. (you can click to it though, using alt-click to step down through the z-order). It is also the only way to select components that are invisible. 4.7.3.4 Manipulating Components Manipulating components can be done with both the mouse and the keyboard. To manipulate a component or group of components, you'll first need to select them.
Resizing
Once the components you want to alter are selected, they'll gets 8 resize-handles displayed around the edge of the selection. These handles look like double-sided arrows around the perimeter. Use the mouse to drag them to change the size of the components in the selection. To maintain the selection's aspect ratio, hold down ctrl as you resize. To resize around the center of the current selection, hold down shift. You can also resize the current selection using the keyboard. To nudge the right or bottom edge of the selection in or out, use shift combined with the arrow keys. To nudge the top or left edge of the selection, use ctrl-shift combined with arrow keys. These nudge actions will resize one pixel at a time. To resize faster, add the alt key.
Moving
To move the component, simply drag it anywhere within the component's bounds. You can also move
Project Design
208
whatever is currently selected by holding down alt while dragging, regardless of whether or not the mouse is over the current selection. This is important because it is the primary way to move a Container component. (Normally, dragging in a container draws a selection rectangle inside that container). While a component is selected, you may also use the keyboard's arrow keys to move a component around. The arrow keys will move the selection one pixel at a time. Just like resizing with the arrow keys, to move faster, add the alt key. Components can be easily duplicated by dragging them as if you were going to move them and holding down the ctrl key. This will drop a copy of the component at the desired drop location. It is often useful to also hold down shift as you do this to ensure exact alignment. You may also use the ctrl-D shortcut to quickly duplicate a component in place.
Rotating
Shapes can be rotated directly using the selection tool. Other components cannot be rotated in this manner. To rotate a shape, first select it using the selection tool so that you see the resize handles around it. Then simple click on it once again and you'll see the rotation handles appear. Clicking (but not double-click ing) on selected shapes toggles back and forth between the resize handles and the rotation handles. Once you see the rotation handles, simply start dragging one to rotate the shape or shapes. Holding down the ctrl key will snap your rotation movements to 15 increments. When the rotation handles are present, there is also a small crosshair handle that starts in the middle of the selection. This is the rotation anchor: the point that the selection will rotate around. You can drag it anywhere you'd like to rotate around a point other than the center of the shape.
Project Design
209
4.7.3.5
Keyboard Shortcuts
Project Design
210
4.7.3.6
Properties Each component has a unique set of properties. A property is simply a named variable that affects something about the component's behavior or appearance. Each property has a distinct type. Hover your mouse over the property in the Property Editor panel to see its data type and scripting name.
4.7.3.7
The Property Editor The property editor is a dockable panel that appears in the window workspace, usually under the SQLTags Browser panel. It displays the properties of the selected component. If more than one component is selected, then it will show all properties that the current selection set have in common.
Filters
Project Design
211
It is common for components to have many properties, so the property editor by default only shows the basic properties. These are the properties that you'll most commonly want to set or bind for a given component. There is also the standard properties. This is a larger set of properties that includes the basic properties and many other useful properties. Some properties are expert properties. These are properties that are either uncommon to set or whose purpose might require an in-depth understanding of the inner-workings of the component. You can change the filter using the filter button ( ) in the property editor's toolbar.
Status Indication
The name of a property in the property editor conveys important information about that property: A blue name indicates that the property is a custom property. A bold name with a link icon indicates that the property is bound using a property binding. A bold name with a color palette icon indicates that the property is being affected by the component's styles settings. A red bold name with a warning icon indicates that the property is double-bound. This means that two things, a property binding and the styles settings are both trying to drive the property value. This is almost assuredly a mistake.
Editing Paints
Both the fill and stroke paints can be a variety of different kinds of paints. To edit a shape's fill or stroke paint, you can either use the paint dropdown in the property editor table by clicking on the pencil icon ( ) or open up the dedicated Fill and Stroke panel from the View menu.
Project Design
212
Paint Types
The top of the paint editor is a selection area that allows you to choose between the five different kinds of paints.
The five different paint types dem onstrated as triangle fill paints.
1. The first paint type is no paint ( ). If used as a fill paint, then the interior of the shape will be transparent. If used as the stroke paint, then the paint's outline will not be drawn at. 2. The second paint type is a solid color ( ). This paint type is equivalent to the Color type used elsewhere throughout the component library. A solid color is any color, including an alpha (transparency) level. 3. The third paint type is a linear gradient ( ). Linear gradients smoothly blend any number of colors along a straight line across the shape. Each color is called a Stop. Each stop is represented as a drag-able control on a horizontal preview of the gradient in the gradient editor. You can click on a stop to select it and change its color or drag it to reposition it. You can right click on it to remove it. You can right click on the preview strip to add new stops and change the gradient's cycle mode. 4. The fourth paint type is the radial gradient ( ). Radial paints are very much like linear paints except that the colors emanate from a point creating an ellipse of each hue. Radial paints are configured in the same way as linear paints. 5. The fifth paint type is the pattern paint ( ). This paint uses a repeating pixel-pattern with two different colors. You can pick a pattern from the dropdown or create your own using the built-in pattern editor. Gradient Paint Bounds The two gradient paints are more than a list of colored stops; they also need to be placed relative to the shape. The same gradient may look wildly different depending on how it is placed against the shape. By default, a linear gradient will run horizontally across the width of the entire shape, but this is readily changed. By switching to the Gradient Tool ( ), you can drag around handles that control how the gradient is applied.
Gradient Cycles The two gradient paints (linear and radial) both have a cycle mode that you can change by right-clicking within the preview strip. The cycle modes are illustrated below:
Project Design
213
1. No Cycle. The first and last stops are repeated forever after the edge of the paint bounds. 2. Reflect. Beyond the bounds of the paint, it will be reflected and drawn in reverse, and then reflected again, creating a smooth repetition. 3. Repeat. Beyond the bounds of the paint, it will be repeated forever.
Stroke Style
A shape's stroke paint is only half the story. The stroke style is also an important component of how an outline is drawn. Primarily the style controls the thick ness of the line drawn, but it also can be used to create a dashed line. The setting for thickness is specified in pixels, and creating a dashed line is as easy as picking the style from the list. The effect the thickness and dash pattern settings is fairly self-explanatory, but the other stroke settings are a bit more subtle. You can notice their effect more readily on thick lines.
Cap style is a setting that controls what happens at the end of a line segment. You can either have the line simply be terminated with no decoration (#1), Round off the end with a semi-circle (#2), or cap the end with a square (#3).
Cap styles
Join styles
Join style is a setting that affects how a line is drawn where two segments meet ( a corner ). The default setting is called a miter join (#1), where the stroke is extended into a point to make a sharp corner. The other options are rounded corners (#2) or beveled edge corners (#3).
Miter style joins can become a problem for very sharp angles. With a sufficiently sharp angle, the miter decoration can become extremely long. To control this, there is a miter length setting to limit the length of a miter decoration. The illustration on the left shows the same miter join with two different miter length settings. The first drawing illustrates the length of the miter join.
4.7.3.9
Geometry and Paths All of the basic shapes, as well as anything created with the pencil or line tool, can be considered to be a path. A path is a series of points and segments between those points. Any two points can either be disconnected (no line between them), connected with a straight line segment, or connected with a Bzier curve.
Project Design
214
Bzier Curves
A Bzier curve, also sometimes called a quadratic curve, is a type of curve used in vector graphics that connects two points. A Bzier curve is configured using four points: the two end-points and two control points. The curve starts along the line between the an endpoint and the first control point, and then curves to smoothly meet the line between the second control point and the other endpoint.
Project Design
215
Union The union function combines two or more paths into one. The resulting shape will cover the area that any of the shapes covered initially. The example shows how the union of a circle, rectangle, and triangle can be unioned together to create a basic pump symbol. Creating the symbol using this method took a few seconds, whereas attempting to draw this shape by hand using paths would be quite frustrating.
Difference The difference function can be thought of as using one shape as a "hole-punch" to remove a section of another shape. The example shows how a zigzag shape drawn with the line tool can be used to punch a cutaway out of a basic tank shape. The level indicator is added behind the resulting shape to show how the area where the zigzag shape was is no longer part of the tank shape.
Intersection The result of an intersection function will be the area only where where two shapes overlap. The example shows how the "top" of the tank in the difference example was easily made using two ellipses.
Exclusion The exclusion function, sometimes called X-OR, creates a shape that occupies the area covered by exactly one of the source shapes, but not both.
Project Design
216
Division The division function divides or cuts one shape up along the outline of another shape.
4.7.3.10 Data Types There is a wide variety of datatypes across all of the Vision Module's components. Here are the most common types that you'll find. Numeric Types Boolean Short Integer / int Long Float Double
A true/false value. Modeled as 0/1 in Python. Technically, 0 is false and anything else is true. A 16-bit signed integer. Can hold values between -215 and 215-1. Thats -32,768 to 32,767, inclusive A 32-bit signed integer. Can hold values between -231 and 231-1. Thats -2,147,483,648 to 2,147,483,647 inclusive A 64-bit signed integer. Can hold values between -263 and 263-1. Thats -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 inclusive A 32-bit signed floating point number in IEEE 754 format. A 64-bit signed floating point number in IEEE 754 format.
Non-Numeric Types String A string of characters. Uses UTF-16 format internally to represent the characters. Color A color, in the RGBA color space. Colors can easily be made dynamic or animated using Property Bindings or Styles Date Represents a point it time with millisecond precision. Internally stored as the number of milliseconds that have passed since the "epoch", Jan 1st 1970, 00:00:00 UTC. Dataset A complex datastructure that closely mimics the structure of a database table. A Dataset is a two-dimensional matrix (a.k.a. a table) of data organized in columns and rows. Each column has a name and a datatype. Font A typeface. Each typeface has a name, size, and style. Border A component border is a visual decoration around the component's edges. You can make a border dynamic by using Styles or the toBorder expression.
2012 Inductive Automation
Project Design
217
Whats the difference: Integer vs int? The difference is that an Integer property will accept the special null (or None in Python-speak) value, while an int property will not. This distinction holds true for all of the numeric types: the type name that starts with a capital letter accepts null, while the alllowercase version does not. Expert Tip: Most of these datatypes are actually defined by Java. For example, the Date datatype is really an instance of a java.util.Date. This means that you can use the java.util.Calendar class to manipulate them, and the java.text.SimpleDateFormat class to format and parse them. Learn more about these classes in the Java 2 Platform online documentation at http://java.sun.com/ j2se/1.5.0/docs/api/index.html See also: Working with Different Datatypes 4.7.3.11 Component Customizers In addition to their properties, many components can be further customized using a Customizer. Many components will have more than one customizer. You can open the customizer for any component by right-clicking on it and choosing the Customizers menu, or by using the customizer split-button ( ) in the Vision main toolbar. Customizers are used to configure components in ways that are too complex or cumbersome for basic properties. Some customizers are used repeatedly for many different components, for example, the "Custom Properties" customizer and the "Styles" customizer. Other customizers are unique for their component, for example the "Easy Chart" cutsomizer or the "Report Designer" customizer. Expert Tip: Often, a customizer is really just a user-friendly user interface to one or more expert properties. For example, all the Easy Chart customizer really does is modify the contents of the pens, tagPens, calcPens, axes, and subplots Dataset properties. Knowing this is very powerful, because this means you can also use Property Bindings and scripting to modify the values of these expert properties at runtime, giving you the ability to dynamically perform complex manipulations of components. 4.7.3.12 Custom Properties Most Vision components support custom properties. This means that in addition to the normal properties of the component, you can add your own properties. You can think of these properties like your own variables in the window.
Project Design
218
things based on the state being 0, 1, or 2 (maybe for a Hand/Off/Auto indicator) Now, we could have used the Multi-State Indicator from the get-go, but understanding this example will let you create your own types of components by combining the existing components in creative ways.
4.7.3.14 Quality Overlays Sometimes things don't go quite as expected. Connections get broken, switches die, machines crash. Aside from taking reasonable steps to prevent these occurrences, it is especially important in HMIs to be able to gauge the health and accuracy of what is displayed at a glance. In a highly distributed system like Ignition, it is especially important, as the client may be located at quite a distance (maybe across the world) from the physical process it is monitoring and controlling. For these reasons, components will get visual overlays for various reasons to indicate that the data they are displaying is not good. Each data binding that drives a component is evaluated for quality. If any of these qualities becomes poor, the component will show an overlay. The different overlays can mean different things, denoting their underlying cause. These follow the Quality properties of SQLTags.
Project Design
219
4.7.3.15 Touchscreen Support It is very common to deploy Ignition Vision projects on touchscreen computers. Often, these are industrial panel-pcs acting as HMI or OIT terminals. Normally touchscreens simply act like a mouse input device. However, these touchscreens usually don't have a keyboard attached. For this reason, all of the input components in Vision are touchscreen-enabled. Under normal circumstances, you don't have to do anything special other than enable touchscreen-mode on your project. This will allow the operator to enable touchscreen mode when they log in. You can also enable touchscreen mode via scripting. Touchscreen-enabled input components all have an expert level property called Touchscreen Mode. Normally, this is set to Single-Click , meaning that the touchscreen keyboard or numeric keypad (depending on the type of input component) will appear on a single click in that component. You can also change this to Double-Click , which should be self-explanatory, or None. None means that automatic touchscreen support is disabled for this component. You may want to set this to handle touchscreen logic via scripting. To handle touchscreen logic via scripting, the general pattern is to respond to a mouse event, popup up
2012 Inductive Automation
Project Design
220
a keyboard, and then set the component's value to whatever was entered in the keyboard. For example, for a text field, you would write a script like this:
if system.gui.isTouchscreenModeEnabled(): currentText = event.source.text newText = system.gui.showTouchscreenKeyboard(currentText)
See also: Client General Properties system.gui.setTouchscreenModeEnabled 4.7.3.16 Component Layout Layout is the concept that a component's size and position relative to its parent container's size and position can be dynamic. This allows the creation of windows that resize gracefully. This is a very important concept because of the web-launched deployment of Vision clients - they often end up being launched on many different monitors with many different resolutions. This is also important for components that have user-adjustable windows like popup windows. Imagine a popup window that is mostly displaying a large table or chart. If you're running on a large monitor, you may want to make the window bigger to see the table or chart easier. Of course, this is only useful if the table or chart actually gets larger with the window. Changing a component's layout is as simple as right-clicking on the component and opening the Layout dialog box. You can also alter the default layout mode that gets assigned to new components. See Designer Window Editing Properties.
Note that relative layout mode respects aspect ratio. So if the parent component is distorted, the contents will not be. The extra space is distributed evenly on both sides of the contents.
Project Design
221
Anchored Layout Anchored layout lets you specify various "anchors" for the component. The anchors dictate how far each of the 4 edges of the component stay from their corresponding edges in the parent container. For example, if you anchor top and left, then your component will stay a constant distance from top and left edges of its parent. Since you didn't specify an anchor for the right or bottom sides, they won't be affected by the layout.
If you anchor bottom and right instead, the components will again stay the same size (since you didn't specify an anchor for their other edges, but they will stay a constant distance from their parent's right and bottom edges.
Project Design
222
Of course, you can mix and match the various modes. There are also special centering anchors. The following image shows the following: The square uses a horizontal and vertical centering anchor. It is centered, and stays the same size. The triangle is anchored bottom and west. The circle is anchored top, left, bottom, and west. This means that its edges are all anchored and stay a fixed distance to each of its parent's edges, so it grows.
Project Design
223
to the shape's parent container's width and height, even in a running client where that container may be a wildly different size due to the layout mechanism. For example, let's say that you have a shape that is located at x=100, y=100, and was 125 by 125 inside a container that is 500 by 500. If you want to animate that shape so that it moves back and forth across the screen, you'd set up a binding so that relX changed from 0 to 375. (You want X to max out at 375 so that the right-edge of the 125px wide shape aligns with the right edge of the 500px container). Now, at runtime, that container might be 1000 by 1000 on a user's large monitor. By binding relX to go between 0 and 375, the true X value of your shape (whose width will now be 250px due to the relative layout system), will correctly move between 0 and 1750, giving you the same effect that you planned for in the designer. Long story short, using the rel* properties let you animate the shape using bindings and not worry about the details of the layout system and how they'll resize the coordinates at runtime. Binding Rotation Another ability unique to shapes is the ability to be rotated. Simply click on a selected shape and the resize controls become rotate controls. There's even a rotation property that can be edited directly or bound to something dynamic like a tag. Binding the rotation comes with one big warning, however. Observe that when you change a shape's rotation, it's position also changes. (The position of any shape is the top-leftmost corner of the rectangle that completely encloses the shape)
Because of this effect, if you wish to both dynamically rotate and move a component, special care must be taken since rotation alters the position. You don't want your position binding and the rotation binding both fighting over the position of the component. The technique to both rotate and move a shape is as follows: 1. Bind the rotation on your shape as you wish. 2. Create a shape (e.g. a rectangle) that completely encloses (in other words, it's bigger than) your shape at any rotation angle. 3. Set that rectangle's visible property to false. 4. Select your shape and the rectangle and group them.
2012 Inductive Automation
Project Design
224
5. Bind the position on the resulting group. If you follow these steps you can animate both the rotation and position of a shape. 4.7.3.18 Grouping Shapes and components can be grouped together so that they act like a single component in the Designer. Grouping components is very similar to putting them in a Container. In fact, it is the same thing as cutting and pasting them into a perfectly-sized container and then putting that container into group mode, with one exception. If the group contains only shapes and no other kinds of components, it will be a special shape-group that has the ability to be rotated and has some other shape-like properties. When components or shapes are in a group, clicking on them in the Designer will select the group instead of the shape. If you double-click on a group, it will become "super-selected", which will allow you to interact with its contents until you select something outside of that group. Layout also works differently for groups. The layout setting for components and shapes inside a group is ignored. All members of a group act as if they are in relative layout with no aspect ratio restrictions. This special group-layout mode is also active when resizing a group inside of the Designer, whereas traditional layout doesn't take effect in the Designer. Groups can contain other groups, creating a nested structure. Groups themselves are also components, meaning that you can add custom properties to groups, bind them, etc. 4.7.3.19 Using Symbol Factory If you have the Symbol Factory module installed, you've got nearly 4,000 industrial symbols at your fingertips. The first step to using the Symbol Factory is to open up the Symbol Factory browser. To do this first launch a Designer. Once the Designer has your project open, choose Symbol Factory under the Tools menu or the project navigation tree. If you can't find these, the Symbol Factory module probably isn't installed. The Symbol Factory browser opens as a pop-up window that stays on top of the Designer. You can browse the different categories to explore what symbols are available, or search to find a specific symbol. When you find a symbol that you'd like to use, you can simply drag it onto an open Vision window. From there, the symbol will become a group of shapes. Just like any group, you can doubleclick on it to get to the shapes inside, or simply un-group it. This way you can edit the symbol if you need to. Note: If the Symbol Factory module is in trial mode, you'll only be able to use the first symbol from each category.
Project Design
225
5. Bind the Fill Paint property to your ValveStatus tag. Add three entries into the number-tocolor translation table: fully transparent for zero, 40% opaque green for 1, and 40% opaque red for 2.
In summary, what we did to tint the symbol was to make a flat shape that had the exact same outline as the symbol, and use semi-transparent fills to achieve a tint effect for the underlying symbol.
4.7.4
4.7.4.1
Templates
Introduction Templates are a simple but very powerful feature that you can use with your Vision windows. HMI and SCADA systems typically have quite a bit of repetition in their screens. For example, you might use a group of the same components over and over within your project to represent different motors. The data driving each set of graphics is different, but the graphics themselves are copies of each other. Without templates, the only way to do this is to copy-and-paste the components each time you want to represent a motor. This is simple, and it works, but it can cause major headaches and time consuming corrections later on. If you ever want to make a change to how motors are represented, you're stuck
Project Design
226
making the change to each copy of the group. Using templates, you define the graphics to display a motor in one place, called the master template. You can then use this template many times in your project on multiple windows. These are called template instances. Any changes made to the master template are then instantly reflected in all of the template instances. Using templates early in your project development for any repeating displays can save a significant amount of time later on. 4.7.4.2 Using Templates Creating and using templates is very simple, and should be familiar to anyone who has designed Vision windows before. You should have the project you'd like to add a template to open in the Designer before you begin.
Editing a Template
You can open a template for editing by double-clicking on it in the project browser, or by double-clicking any instance of that template within a window. You design your template in the same way that you design windows: by adding components to it, and configuring those components using property bindings and scripting. There are a few differences between templates and windows from an editing perspective. Templates, unlike windows, have a transparent background by default. This can be changed simply by editing the background color of the template. Templates also do not have the concept of a "Root Container" - the template itself acts like a container.
Project Design
227
Project Design
228
4.7.5
4.7.5.1
Property Binding
Overview Property Binding is perhaps the most important concept to understand when designing a project using the Vision module. It is primarily through property binding that you bring windows to life, and have them do useful things. When you initially place a component on a screen, it doesn't really do anything. Changing its properties in the designer will make it look or act different, but it has no connection to the real world. This is what property binding adds. Property binding, as its name suggests, lets you bind a property to something else. That something else might be: an OPC Tag the results of a SQL query executed against a remote database some other component's property an expression involving any of these things the results of a Python script etc... For example, bind the value property of an LED Display to an OPC SQLTag, and voil - the value property will always be the value of that tag - creating a dynamic display. Bindings can also work the other way, using a bidirectional binding. Bind the value of a numeric text box to a tag, and that tag will be written to when someone edits the value in the text box. The power of property bindings comes from the variety of different binding types that exist, and the fact that you can bind nearly any property of a component to anything else. Want it's foreground to turn red when an alarm is above a certain severity? Bind its LED Lit (glyphForeground) color to a tag's AlertCurrentSeverity property. Want it to only appear if a supervisor is on shift? Bind its visible property to the result of a SQL query that joins a personnel table with a shift table. The possibilities are, quite literally, endless. How Bindings Work: Event-based vs Polling While there are quite a few different binding types, they all boil down into two broad categories. Some complex bindings can span both categories. Event-based bindings are evaluated when the object they are bound to changes. For example, when you bind a property to a SQLTag, that binding listens to the SQLTag, and every time the tag changes, it assigns the tag's new value into the property that it is on. If you bind the value of a Cylindrical Tank to the value of a Slider, then every time the slider changes, it fires a propertyChangeEvent. The binding is listening for this event, and when it is fired, updates the tank's value. The following bindings are event-based: Tag bindings Property bindings Polling bindings are evaluated when a window first opens, on a timer, or when they change. For example, if you bind the data property of a Table to the results of a SQL query, that query will run on a timer, updating the Table every time it executes. The following bindings are based on polling: SQL query bindings some expression functions, like runScript() or now() Many bindings can combine elements of a polling binding and event based binding. An expression binding may combine lots of other bindings to calculate a final result. A query binding will often itself be
2012 Inductive Automation
Project Design
229
dynamic, altering the query based on other bindings. For example, you might have a dropdown on a window that lets the operator choose a type of product that is produced. Then you can use a query binding like this to calculate the defect rate for the given product:
SELECT SUM(defective) / COUNT(*) AS DefectRate FROM production_table WHERE productCode = '{Root Container.ProductPicker.selectedValue}'
The red code is a binding inside of the query binding. Every time this (event-based) binding fires, the query will run again. Using bindings like this, you can create highly dynamic and interactive screens with no scripting whatsoever. 4.7.5.2 Polling Options For bindings that poll, you have a few options. Polling Off A polling-off binding will execute once when the window is opened, and then it will only execute again if it changes. The typical example of a binding that can change is a SQL query binding where it uses the brace-notation ( {} ) to include dynamic information inside the query. When this dynamic information changes the query, it will run again. Relative Rate The binding will execute at a regular rate, based on a delta off of the project's base polling rate. See Client Polling Properties. This is usually a good idea so that you can speed up or slow down an entire client's polling system in one place. Absolute Rate Using this option, you can specify an absolute rate for the binding to execute at, instead of one that is based off the relative rate. 4.7.5.3 Bidirectional Bindings Tag bindings and Query bindings can be set up as bidirectional bindings. This means that not only is the binding assigning the tag value or query value into the property, but it is also listening for changes to that property, which will then be written back to the tag or the database.
Tag Bindings
Tag bindings can be made bidirectional simply by checking the checkbox. The "Fallback Delay" is the amount of time that the value will remain at the written value, waiting for a tag change to come in. If no tag change comes in within the allotted time (specified in seconds), then the property will fall-back to the value as it was before the write. This is needed, because sometimes even if a write succeeds, another write or ladder logic in a PLC might have written something different, even the old value, in which case no tag change event will be generated. As a rule of thumb, the fallback delay should be twice the tag's scan class rate.
Query Bindings
When a query binding is made bidirectional, it needs an UPDATE query to execute when the property changes. You can use the special marker {this} as a placeholder for the new value.
Project Design
230
Bidirectional query bindings are only available on scalar-typed properties (i.e. not Datasets) 4.7.5.4 Indirect Bindings Making bindings indirect is an important part of the binding system. Indirect Tag, Expression, and SQL Query bindings can all be made indirect. All this means is that what the binding is bound to can be changed based upon the value of something else. For example, instead of binding straight to a tag's path, like [TagProvider]MyPlant/EastArea/Valves/Valve4/FlowRate you can use other properties to make that path indirect. Suppose the "area" and valve number that we were looking at was passed into our window via parameter passing. Then we might use those parameters in the tag path, like this: [TagProvider]MyPlant/{1}Area/Valves/Valve{2}/FlowRate {1}=Root Container.AreaName {2}=Root Container.ValveNumber Now our binding will alter what tag it is pointing to based upon the values of those root container properties. Making query bindings indirect, or dynamic, is so common that there are probably more indirect query bindings than direct ones. All this means is that the query is calculated dynamically. A common example of this would be to use a dynamic start date and end date in a query. Suppose we had a Classic Chart that we're binding to a range of history, and a Date Range that we wanted to have the operator use to select a time period. Then we could use an indirect query binding like this:
SELECT t_stamp, flow_rate, amps FROM valve_history WHERE t_stamp >= '{Root Container.DateRange.startDate}' AND t_stamp <= '{Root Container.DateRange.endDate}' AND valve = {Root Container.ValveNumber} AND area = '{Root Container.AreaName}Area'
A tag binding is a very straight-forward binding type. It simply binds to a tag property. This sets up a tag subscription for that tag, and every time the chosen property changes, the binding is evaluated, pushing the new value into the property. If the tag is in a leased scanclass, this binding will activate the lease while the window is open. If you choose a tag in the tree, and not a property, the Value property is assumed. Bidirectional Mode Choosing bidirectional will make this binding also write to the chosen tag when the property changes. The fallback delay is the amount of time to keep the property at the written value waiting for a new tag value update to come in. If no update arrives within the given timeout, the property falls back to the
Project Design
231
original value. See Bidirectional Bindings. Overlay Opt-Out Choosing this option will ignore the quality of the chosen tag, making it have no effect on the component's quality overlay.
An indirect tag binding is very much like a standard tag binding. except that you may introduce any number of indirection parameters into the path. These parameters are numbered starting at one, and denoted by braces, e.g. {1}. The binding will be bound to the tag represented by the tag path after the indirection parameters have been replaced by the literal values they are bound to. An indirection parameter may represent a property on any component in the same window, or the value of any tag. Indirect tag bindings can use bidirectional mode just like standard tag bindings.
4.7.5.5.3 SQLTags Historian Binding
This binding type (which is only available for Dataset type properties), will run a query against the SQLTags Historian. Selected Historical Tags For this type of query, you must select at least one tag path to query. The Dataset returned by the query will have a timestamp column, and then a column for each path that you select here. These paths may use indirection following the same rules as the Indirect Tag Binding. Simply type the indirection parameters (e.g. {1}) into a selected tag path by double-clicking in the list of selected paths. All valid parameters will appear in the lower indirection table. Date Range Choose either a Historical or Realtime query. Historical queries use a date range that must be bound in from other components on the screen, typically a Date Range or a pair of Popup Calendars. Realtime queries always pull up a range that ends with the current time, so all they need is a length. Sample Size and Aggregation Mode The sample size determines how the query results will look. A Natural query will look up the logging rate for the queried tags, and return results spaced apart at that rate. This means that the return size will vary with the date range. An On Change query will return points as they were logged. This means that the results may not be evenly spaced. A Fixed query will return the given number of rows. Where data was sparse, interpolated values will be added. Where data is dense, the Aggregation Mode will come into play. The Min/Max aggregation mode will return the min and max for every timestamp. The Average aggregation mode will return the average timestamp for data within the underlying range. Return Format Return format dictates how the requested data will be returned. The options are "wide" (default), in which each tag has its own column, and "tall", in which the tags are returned vertically in a "path, value, quality, timestamp" schema. SQLTags Historian information is often easiest to work with in the Easy Chart component, which
2012 Inductive Automation
Project Design
232
handles all of these options automatically. See also: How SQLTags Historian Works Data Types system.tag.queryTagHistory
4.7.5.5.4 Property Binding
A property binding is a very simple type of binding. It simply binds one component's property to another. When that property changes, the new value is pushed into the property that the binding is set up on. Why aren't all properties listed? You may notice that the list of properties available to bind to is smaller than the list of all properties. While nearly all properties can be bound, only some properties can be bound to. Only properties for which a propertyChangeEvent is fired may be bound to.
4.7.5.5.5 Expression Binding
An expression binding is one of the most powerful kinds of property bindings. It uses a simple expression language to calculate a value. This expression can involve lots of dynamic data, such as other properties, tag values, results of Python scripts, queries, etc. Expressions can be used for many different purposes. Anytime information needs to be massaged, manipulated, extracted, combined, split, etc - think expressions. Example You have 3 bits in a PLC, only one of which will be on at a time. You want to turn these three bits into a single integer (0,1,2) to drive a component's Styles. Bind a dynamic integer property to:
binEnum({MyTags/Bit1}, {MyTags/Bit2}, {MyTags/Bit3})
Example You have a Date, and need to extract the year, and concatenate the word "Vintage" to the end for a label display. Bind a label's text property to:
dateExtract({Root Container.VintageDate}, 'year') + ' Vintage'
Example You have a button that starts a batch, but you only want to let it be pressed after the operator has entered a scale weight. Bind the button's enabled property to:
{Root Container.EntryArea.WeightBox.doubleValue} > 0.0
Example You want to display a process's current state, translating a code from the PLC to a human-readable string, use of these two expressions (they're equivalent)
if ({CurrentProcessState} = 0, "Not Running", if ({CurrentProcessState} = 1, "Warmup phase - please wait", if ({CurrentProcessState} = 2, "Running", "UNKNOWN STATE")))
- or switch ({CurrentProcessState}, 0,1,2, "Not Running", "Warmup phase - please wait", "Running", "UNKNOWN STATE")
Project Design
233
This binding is technically equivalent to the SQL Query binding, except that it helps write the queries for you. Using the database browser, you can pick the table that you want to pull content from. If you have a fixed range of data to choose, simply select it in the table, and watch the query get generated. In the browse tree, you can choose which columns should act as your keys (these columns get put in the WHERE clause based on your selection) and which columns should be used to sort the data (these columns get put in the ORDER BY clause). This binding type also serves as a convenient jumping-off point for the more flexible SQL Query binding. Construct the basic outline of your query in the DB Browse section, and then flip over to the SQL Query binding. Your query will be retained and can then be improved by hand.
4.7.5.5.7 SQL Query Binding
The SQL Query binding is a polling binding type that will run a SQL Query against any of the database connections configured in the Gateway.
Dynamic Queries
Using the brace notation, you can include the values of component properties (within the same window) and tag values inside your query. This is a very common technique to make your query dynamic. The values of the property or tag represented are simply substituted into the query where the braces are. Note that because the substitution is direct, you'll often need to quote literal strings and dates to make your query valid. If you're getting errors running your query complaining about syntax, it is important to realize that these errors are coming from the database, not from Ignition. Try copying and pasting your query into the Query Browser and replacing the braces with literal values. Example A common requirement is to have a query filter its results for a date range. You can use the Date Range component or a pair of Popup Calendar components to let the user choose a range of dates. Then you can use these dates in your query like this:
SELECT t_stamp, flow_rate, amps FROM valve_history WHERE t_stamp >= '{Root Container.DateRange.startDate}' AND t_stamp <= '{Root Container.DateRange.endDate}'
Notice the single quotes around the braces. This is because when the query is run, the dates will be replaced with their literal evaluations. For example, the actual query sent to the database might look like this:
SELECT t_stamp, flow_rate, amps FROM valve_history WHERE t_stamp >= '2010-03-20 08:00:00' AND t_stamp <= '2010-03-20 13:00:00'
Fallback Value
If the property that is being bound is a scalar datatype (i.e. not a Dataset), then the value in the first column in the first row of the query results is used. If no rows were returned, the binding will cause an
Project Design
234
error unless the Use Fallback Value option is selected. The value entered in the fallback value text box will be used when the query returns no rows. When binding a Dataset to a SQL Query, no fallback value is needed, because a Dataset will happily contain zero rows. See also: Polling Options Creating a Database Connection
4.7.5.5.8 Cell Update Binding
The Cell Update binding enables you to easily make one or more cells inside a dataset dynamic. This particularly useful for components such as the Linear Scale or the Easy Chart, that store configuration information inside datasets. For example, when you configure indicators on a Linear Scale component using that component's customizer, the indicators that you set up are stored in the "Indicators" property on the scale. Suppose you wanted high-setpoint and low-setpoint indicators on the scale that weren't simply static values, but actually bound to a SQLTag indicating the realtime high and low setpoints. In order to do this, you'd set up a Cell Update binding on the Linear Scale's Indicators property. You would configure two cell bindings - one for the low setpoint indicator's Value column, and one for the high setpoint. You would then bind these to the appropriate tags. As another example, let's say you had an Easy Chart on a window that displayed 5 pens representing the history of a Compressor: running status, amperage, rpm, output pressure etc. Using SQLTags Historian, you had simply dragged the 5 applicable tags onto the Easy Chart. But now you want to use that same Easy Chart to dynamically display the same 5 pens of any of the many compressors in your system. To do this, you could pass the compressor number into the window as a parameter, and use it to calculate the tag path of the folder containing the pens. Then set up a Cell Update binding on the Easy Chart's "Tag Pens" property, dynamically altering the pens' tag paths. Now you have a generic chart window that can be used for any compressor. Note that this binding type is only applicable for Dataset-typed properties.
4.7.5.5.9 Function Binding
This is a generic binding type that allows you to bind a dataset property to the results of a function. It allows any of the function's parameters to be calculated dynamically via tag and property bindings. The function that you choose determines the parameters that are available.
4.7.6
4.7.6.1
Event Handlers
Overview Event handling allows you to use scripting to respond to a wide variety of events that components fire. This lets you configure windows that are very interactive, and are an important part of project design in the Vision module.
Events
An event can be many things, like a mouse click, a key press, or simply a property changing. Whenever these events occur, a script can be called to "handle" the event. Different components can fire different types of events. For example, mouse events are very common and are fired by almost all components. The cellEdited event, on the other hand, is only fired by the Table component.
Project Design
235
Configuring Handlers
To configure event handlers for a component, right click on it and choose the Event Handlers... item. You can also get to this button vial the toolbar ( ) or the Component menu. Once in the event handler window, you can pick any event to handle. Each event can have its own handling logic.
Script Builders
All events are handled with scripting, but you frequently don't need to write the scripts by hand. This is where the Script Builders come in. For each event, you can choose a common way of handling the event. This can be a navigation action, setting a tag value, etc. To write an arbitrary script, choose the Script Editor tab. For example, one of the most common uses of event handlers is to open a window when a button is pushed. To do this, simply select the actionPerformed event, and select the Navigation tab. Here you can simply pick the navigation action Open, and choose the window to open. If you're curious, you can peek over at the Script Editor tab to see the underlying code that makes this action tick, but you certainly don't have to. See also: About Scripting 4.7.6.2 The 'event' object Event handling scripts are just regular Python scripts except for one important detail. They all have a special variable defined in their namespace called "event". This is an object that represents information about the event that just occurred. For example, the event object for a mouse click will have the x and y coordinates where the click occurred. A key press event, on the other hand, will have a keycode, but not a coordinate. In addition to information about the event that has just occurred, the event object has a source property. The source of an event is the component that fired it. This is a crucial concept to understand. The reference to the component is your handle into the entire hierarchy of the window that your script is contained in. Example Suppose you're handling the mouse pressed event of a label component. The following script would print out the coordinates of the click, as well as the text of the label:
currentText = event.source.text print 'Mouse clicked on label "%s" at %dx%d' % (currentText, event.x, event.y)
The output would look like this if the label's text was "this is my label": Mouse clicked on label "this is my label" at 27x99
Project Design
236
To navigate sideways (getting a reference to a sibling component) you simply go up one level and then back down. Example Suppose the component hierarchy in our window looked like this: Root Container HeaderLabel StartButton Options ProductCode BatchSize PreviewTable This window has a start button, a header, some options, and a preview table. Lets say that it is a window that lets the operator start a new batch. It has some options that are grouped into their own container. Lets say that the Root Container also has some parameters that our start button needs to know about. The following table shows some script expressions and what they will evaluate to if you're writing an event handler for the StartButton component: event.source ... the StartButton event.source.parent ... the Root Container event.source.parent.MyProperty ... the value of custom property "MyProperty" on the Root Container event.source.parent.getComponent("Options") ... the Options container event.source.parent.getComponent("Options").getComponent("ProductCode"). selectedValue ... the selected value of the ProductCode dropdown component event.source.parent.getComponent("PreviewTable").selectedRow ... the index of the selected row in the PreviewTable There is one exception to the pattern of using .parent to go up the hierarchy and using . getComponent(name) to go down. The parent of a root container is not the window, and a reference to the window does not have a .getComponent(name) function. To get a reference to a window, simply use system.gui.getParentWindow with any component's event object as the parameter. Once you have a reference to a window, you can use its .rootContainer property to get to the root of the component hierarchy, and from here you can follow the rules laid out above. See also: Working with Components 4.7.6.3 Event Types These are all of the event types that are fired by the various components in the Vision module. Events are organized into event sets. For example, the mouse event set includes mouseClicked, mousePressed, and mouseReleased. All of the events in an event set share the same properties for their event object.
Event Sets
2012 Inductive Automation
Project Design
237
action cell focus internalFrame item key mouse mouseMotion paint propertyChange
action Events
Events actionPerformed Properties in 'event' source The actionPerformed event is fired when an "action" occurs. What that "action" is depends on the component. The most common example is the Button component. You should always use the action event on a button instead of a mouse click, because it will be fired whenever the button is pressed, whether it is via the mouse or the keyboard (via a mnemonic shortcut or tabbing over to the button and pressing enter or space). The Timer component is another example of a component that fires an action event. In this case, the action is the timer firing.
cell Events
Events cellEdited Properties in 'event' source oldValue - the previous value in the cell newValue - the newly entered value for the cell row column Cell events are fired by a Table component that has editable columns. When a user edits a cell, this event will fire. The oldValue and newValue properties in the event can be used to determine what value the cell used to hold, and what new value the user has entered. The row and column properties, both integers, show what position in the table's data property the edit occurred at. Example Commonly, the event handler for a cell event will issue a SQL update query to persist changes to the table back to an external database. You can use the row to determine what the primary keys were for the row that was edited by looking at the table's data property. You can use the column index to find the column name of the edited column.
Project Design
238
columnName = event.source.data.getColumnName(event.column) primaryKeyValue = event.source.data.getValueAt(event.row, "keycolumn") query = "UPDATE mytable SET %s=? WHERE keycolumn=?" % columnName system.db.runPrepUpdate(query, [event.newValue, primaryKeyValue])
focus Events
Events focusGained focusLost Properties in 'event' source oppositeComponent - the component that either gave up focus to this component, or took it away Focus events are fired for components that can receive input focus. For both the focus gained and focus lost events, you can also access the "opposite" component. For a focus gain, this is the component that previously had the focus. For a focus lost event, the opposite component is the component that took the focus away. You can programatically request that focus be given to a component by calling the function requestFocusInWindow() on that function. This function is actually defined by Java's JComponent class, from which all Vision components extend. If you are trying to alter the focus from within a focus event handler, you must wrap your code in a call to system.util.invokeLater. This will let your focus change be processed after the current focus change event that is being processed has a chance to finish.
internalFrame Events
Events internalFrameActivated - fired when the window becomes the focused window internalFrameClosed - fired after the window is closed internalFrameClosing - fired just before the window is closed internalFrameDeactivated - fired when the window loses focus internalFrameOpened - fired the first time a window is opened after not being in the cache Properties in 'event' source
Internal frame events are fired by windows. ( They are known as "internal frames" in the underlying Java windowing system that the Vision component uses). Note that the source of these events is the window itself. To get the root container of the window, use event.source.rootContainer, not event.source.getComponent("Root Container"). The Activated/Deactivated events get fired when the component receives or loses input focus. The Activated event is a more reliable event to use as a window startup event than the Opened event, because the Opened event will not be called if the window was opened when it was already cached. See also:
Project Design
239
item Events
Events itemStateChanged Properties in 'event' source stateChange - a code that will be equal to either the SELECTED or DESELECTED constants. SELECTED - a constant representing a selection event. DESELECTED - a constant representing a deselection event. The itemStateChanged event is used by components that choose between a selected or deselected state. For example, a Check Box or Radio Button. You can respond to this event to be notified when the state has changed (via any mechanism - click, keyboard, property bindings, etc). To check whether the event represents a selection or a deselection, you compare the event's stateChange property with the SELECTED or DESELECTED constants, like this;
if event.stateChange == event.SELECTED: print "Turned ON" else: print "Turned OFF"
key Events
Events keyPressed - fires when a key is pressed while the source component has input focus. Works for all keyboard keys. keyReleased - fires when a key is released while the source component has input focus. Works for all keyboard keys. keyTyped - fired when a character key is pressed and then released while a component has input focus. Properties in 'event' source keyCode - an integer code representing the key that was pressed or released. Only valid on keyPressed and keyReleased events. See table below. keyChar - a string that represents the character that was typed, if applicable (e.g. used for letters, but not an F-key). Only valid on keyTyped event. keyLocation - the location of the key. E.g. to differentiate between left shift from right shift. altDown - true (1) if the alt key was held down during this event, false (0) otherwise. controlDown - true (1) if the control key was held down during this event, false (0) otherwise. shiftDown - true (1) if the shift key was held down during this event, false (0) otherwise. Key events are used to respond to keyboard input. They will only be fired on components that receive input focus. Handling key events often involves checking exactly what key was pressed. These events make a distinction between character keys (A,B,C...) and non-printable keys (F3, Esc, Enter
Project Design
240
). All keys will get keyPressed and keyReleased events, but only character keys will get keyTyped events. For keyTyped events, checking what key was pressed is relatively simple, you can simply do a comparison on keyChar, like event.keyChar == 'a'. For other keys, however, you need to compare the keyCode to a constant, enumerated below. These constants can be referenced through the event object itself, like: event.keyCode == event.VK_ENTER. Key Code Constants VK_0 - VK_9 VK_A - VK_Z VK_F1 - VK_F24 VK_ALT VK_CONTROL VK_DOWN Location Code Constants KEY_LOCATION_LEFT KEY_LOCATION_NUMPAD VK_END VK_ENTER VK_HOME VK_INSERT VK_LEFT VK_PAGE_DOWN VK_PAGE_UP VK_RIGHT VK_SHIFT VK_SPACE VK_TAB VK_UP
KEY_LOCATION_RIGHT KEY_LOCATION_STANDARD
All of this information comes straight out of the Java documentation for java.awt.KeyEvent. See http://java.sun.com/j2se/1.5.0/docs/api/java/awt/event/KeyEvent.html
mouse Events
Events mouseClicked - fired when the mouse is pressed and released in the same spot on the component. mouseEntered - fired when the mouse is moved so that it is hovering over the component mouseExited - fired when the mouse had been hovering over the component and exits mousePressed - fired when the mouse is pressed within the bounds of the component mouseReleased - fired when the mouse is released after having been pressed within the bounds of the component Properties in 'event' source button - an integer code representing the button that was clicked. Use the constants event. BUTTON1, event.BUTTON2, and event.BUTTON3. clickCount - an integer count of the number of successive clicks. x - the x-axis location of the mouse click, with (0,0) being the upper left corner of the component. y - the y-axis location of the mouse click, with (0,0) being the upper left corner of the component. popupTrigger - true(1) if this mouse event should pop up a context menu. Meaning is OSdependent. On windows, it is a release of BUTTON3. altDown - true (1) if the alt key was held down during this event, false (0) otherwise. controlDown - true (1) if the control key was held down during this event, false (0) otherwise. shiftDown - true (1) if the shift key was held down during this event, false (0) otherwise.
mouseMotion Events
2012 Inductive Automation
Project Design
241
Events mouseDragged - fires when the mouse is pressed within the component, and then moved. Will continue to fire until the button is released, even if the mouse moves outside the component. mouseMoved - fired when the mouse moves over the component. Properties in 'event' see mouse events.
paint Events
Events repaint Properties in 'event' source graphics - An instance of java.awt.Graphics2D that can be used to paint this component. The point (0,0) is located at the upper left of the component. width - The width of the paintable area of the component. This takes into account the component's border. height - The height of the paintable area of the component. This takes into account the component's border. This event is fired by the Paintable Canvas component. This component is provided for highly scriptliterate users, and is decidedly not user-friendly. Don't say you weren't warned. It allows you to use Java2D through Python to programatically "paint" your own dynamic, vector-based component. This event is called every time the component needs to repaint. It will repaint when any of its custom properties change, or when .repaint() is called on it. Drop a Paintable Canvas onto a window and look at the paint event handler for an example.
propertyChange Events
Events propertyChange Properties in 'event' source newValue - The new value of the property oldValue - The previous value of the property. Not all properties provide this information. propertyName - The name of the property that has changed. The propertyChange event is called any time a bindable property changes on a component. This includes all custom properties. This can be a very useful tool, allowing you to respond via scripting when a property changes. Because this one event handler is called for multiple properties, it is typical for a handler to first have to filter based on the propertyName, so that it is responding to a specific property changing. Example
#This script might go on a Table whose data must be filled in before continuing if event.propertyName == "data": newData = system.db.toPyDataSet(event.newValue)
Project Design
242
if len(newData)>0: # Data exists - let the user know they may proceed system.gui.messageBox("You may proceed.")
4.7.6.4
Script Builders When creating an event handler, you can use one of the handy "script builders" instead of writing the script by hand. In the Event handlers configuration window, the script builders are accessible as tabs along the top. The last tab, "Script Editor", lets you write an event handler by hand. You can also use it to view the script that was generated by the script builder, which is a good way to get started learning how to write event handlers by hand. Action Qualifiers All of the script builders allow you to put security and/or confirmation qualifiers onto the event handler. The security qualifier lets you restrict the event handler from running if the current user doesn't possess a set of roles. Use CTRL-select to pick multiple roles. The confirmation qualified will prompt the user with a popup Yes/No box. The action will only be executed if the user chooses "Yes".
Navigation
The navigation script builder has various functions that deal with opening and closing windows. Open / Swap Opening is a very straight-forward operation - it simply opens the specified window. You are also given options to then center that window within the Client, and to close the window that the event was fired from. Swapping is the practice of opening another window in the same size, location, and state as the current window, and closing the current window. This gives the appearance of one window simply swapping into another, seamlessly. The navigation builder uses the swapWindow version of swapping, but most "by hand" script authors will us the swapTo version. This last version relies on the fact that the windows being swapped are both maximized windows. See the typical navigation strategy section for more information. You can also pass parameters to the opened or swapped-to window. The names of these parameters must match names of custom properties on the root container of the target window. The values can either be literals or values of other properties from the source window. To use a property, highlight an empty cell in the Value column of the parameter table, and press the Insert Property ( ) button. See the parameterized windows section for more information. Forward / Back These action give you a simple way of implementing "browser"-style forward/back buttons in your client. Note that you must be using the default navigation strategy for this to work, because these functions rely on calls to system.nav.swapTo in order to keep track of what the sequence of recent windows has been. Closing Windows These options allow for an easy way to have an event handler close the window that it is a part of, or any other window. See also:
Project Design
243
SQL Update
This script builder helps you build an update query using a database browsing interface. Choose a spot in your target database and the update query will be built for you. By setting columns as key columns, you can have the filter correctly filter to the right row. You may use either literal values or property values by using the Insert Property ( ) button next to the Update Value text box.
Set Property
This script builder will respond to an event by altering a property in the window. You must choose the property to alter, and the value that you wish to assign to it. The value can be a literal value or the value of any other property on the window by using the Insert Property ( ) button.
4.7.7
4.7.7.1
Security
Role-based access Security is configured using roles. This simple concept just means that instead of granting or revoking privilege based on user, you do so based upon the more abstract concept of a role, and then you assign users to belong to one or more roles. The maintenance ramifications of this separation are fairly obvious - you define your security based upon the process, not the people. Ideally, the process remains constant even if the cast of characters changes. As people are hired, transferred, promoted, fired, etc, the security management simply becomes the re-assigning of roles, not the re-designing of your project.
Project Design
244
clearance to read or write to, the component will get a forbidden overlay.
See also: Quality Overlays Tag Permissions 4.7.7.3 Component Security Each window and component can define its own security settings. These settings determine who can see and/or use the component. To define security for a component, right click on it and choose "Component Security". Here you can choose to implement a security policy different than that of your parent. In the Client, if the user does not match the role filter that you define, the component will be disabled or hidden and disabled. If a user with higher privileges logs in, the component will be useable again. If you choose to disable a component, make sure that it is a component that actually does something different when it is disabled. For example, buttons and input boxes can't be used when they are disabled, but disabling a label has no effect.
4.7.7.4
Securing event handlers Event handlers often execute logic that must be secured. The various script builders all have special security qualifiers that can be enabled. These qualifiers get translated into the generated script by accessing the user's current roles via scripting. Example
if 'Administrator' in system.security.getRoles(): productCode = event.source.productCode qty = event.source.parent.getComponent("QuantityBox").intValue query = "UPDATE my_secure_table SET quantity=? WHERE product=?" system.db.runPrepUpdate(query, [qty, productCode]) else: system.gui.errorBox('Insufficient security privileges.')
4.8
4.8.1
Reporting Module
Introduction
Project Design
245
introduced through Ignition, providing access to any SQL database! Ignition Reporting makes creating professional reports easy with a rich library including: images, graphs, tables, and a variety of basic shape tools. Access to reports is web based via the Ignition runtime, a Java application, providing authenticated users access from anywhere, all based on networking standards that your IT department can support. Reports are printer friendly and can easily be exported to a variety of formats including pdf! Here are some common uses of dynamic reports: Production Management Efficiency Monitoring Downtime Tracking Statistical Process Control Quality Assurance Overall Equipment Effectiveness (OEE) Management Historical Data analysis
Benefits
Ignition Reporting enables managers to increase productivity, decrease waste, reduce costs, and increase quality with existing resources by providing an view of their manufacturing process. Managers often save time by automating reporting processes that were once done by hand. Often valuable man hours that went into creating spreadsheets or reports can be recovered! These reports are trivial to manage since they are generated on the fly from existing SQL database data.
Project Design
246
Project Design
247
Project Design
248
the tools that allow the creation of professional reports. Concepts User Interface concepts go over the way that report customization works within the Report Designer. Basic and Advanced concepts discuss various aspects of Ignition Reporting. This is a good section to begin reading early to learn what Reporting is all about. Re-read this section after you have become proficient with the interface to gain a full understanding of how Report Generation works.
Extended Help
As no manual can fully cover every conceivable situation or topic, it's important that you know where to go for answers. The first and best place is the Inductive Automation Web site and the Inductive Automation Forum, where you can peruse the issues and questions that other users have encountered. We will respond to your posts by the next business day. From there, you may E-mail Us. We strive to provide a quick turn around on answers usually within 24 hours. Finally, registered users may call us toll-free at 1-800-266-7798. 4.8.1.2 Features The most noteworthy feature of Ignition Reporting is the fact that is integrated into the Ignition system. This: provides access to Ignition data including any SQL database, allows an unlimited number of concurrent clients via web based access, and shares authentication with your existing Ignition project. Other features: Easy to use WYSIWYG (What you see is what you get) designer that includes an intuitive layout and drawing tools Powerful table tool that creates new pages to fit your data. It supports a wide range of features. Ability to start with an existing pdf report for automatic form fill-in. Reports are printer friendly. Every report can be saved by the user in a variety of formats including pdf. The Reporting Module includes the Row Selector and Column Selector components. Both are very useful when working with DataSets. They work especially well with Ignition graph and table components as well as the Report Viewer. The Reporting Module includes the File Explorer and PDF File Viewer components. These are very useful for viewing machine maintenance manuals or any other PDFs from within your project.
Project Design
249
4.8.1.3
How it works When you install the Ignition Reporting module a Reporting tab appears in the designer that contains the following: Row Selector
Column Selector
Project Design
250
Report Viewer
File Explorer
PDF Viewer
Simply use these objects as you would any Ignition components. The bulk of creating your professional report is done through the Report Designer, which is the customizer (C ntl+U) for the Report Viewer.
Project Design
251
Project Design
252
4.8.1.4
Installation
Installing the Ignition Reporting module is a simple process done in the Ignition web configuration. From the Gateway Configuration Page do the following
Project Design
253
Fig. 1: Go to the Modules section, then click the "Install or Upgrade a Module" icon
Project Design
254
Fig. 2: Select the Reporting Module .modl file and click Install.
Trial Mode
The Ignition Reporting module trial works in a similar fashion as Ignition's trial mode. The trial mode provides a way for you to try our software without any feature restrictions. This allows you to fully evaluate our software to make sure that it's right for you. In the trial mode, all reports will have a watermark on them displaying the fact that the reporting module is being run in trial mode. In addition, after two hours of cumulative runtime, the module will 'timeout'. When the module times out, the Row Selector and Column selector components will have a watermark on them, and the report component
2012 Inductive Automation
Project Design
255
will no longer be able to print or save to PDF. You can log into the Ignition Gateway and reset the trial timer, which resets the two-hour timeout period. You can do this as many times as you want, which means that you can evaluate it for as long as you want! This system gives you flexibility to evaluate our product, while making it impractical for industrial use. Running Ignition Designer does not cause your trial window to decrease. This means that you can design an entire project on an un-activated Ignition Gateway. 4.8.1.5 Getting Started Ignition Reporting is really pretty easy to use. A basic grasp of the following topics, shown in order of precedence, will have you on your way to creating professional reports: Understand how data gets into the report via dynamic properties. Read how selection works. Pay close attention to superselection. This is very important! Know that all properties can be modified via the attribute panel or the inspector panel once you select the right object. Understand that substitution keys are the way that reports display dynamic data. When working with tables and graphs, the DataSet Key defines the Ignition DataSet that will populate the object. Once defined, you may implicitly specify variables under that dataset. At this point click through the Quick Start or Tutorial #1. 4.8.1.6 Step by Step Quick Start This guide steps you through creating basic report that contains a table and pie chart with the default DataSet, Data, shown below. Click here to learn how to install the Ignition Reporting module or here to learn how to populate the report with your own data.
Project Design
256
Instructions
We begin with the default DataSet, Data, that comes attached to every Report Viewer.
Project Design
257
Here are the steps to creating the report: 1. Install Ignition Reporting Module 2. Drag Report Viewer from Reporting tab into project window 3. Open Report Designer by selecting Report Viewer and clicking on the Customizer.
Project Design
258
4. Select the keys tab of the Attributes panel and drag Data to the report. 5. Select graph 6. Click on the report to unselect the graph. Drag Data again, this time select table .
Project Design
259
7. Drag Value key down to "Keys:" or type Value 8. Keep double-clicking until you select "Legend" then type @Label@ or drag the Label key in.
Project Design
260
9. On the Graph tab of the Inspector Panel, select the pie chart icon 10.Drag colors from the Color Attribute Panel to the graph's series colors. 11.Superselect the graph shape and resize the graph and legend.
Project Design
261
12.On the Graph tab, check Show Bar/Wedge Labels. 13.Superselect the label text. Change the font size to 12 point. 14.Change the text to "@Value@ (@100 * Value / total.Value@%)". We're intermingling static text and substitution keys to display both the value and percentage. 15.Select @Value@ text and type Cntl+B to make it bold.
Project Design
262
16.Select Table and check Header 17.Drag extra column off workspace to get rid of it. This can also be done in the table inspector. 18.Type in headers. In this case we made the text bold and centered. 19.Drag key columns to Data Details columns. 20.For percentage, we use "@Value / Up.total.Value * 100@%" or "@Value / Data. total.Value * 100@%" 21.Drag Value key to Sorting:. Click descending sort .
Project Design
263
22.Resize the graph and modify the label 23.Double-click the graph, click to add Alternate Row Version 24.Click Standard on Data Details, select Alternate 25.Change the row fill color to gray. 26.Do the same for the Data Header fill color with a darker gray. 27.Select the graph and add a border (stroke) in the Stroke tab.
Project Design
264
28.Drag in a gradient filled rectangle, text and the included image Bultin/icons/48/ check2.png to create our header 29.From the Keys tab, click Built-ins and drag down page numbers.
Project Design
265
Project Design
266
4.8.2
Tutorials
Tutorial #1 takes you through a Widget Co. quarterly employee vacation report. It should give you an idea on how to make a table based report and provide examples of common reporting features. Check out Tutorial 2 for an example of more features.
Project Design
267
Background Getting Started Basic Layout including headers and footers Substitution Keys and Tables including grouping and sorting Row Versioning and final touches Next (Background) TIP Create your own report as you go through the tutorial.
Project Design
268
4.8.2. .2 Background
Widget Co. is concerned with maximizing the morale of its people. Every employee is entitled 3 days of paid vacation per month. Employees are given the option of selling back their vacation days at 1 1/2 times their normal wage. The production manager has tasked you with creating a report with the following requirements: Look presentable - The report will be going to the VP. automatically display generation date and page numbers. This needs to be a "one click" report. Group employees by department. Be dynamic - Widget Co. anticipates rapid growth. The report needs to be able to deal with a large number of employees, possible new departments, and separate pages automatically without cutting off data. Calculate equations automatically - The manager is interesting in knowing how much money in vacation time each employee is owed, as well as a running total by department. Sort employees by vacation days. Widget Co. gives preferential approval to the employee with the most days. Support custom row versions. A special paid vacation is offered when an employees vacation sellback value exceeds $5000. Such employees need to stand out! Employee data can be retrieved from the accounting database with the following SQL query: SELECT * FROM em oy ees ; pl
Project Design
269
We will modify our SQL query to include the derived value buyout, the monetary value of employee's vacation days. CAST is used so that MySQL returns buyout as a number instead of a string. SELECT * , CAST( i nc om 360 * 1. 5 * v ac at i onday s AS SI GNED) AS buy out FROM e/ em oy ees ; pl
We could use expressions within the report to calculate buyout. In this tutorial we use the SQL database because we will be using buyout in many places. We will: display it as a column, use it as the basis of our custom row versions, and may want the option of sorting our report based on it. Other reasons include: leveraging the SQL database's rich function library and only needing to change the expression in one place.
We begin by installing the Reporting module and creating a report in our project within the Ignition designer.
Project Design
270
1. Install the Ignition Reporting Module 2. Create a new Window, and drag down a Report Viewer from the Reporting tab. 3. Populate the Data dynamic dataset. Note: You can customize your own Reporting datasets. 4. Select the Report Viewer component and click on the Customizer (Cntl+U). This is where you will be creating the report. Index
4.8.2. .4 Basic Layout
Previous (Background)
Clicking on the customizer with the Report Viewer opens the Report Designer window where we create our report.
Project Design
271
Everything here was created with the toolbar.The following steps were taken: 1. Drag the left and top rectangles. Modify their fill property in the attributes panel to create the blue and orange background colors. 2. Drag another border rectangle for good measure. 3. Add Shapes->Image. Repeat for gears and header image. 4. Add Text. Modify applicable properties in their inspector and attributes panels. Double clicking text for superselection is key here! 5. Add 4 Lines. Modify applicable properties in their inspector and attributes panels. Index Previous (Getting Started) Next (Substitution Keys and Tables)
Project Design
272
TIP
The most interesting portion of this report will be a table. It will occupy as much space as the size that we drag it on the screen, creating extra pages as necessary for the data.
Project Design
273
2. Repeat, dragging the builtin key "Page @Page@ of @PageMax@" to the footer (bottom) of the report. 3. Format the date by double clicking the text label to superselect the text, then use the formatter to format the date.
Creating Table
1. Drag the DataSet Data from the keys tab and choose table when you see the Dataset Key Element window above. Select table and click ok. Alternatively, create the table from the toolbar then drag down the Data key to the Dataset key field of the keys attribute panel. Defining the table's DataSet is done automatically when using the step above. 2. Resize and position the window as desired.
Table Customization
1. Select the table, and select to the Table Inspector panel. Clicking on the Shape Specific Inspector will bring up the same panel. 2. Select Data under grouping and check: Header, Details, and Summary. This creates a unique header and summary row for each unique department. Data Details refers to each employee. 3. Select department under grouping and check: Details, and Summary. Summary creates a single summary row for the report. Details at this level of grouping is just above as the Data Header level of Data (We could have used either one instead of both for this example). More on table row grouping precedence here. 4. Modify the structured column width property for each row. This defines how many columns, of a fixed user definable width, a given table row will use. We will use 6 columns for Data Details, and not use structured columns for the others. Not using structured column width can be set by unchecking the top checkbox shown below or by de-selecting the row's prison icon . when the table is superselected
Project Design
274
Superselect table, then single click select row to pull up this inspector
5. Drag keys into table row columns. See the six columns in the Data Details row of the screenshot below. Notice the use of text editing, and text formatting. The total aggregate key, @total.buyout@, is used for both departmental subtotals and the grand total. The difference lies in the level of grouping it is placed in and is explained here.
Project Design
275
Preview
1. Click the preview button to view your report.
Project Design
276
Index TIP
Previous
Don't be afraid to play with these options! It is much easier than it looks!
Now we want to color in the rows, and create different row versions for those employees that are entitled more than $5000.
Project Design
277
Here were the steps for this report 1. We begin by customizing the Standard Row Version, created by default for header, details, and summary. Click Data Details to select the row and use the fill/stroke inspector to add a background color (fill) and border (stroke). Resize columns and try to make all adjustments now as duplicate rows will be based on this one. 2. Click on the Row Version Label (Where the image shows Click here to add "Row Versions") and click "Add Alternate". 3. Customize Alternate rows. In this case our only change was to darken the background color. 4. Click on the Row Version Label (Where the image shows Click here to add "Row Versions") and click "Add Custom". Add badnews 5. Customize badnews rows. To illustrate flexibility, added borders to the individual key labels, changed background colors, and modified font properties including the bold property and text centering.
2012 Inductive Automation
Project Design
278
6. Double click on the table then click on Data Details to select the Data Details row. Select the shape specific inspector property. Under Table Row Version Key: we enter: buy out >5000?" badnews " How it works: This conditional statement will return the string "badnews" if buyout exceeds $5000 for a given employee, changing the row version to badnews for that person. We intentionally don't specify an ELSE condition. Since a valid string is not returned, the report will default to using Standard, Alternate, or whatever builtin row versions are defined. buy out >5000?" badnews " : " Al t er nat e" Would make employees show up as our Alternate dark gray or badnews red. Standard would never be displayed. Note: Versions are different for each row, and they each have their own defining Table Row Version Key 7. Make final minor cosmetic changes
Project Design
279
Borrow the look and feel of an existing report! This is much easier than it looks!
Project Design
280
4.8.2.2
Tutorial #2 - Adding Graphs Tutorial #2 adds dynamic graphs to the Widget Co. quarterly employee vacation report in Tutorial 1. We will make changes to the main table, have a unique header for the first page, and create a report summary for all employees. We will also add an extra dataset, polling data from two datasources.
Project Design
281
Notice that the EMPLOYEE VACATION REPORT label only exists on the first page. Every page in Tutorial 1 would display that label. Background Getting Started Basic layout and summary More changes Graphs Next (Background)
4.8.2.2.2 Background
Project Design
282
The Vice President of Widget Co. is so happy with his EMPLOYEE VACATION REPORT that he insists you be the only one to modify it. After much thought he has come up with additional changes that will make his analysis easier and more effective. 1. Only display the EMPLOYEE VACATION REPORT header on the first page. Do what you can to maximize page usage. You are instructed not to remove the blue border. 2. Add pie graphs that illustrate vacation buyout value by department to indicate monetary entitlement. 3. Add bar graphs that show the number of vacation days per employee by department. 4. Add a summary bar chart that shows buyout values of employees with the greatest value, indicating the value and department. 5. Calculate average and total: income level, vacation days, and buyout value for all employees. 6. Calculate average and total: income level, vacation days, and buyout value for all employees with a buyout value exceeding $5000. Previous (Index)
4.8.2.2.3 Getting Started
After going through the documentation, you've come up with the following strategy: 1. Displaying a header on one page can be done with the reprint Table Row Version. Easy! We used the same technique to create alternate row colors in Tutorial 1! 2. Pie graphs should be simple enough. They need to be grouped by department. We will embed them within our department grouping. 3. Bar graphs will be exactly like pie graphs. 4. The summary bar chart needs to be outside department grouping. You choose to put it in the table summary. 5. Averages and totals should be no problem with aggregate keys. These will be placed with the above graph. 6. The last requirement strikes you as tricky to calculate within the report. You realize that you're dealing with a subset of the employees based on a definable condition, but maintaining totals and averages over that subset looks ugly. Can it be done with assignment expressions? Yes, but why not leverage our SQL database? You can come up with a single simple query that will return all employees with a buyout value > $5000. The report will see two different DataSets and can easily perform aggregate functions (total, min/max, average) on either. An additional benefit is that if you need to change the requirements you need only change one
Project Design
283
query. SELECT * , CAST( i nc om 360 * 1. 5 * v ac at i onday s AS SI GNED) buy out e/ FROM em oy ees W pl HERE ( i nc om 360 * 1. 5 * v ac at i onday s ) > 5000 ; e/
Index TIP
Previous (Background)
Get in the habit of utilizing the SQL database. It is easier to manipulate the data before the report gets it. This is especially true when you need to do joins or have other complex query requirements.
We're going to make a few minor aesthetic changes to give us room for graphs in the report. We will use both bar and pie graphs to indicate how many vacation days and how much vacation buyout money employees are entitled to. These graphs provide managers with an accurate idea on where they stand at a quick glance.
Project Design
284
Project Design
285
1. Change the font of our EMPLOYEE VACATION REPORT label and moved it from outside the table into the department header. 2. Add highvalue Dynamic Property. within the Ignition designer, under Viewer component just like we did SELECT * , CAST( i nc om 360 * e/ It needs to be a DataSet. Populate the data the highvalue dynamic property of the Report in Tutorial #1. Our new SQL query: 1. 5 * v ac at i onday s AS SI GNED) buy out
Project Design
286
FROM em oy ees W pl HERE ( i nc om 360 * 1. 5 * v ac at i onday s ) > 5000; e/ We are creating a second DataSet that contains the subset of employees whose buyout value exceeds $5000. This will simplify our conditional average and total calculations. 3. Add yellow header rectangle and move page numbers up. 4. Resize table downward to the bottom of the page for more room. 5. Add yellow labels for summary aggregates. We will be using: count, total, and average and placing them under department summary. Index Previous (Getting Started) Next (More Changes)
We now add a reprint row version to only display EMPLOYEE VACATION REPORT on the first page. We will also add summaries for our buyout > $5000 employees.
Project Design
287
1. Add reprint row version for every other header besides the first page. Customize as necessary. 2. Add highvalue summaries. The process is identical to our existing summaries.
Project Design
288
Index TIP
Previous
Next (Graphs)
In this table, Data is implied and can be omitted since it is the table's primary DataSet. highvalue must be explicitly entered. For example, @Data.count@ could have been entered @count@, while @highvalue. count could not have been simplified.
4.8.2.2.6 Graphs
Project Design
289
1. Drag 2 graphs down to the department Header. The left one will be a buyout pie graph, while the right will be a vacation days bar graph. 2. For both graphs, ensure the Dataset Key is blank. Found under graph>shapespecific inspector->Series tab. Set Keys: to buyout and vacationdays, respectively. 3. Make one graph a pie graph and the other a bar graph. Look for icons under graph->shapespecific inspector->Graph tab Notice that you can set series colors here under Colors.
4. Enable switch versions by checking Show Bar/Wedge Labels. We will add one on the top and one in the middle. Look at bar chart labels on the final screenshot for an example.
Project Design
290
5. Use lots of double clicking to drilling down to select basic shapes and text. Change colors and fonts as desired. 6. Added semi transparent label with department subtotal (@total.buyout@) to the pie graph. 7. Added department label for summary bar graph using bottom switch version. @substring(department,0,3)@ used string functions to display a 3 letter abbreviation.
Project Design
291
Project Design
292
Index TIP
On to Tutorial 3
The toughest part of creating small graphs is labeling the data legibly. This takes a little practice. Don't hesitate to mess up your report playing with options, then click cancel in the customizer window and start over again. You'll get the hang of it in no time!
4.8.2.3
Tutorial #3 - PDF Example Tutorial #3 turns an existing PDF file into a dynamic report
Project Design
293
Project Design
294
Widget Co. wants to automatically generate 1040EZ forms for its employees taxes. Here are the requirements: 1. Start with an existing pdf report. 2. Dynamically fill in: name, income, withholdings, dependents, and other details. 3. Dynamically calculate taxes based on an expression. 4. Display a check mark (isVisible condition) based on an expression. 5. Allow users to print report or save as a pdf. Previous (Index)
4.8.2.3.3 Creating the report
Widget Co. wants to automatically generate 1040EZ forms for its employees taxes. Here are the requirements: 1. Start with an existing pdf report. 2. Drag in keys 3. Users can print report or save as a pdf by right clicking the report.
Project Design
295
Project Design
296
Previous (Index)
4.8.3
4.8.3.1
Components
Ignition Components
Icon in toolbar:
Project Design
297
Description
The selected data will output all data from Oct 4, 2005
The Row Selector is a component that allows users to filter a DataSet based on unique values of one or more columns. Each level in the sorting tree is based on these properties. The user will see a dynamically generated expandable tree that groups their data by any number of choices. As they click down the tree, objects bound to the DataSet will indicate the filtered data. Here are a few examples. A line graph bound to a Row Selector. Set up grouping to be first by month and year, then day, then hour, like the top left illustration. Clicking on a month and year will dynamically update the graph for that time period. Further clicking to a specific day or hour will re-filter the graph for that period. A Report Viewer bound to a Row Selector. Grouping by department (String) would allow selection by department, automatically regenerating the Report on selection. An "alarm history" table bound to a Row Selector. This could first be broken down severity level (Integer), then broken into "Alarm Acknowledged" / "Not Acknowledged" (Boolean based). Clicking "Severity 3" would filter the table to all Severity 3 alarms. Selecting "Unacknowledged" would then filter the table to unacknowledged alarms of severity 3.
Properties
Show All Data showAllDataNode BOOLEAN Node Displays or hides the 'All Data' (root) node. Show Root
2012 Inductive Automation
showRootHandles
BOOLEAN
Project Design
298
Handles If true, root node(s) will have collapsible handles like child nodes. Show Node Size showNodeSize BOOLEAN
If true, the number of nodes in each row will be shown. propertiesLoadin Properties INTEGER g Loading Indicates number of dataSets loading. This is strictly a bindable property. It can be used as status indication to the user that data is loading.
Customizer
The Row Selector customizer defines Filters that allow each level of user data filtering. Browse through the tree of Available Filters, then drag the desired filter to the filter pane. Different options will be available under Configure Filter: FilterType based on the filter type.
Common Filter Properties Property Column Name Icon Path Function Allows selection of date column Click to choose a graphic for each node.
Date Filters
Project Design
299
The Day (Date) filter separates rows by day. The Custom Date (Date) filter uses pattern masks in the Format String for a flexible date criteria definition. The Shift (Date) filter breaks up data into shifts, which are named defined time ranges. Other Filters
The Discreet (Integer) filter breaks rows down by unique integer. Format String allows you to define the text string that the user sees. The String (String) filter breaks rows down by unique string. Case Insensitive defines case sensitivity.
Events
mouse mouseClicked
Project Design
300
Scripting Functions
TIP
The Row Selector works well with the: Report Viewer, Graph, and Table components!
Icon in toolbar:
Description
Project Design
301
Project Design
302
The Column Selector is a component that takes DataSets in, allows users to show or hide variables in the DataSets (Columns) via checkboxes, then outputs the resulting DataSet. The Column Selector allows users to choose which columns in a DataSet that they wish to use. If an object is bound to the Column Selector it will update itself whenever a user checks or unchecks a column. This allows users to dynamically show/hide: Table columns, "pens" on a graph, data in a Report Viewer, or any other component set up to use a DataSet.
Properties
Group by DataSet grouping
BOOLEAN
Displays each DataSet's columns in a separate bordered container. Applicable to multiple DataSets only. alphabetize BOOLEAN Alphabetize Orders columns alphabetically as opposed to their native order in the DataSet . Normalize Widths normalizeWidths BOOLEAN
If true, all checkboxes will be assigned the same width, which causes them to line up in columns Horizontal Gap hGap INTEGER
The horizontal gap, in pixels, between checkboxes and grouping panels. Vertical Gap vGap INTEGER
Customizer
The Column Selector customizer is very straightforward. The left pane allows you to add and remove DataSets. Selecting a DataSet will display a list of columns in the table in the right pane. Under Display you may modify the name that users see. Excluded from Selection will remove the given column from the users list of choices.
Events
mouse mouseClicked mouseEntered mouseExited mousePressed mouseReleased mouseMotion mouseDragged mouseMoved
Project Design
303
propertyChange propertyChange
Scripting Functions
TIP
The Column Selector works well with the Ignition Graph and Table components!
Icon in toolbar:
Description
Project Design
304
The Report Viewer is the component that displays reports within Ignition. Dynamic Properties bring data from Ignition into the report. Any changes to the dynamic data automatically regenerates the report. Customization is done in the Report Designer via the customizer (C ntl+U)
Project Design
305
Users can zoom in to the report and scroll between pages with the builtin controls located at the bottom. Right clicking anywhere on a report in the Report Viewer in the Runtime will allow you to print or save the report in several formats.
Properties
Zoom Factor zoomFactor
INT
This variable sets and displays the current zoom level of the report.
Customizer
The customizer for this class is the Report Designer. It lets you add, remove, and edit properties for the Report's datasets as well as create entire reports.
Events
mouse mouseClicked mouseEntered mouseExited mousePressed mouseReleased mouseMotion mouseDragged mouseMoved propertyChange propertyChange
Project Design
306
Parameters [printerName] The name of the printer to print to. Omit or use None to use the default printer. [showDialog] A boolean (0 or 1) indicating whether or not to show the user the print dialog options box. Example:
# This would prompt the user to print, showing them the print dialog box and starting with the report = event.source.parent.getComponent("Report Viewer") report.print()
Example:
# This would print to the "HP Laserjet" printer with no user interaction report = event.source.parent.getComponent("Report Viewer") report.print("HP Laserjet", 0)
Example:
# This would print to the default printer with no user interaction report = event.source.parent.getComponent("Report Viewer") report.print(None, 0)
saveAsPDF( filename)
Saves the generated report as a PDF to the specified filename.
Project Design
307
Parameters filename The filename, such as myfile.pdf saveAsPNG( filename) Saves the generated report as a PNG to the specified filename. Parameters filename The filename, such as myfile.png
Icon in toolbar:
Description
The File Explorer component displays a filesystem tree to the user. It can be rooted at any folder, even network folders. It can also filter the types of files that are displayed by their file extension (For example, "pdf"). The path to the file that the user selects in the tree is exposed in the bindable property Selected Path. This component is typically used in conjuction with the PDF Viewer component, in order to
2012 Inductive Automation
Project Design
308
create a PDF viewing window. This is very useful for viewing things like maintenance manuals from within your project. To create a window like the one shown below follow these steps: 1. Bind the PDF Viewer's Filename property to the File Explorer's Selected Path property 2. Set the File Explorer's File extension filter to "pdf" 3. Set the File Explorer's Root Directory to a network folder that has your maintenance manuals in it. (Use a network folder so that all clients will be able to access the manuals).
The File Explorer used with the PDF Viewer for manual viewing.
Properties
selectedPath Selected Path STRING This Read-Only property provides the path to the selected file or folder. selectedPathIsFi Selected Path Is BOOLEAN le File This Read-Only property is true when the selected path is a file, and false otherwise (i.e., the selected path is a folder). File extension fileFilter STRING filter A semicolon separated list of file extensions to display, such as "pdf" or "html; htm;txt;rtf". Leave blank to show all file types. rootDir Root Directory STRING The path to the root folder to display. Examples: "C:\Program Files" or "\ \fileserver\manuals\Maint Manuals". If blank, the local system's filesystem
2012 Inductive Automation
Project Design
309
root is used.
Customizer
None.
Events
mouse mouseClicked mouseEntered mouseExited mousePressed mouseReleased mouseMotion mouseDragged mouseMoved propertyChange propertyChange
Scripting Functions
Icon in toolbar:
Project Design
310
Description
The PDF Viewer component displays a PDF that exists as a file in some accessable filesystem, or as a URL. Note that this component is simply for viewing existing PDFs - for creating dynamic reports, use the Report Viewer component. This component is typically used in conjuction with the File Explorer component, in order to create a PDF viewing window. See the File Explorer's documentation for instructions on how to put these two components together.
Properties
Filename filename STRING The path or URL to the PDF file to display. Examples: "C:\PDFFiles\example.pdf ", "\\fileserver\manuals\valve-2.pdf", or "http:\\www.example.com\test. pdf". zoomFactor FLOAT Zoom Factor The zoom factor of the viewer. 1=100%.
Customizer
Project Design
311
None.
Events
mouse mouseClicked mouseEntered mouseExited mousePressed mouseReleased mouseMotion mouseDragged mouseMoved propertyChange propertyChange
Example 2:
# This would get the PDF bytes from a SQL database bytes = fpmi.db.runScalarQuery("SELECT PDFBlob FROM PDFTable WHERE ID = 1") pdfViewer.setBytes(bytes)
4.8.3.2
ReportViewer Components
Project Design
312
Drawing tools
Ico n Name Toggle Preview/ Edit Mode Description Toggles between Preview and Edit modes. This is equivalent to going between Preview and Design mode in the Ignition designer. Edit mode will allow you to make changes to the layout of the report. Preview mode will populate the report with data and show you what it will look like in the runtime. Default tool. Clicking on objects with the selection tool will select them for movement or modification. Click and drag to create a line. Click and drag to create a rectangle. The Rect inspector will allow you to set rounding radius. Click and drag to create an oval. The oval inspector will allow you to select sweep and start angle. Click and drag to create text. Click for more on text editing.
Selection Tool Line Tool Rect Tool Oval Tool Text Tool
Project Design
313
Polygon Tool
The polygon tool lets you click points that will be joined with straight lines. Alternatively, you can click-drag-release to position line segments interactively. If you hold down the alt key while adding points the polygon tool will behave like pencil for added segments. Editing stops under the following conditions: clicking the same point twice, clicking close to the start point or clicking a new tool in the tool bar (like the selection tool) .
Pencil Tool The pencil tool lets you click and draw free-hand path segments, automatically smoothing the curve on mouse up. If you hold down the alt key, it will behave like polygon for added segments. Editing stops under the same conditions as polygon.
Shapes Menu
This shapes menu allows you to modify the layout of objects in a report Menu Item Group/ Ungroup Function Allows you to merge the currently selected shapes into a single shape for convenient management. Contained shapes are still accessible, via double-click super-select. Ungroup separates grouped shapes.
Bring to Front/ All shapes have an order on the page that determines what is Send to Back drawn on top when two shapes overlap. These options allow you to alter that order. Make Row Top/Center/ Bottom Make Column Left/Center/ Right Make Same Size, Width, Height Equally Space Row/Column Group in Switch/3D Shape Move to new layer Quickly align several shapes in a row, either by their top, center, or bottom border. Useful when shapes are of different heights. Same as above, but for columns.
Equalizes the distance between shapes horizontally or vertically. This feature groups selected shapes in a Switch Shape, which has the same features as Table Row Versions. It's a powerful way to conditionally provide a different look for a specific element. Creates a new page layer with the currently selected shapes.
Combine/ Takes multiple overlapping shapes (such as a rectangle and an Subtract Paths oval) and combines them into a single shape using the combined paths. A powerful tool to construct complex shapes. Convert Into Converts the selected shape into an image. Be sure to group
Project Design
314
Image
shapes first if you want to convert multiple shapes into a single image.
TIP
The Drawing Tools are really intuitive. Try them out. You'll be an expert in no time.
4.8.3.2.2 Crosstab
The CrossTab is a DataSet element like the table and graph. It shows a summaries of cross sections of data. To be useful, crosstab data should have the following: Lots of repetitious data. You should be looking for sums, averages, or other aggregate functions At least 2 (key) columns whose data are repetitious compared to the number of rows. Your data should look "rectangular". For example, If there is only one row for each combination of values of the 2 keys, you will get a trivial crosstab. You will typically have a third column that is a number to perform an operation on. Examples are: summing money, displaying average response times, counting occurrences, etc. The CrossTab template is much simpler than the table template. By default it just shows one cell of a simple table. This is usually configured with an aggregate key, like "@total. getAmount@". After that, grouping keys are dragged to the horizontal and vertical axis.
Example
We will use a crosstab to illustrate total downtime by equipment and location. Employee data can be retrieved from the accounting database with the following SQL query: SELECT * FROM downt i m e;
Project Design
315
Notice that the example only has 2 unique sites. This is because we only have 12 rows of data.
4.8.3.2.3 Graph
The Graph is a DataSet element like the table. It shows a 2D or 3D graphical representation of data in the form of bar graph or pie graph. Graphs are useful for illustrating relative amounts of summarized data. Populating data including the concepts of data keys, sorting, and filtering are nearly identical to that of a table. The look of the graph has a much deeper superselection model than a table.
Example
We will explore graph options with a total downtime by equipment example. The same data is used as the table example. A downtime summary can be retrieved with the following SQL query: SELECT equi pm ent , s um t i m ( e) AS t ot al Downt i m FROM downt i m GROUP BY e e
2012 Inductive Automation
Project Design
316
equi pm ent ;
Project Design
317
Graph Settings
Basic graph settings can be found on the Graph Tab of the graph shape specific inspector . Graph Menu Item Graph Type Choose Bar Show Legend Show Bar/ Wedge Labels , Horizontal Bar , or Pie type graph. Displays a legend object to label series Builtin graph labels. You may want to rotate them to create space. Drag colors to define graph series colors. Colors will repeat if rightmost color is white.
2012 Inductive Automation
Function
Project Design
318
Draw 3D
Project Design
319
Custom Children
The Graph shape supports additional custom children. Add axis labels or arbitrary text by superselecting the graph and using standard tools such as Text, Rect, Polygon, etc. You can reference keys in added text children which will be evaluated against the group of objects provided for the graph. TIP The best way to get the hang of graphs is to create a huge one and experiment with it.
The Line Graph is a DataSet element like the table. It shows a graphical representation of data in the form of a line, area or scatter garph. Populating data including the concepts of data keys, sorting, and filtering are nearly identical to that of a table.
Example
The Line Graph component is used to display data where the X value is time or numeric, and the Y value(s) are numeric. Lets set up a graph for some timeseries data. Suppose you have a table with data like this:
Project Design
320
The t_stamp column is your X value, and the other columns are your "pens" or series of Y values. You get this data into a report by binding a DataSet property of the report viewer (see Concepts > Basic > Dynamic Properties) to a SQL query, such as SELECT t_stamp, temperature, pressure FROM graph_data . Lets say that you had this data in the default Data property. You set up the Line Graph's data the same way you would a Graph or Table. The only trick is that the keys needs to be a comma separated list of keys, with the first one being your X value. Lastly, make sure that the data is sorted ascending by the X value. The following setup:
Project Design
321
If true, the X axis (first Key) should be a date/time. If false, the X axis should be a number. Displays a legend with the name of each series (each Key besides the first one. If true, the domain axis (X axis) will be shown. The label for the domain axis. Date axes may automatically display additional label information to disambiguate certain ranges. If true, the range axis (Y axis) will be shown. The label for the range axis. Leave blank for automatic, or specify a range like 0,100 Drag colors to define graph series colors.
Project Design
322
Since a graph is generally a large shape, you usually want to define an explicit page break for the row that contains the graph, so that the graph won't get chopped off on a page boundary. Select the light gray region to the left of the Group in the Table inspector to do this.
4.8.3.2.5 Images
Create images by clicking on the image button on the add shapes button of the toolbar. Double click on an image in the Image Browser window.
Image Options
Image options are specified in the shape specific inspector for images. Option Key Page Margins Function Specify a string expression that returns an image path to change the image. Useful for a multistate image within a table. Applicable to pdfs only. Selects page number of multipage pdf to display. Specifies how many pixels you want of margins around the image.
Style - stretch Stretches the picture to the image object's size, regardless of aspect ratio. Style - tile Style - fit Style - fit if needed Tiles the original sized picture within the image object, cutting off sides as necessary. Resizes picture to image object maintaining aspect ratio. Resizes picture to image object maintaining aspect ratio, shrinking if necessary, but never enlarging.
Size borders to Applicable to fit and fit if needed. image Rounding Radius Turns stroke (border) from rectangle, to rounded rectangle, to circle as the number is increased.
Project Design
323
Image Placeholders
Images can be populated with BLOB data from an SQL database. They are referred to as Image Placeholders when used in this fashon. Simply define the Key to the Blob image.
Using an Image Placeholder and blobs to dynamically illustrate table row based on department.
Project Design
324
Project Design
325
TIP
Extract only the pdf pages that you are going to use before putting them into your report.
4.8.3.2.6 Labels
Labels can be used to print out mailing labels, create name tags, or any other generic labels. You can use standard Avery label sheets or specify your own dimensions.
Project Design
326
Shape Specific Inspector Item List Key Avery Product Number Label Width/ Height Spacing Width/Height Sorting Paginate
Function Name of DataSet that will populate the labels Choose from a list of Avery Label Formats
Rows/Columns Defines the number of rows and columns on the page Width and height of labels in pixels Distance between labels on the page in pixels Specifies printing order. Works the same as table sorting. Two setting (Off or On ) option that determines whether or not to use page breaks. Broken are useful for pdf files, continuous are good for Flash or CSV. Typically leave this alone.
Example
1. Create labels from tool bar or by dragging a DataSet to the report. 2. Specify the DataSet name (employees) as the List Key in the shape specific inspector 3. Choose the appropriate Avery Product number or manually specify dimensions 4. Create text labels. Set up your labels with substitution keys Employee addresses can be retrieved from the database with the following SQL query: SELECT e. f i r s t , e. l as t , a. addr es s , a. c i t y , a. s t at e, a. z i p FROM em oy ees pl e, addr es s a W HERE e. i d=a. em p_i d;
Project Design
327
Resulting Output
4.8.3.2.7 Barcode
Description
The reporting barcode component is identical to Ignition's normal barcode component. It displays some text encoded as a barcode, and also displays the text verbatim below the
Project Design
328
barcode. In the report designer, you can drag a data key into the text box, and the barcode will be dynamic just like any other reporting component.
Properties
Value The value (code) that will be encoded as a barcode. Acceptable values vary depending on the encoding type. Drag a data key (Like @SerialNum@ ) into the value box to make the barcode dynamic. Type The encoding type of the barcode. Types are< Code 39 Code 39 Narrow Extended Code 39 Extended Code 39 Narrow Code 128 Codabar Codabar Narrow Interleaved Code 25 Interleaved Code 25 Narrow MSI EAN 13 EAN 8 Bar Width The width of a single bar. Bar Height The height of all bars.
The Simple Table is a table of a fixed size that does not have a dataset key. It has an intuitive superselection model. Property Rows Columns Header Row Specify number of rows Specify number of columns Optional Header Row
2012 Inductive Automation
Function
Project Design
329
Header Column
Note: @first@ will not resolve to anything because there is not an implied dataset key. You would need a full path such as @employees[0].first@ (unless you have the dynamic non-DataSet property, first). 4.8.3.2.9 Tables
Tables are objects that display data in a structured, repetitious format. Their complexity can range from trivially simple to complicated. The Reporting engine will automatically create new pages to fit all data within the table's boundaries. Combine that feature with powerful data manipulation and layout tools, and you get an object that often forms the basis of your reports.
A Simple Table
A Complex Table
Project Design
330
The above table was created in Tutorial #2. It uses the following features: Header, detail, and summary rows Grouping Sorting Row Versioning Next (Table Basics) TIP Table related help sections can be referenced independently, but will be written so that examples follow sequentially.
4.8.3.2.9.2 Basics
Let's go through the process of creating a simple table! We will cover: getting data into the report, creating a table, defining data, and explore basic parts. Make sure you understand how the Dataset key defines the table's DataSet.
Project Design
331
Project Design
332
Creating a Table
1. Open the Report Designer by selecting the Report Viewer in the Ignition Designer and applying the customizer (C ntl+U). 2. Click the table icon on the add shapes button of the toolbar. 3. Size and position table as desired.
Project Design
333
Defining Data
The Dataset Key is the name of the DataSet that a table or graph is getting its input from. @yourSubstitutionKey@ in the table with a defined Dataset key will work as if it were @DataSet_Key.yourSubstitutionKey@ 1. Click the table to select it 2. Select the Table Inspector
3. Under Dataset Key:, type Data or drag the Data DataSet from the Keys Attribute Panel, choose table and click ok. This is the step that defines which DataSet this table will use. You may only define one per table. If you created the table by
2012 Inductive Automation
Project Design
334
dragging the DataSet, you will not need to fill in the DataSet Key in the next section. With a defined dataset key, your table can reference that data without explicitly defining the path. For example, in this table, @Data.comment@ is the same as @comment@. 4. Drag Keys to the table columns from the Keys Attribute Panel. We appended the string "minutes" to the time label and formatted the date.
5. Click
6. Click "Header" and "Summary" check boxes in the Table Inspector. Add text labels to Header and Summary. 7. Select Data Header, add a Fill Color (Background) in the Fill & Stroke Inspector. 8. Select Data Details, add a Stroke Color (Outline) in the Fill & Stroke Inspector. 9. Adjust text, fill, and stroke as desired. 10.Click to view your table.
Project Design
335
Anatomy of a Table
There aren't many parts to a table. You have the entire table to define the region on the report that the table occupies. Much area of simple tables often end up as a placeholder. Header, detail, and summary rows are optional for each level of Grouping. The Table Inspector and Table Row Inspector are where table configuration occur.
Project Design
336
Tables can also be created by dragging a DataSet to your report. This will automatically set the Dataset Key.
Rows are an important fundamental aspect of tables. The different types of rows can be independently enabled for each level of Grouping. Table Row Versioning gives you the option of conditionally displaying rows with a different format.
Header Row
The header row is used to add such report features as column labels. An interesting feature of the header is reprint versioning, which allows a different header on every page after the first. The main data in a table has one header row. Each subgroup of data can have its own row header. With grouping, the "top" level Header is the first row for the entire report. Lower level Headers fall immediately below higher level Details. In many cases where one is used,
Project Design
337
Detail Rows
The detail rows typically represent the majority of the data on a table or the "middle" rows. You might disable detail rows in unusual situations such as only displaying aggregate summaries in a grouped report. With grouping, the Detail rows appear below the same level Header and above the Header of the next level.
Summary Row
The summary row works like the header row. It prints at the bottom of the table. With grouping, Summary rows are always last, always in the opposite order of the Headers.
Row Properties
Row properties are defined in the Table Row Inspector.
Project Design
338
Table Row Versioning allows any given row to use different constructions based on an expression. This gives you options like: alternating row background color, emphasizing alarm states, and conditionally displaying different information in general.
Sorting orders your data by a key or list of keys. Filtering excludes data based on some condition. Both are done in the table inspector.
Sorting
There are two similar methods of sorting. They can be ascending ( and can use aggregate keys. ) or descending ( )
Sort takes a list of keys and sorts by the first one. In the event of a tie it goes down the list. TopN uses a single key path. The Count option allows a limit to the number of rows processed.
Filtering
Project Design
339
Filtering gives the option of processing data based on an expression. If the expression resolves false, the row will be skipped. Note: you do not need @ symbols to reference keys.
Example
This example is sorted descending by downtime and filtered by downtime greater than 20 minutes.
Project Design
340
TIP
The term processed is used instead of displayed because TopN and Filtering work with aggregate functions. Filtered data is treated as if it didn't exist.
Row versions allow you to conditionally display rows of data in different format. They are used to make certain data stand out or to make your report more legible. Row versions are either builtin or user defined and may be specified with a version key expression. They are applicable to header, detail, and summary rows
Project Design
341
Example
1. Add a custom row version. scheduled, in this case. 2. Select your row and customize it 3. Specify Table Row Version Key. Tip: start with the expression "scheduled" to try out your custom row version before using more complex expressions. In this case we use: IF comment = "Scheduled maintenance" THEN use our custom row version. TIP When using an IF condition for row versioning leave out the ELSE. Your table will then still respect builtin row versions. If you defaulted the ELSE to "Standard", none of the builtin versions such as Alternate would ever appear.
Project Design
342
Make sure that you're happy with the Standard row version before you create other row versions. This will save you time as other versions begin as a copy of Standard.
4.8.3.2.9.6 Grouping
Grouping breaks tables down by keys that share a common value. Tables support an arbitrary level of groups. Each can have its own header, detail, and summary rows. Additionally, totals and other aggregate functions are supported for any level of grouping. See Table Rows for specifics on row precedence with grouped tables.
Example
This example begins with the Table Basics example. We'll group our existing downtime report table by equipment. 1. Drag the equipment key into the grouping table inspector. 2. Check header, detail, and summary to enable all. 3. Add headers and details. 4. Use @total.time@ for both summary rows. Notice that the total respects grouping. In the equipment Summary row total.time is a sum of all time at that level of
Project Design
343
grouping, which includes all downtime events. In the Data Summary row total. time is a sum of all downtime at that level of grouping, total time that has already been grouped by equipment, equivalently, total downtime by equipment.
Project Design
344
In the example above, separating the equipment level of grouping by page would create separate report pages for the following: labeler, filler, palletizer, and converyor line.
Previous (Table Row Versioning) Tip Double Clicking a key while a table is selected will add that key to the grouping list and add it as a table row.
Project Design
345
Table Groups
Table groups allow you to specify child tables for each object in the master list (using a list key found in each of those objects). It also allows you to specify additional "peer" tables that pick-up exactly where the first table ends (note: multiple tables can also be configured as multiple- page templates, providing a page break between tables).
Use
To turn a table into a table group, simply select the table and click the "Group in Table Group" button in the table inspector. The table is actually a child of a "Table Group" element, which has it's own inspector. Now you can drag any list key of the master table into the table group's table tree to add a child table (the Table Group pull-down menu also provides a way to add child or peer tables). This will add a whole new table for this "child" list key. You can edit each of the different tables in the table hierarchy by clicking their node in the table tree. Double-click a node to get its table inspector (or double click on the table template in the open document). You can get back to the table group inspector by clicking on the "Table Group" button at the bottom left corner of the table template, or by selecting the table group icon in the "Selection Path" area of the inspector.
Parent Reference
To reference the parent row object from a child table, you can simply use the key prefix "Parent". So if a row in a movie role child table wanted to display the movie title, it could use the key "@Parent. getTitle@".
Project Design
346
4.8.4
4.8.4.1
Concepts
User Interface
Reporting has a "deeper" selection model than the Ignition designer. Simple object selection is done by single clicking an object. "Selecting deep" is done by double-clicking to get into the report hierarchy. For instance, if you group two rectangles together, you can select the individual rectangles by double clicking "into" the group.
Superselection
Project Design
347
Superselection refers to an editing state that some shapes go into when double clicked. Text is the most common of these. When a text box is selected you can move and resize it. When it's super-selected, you can place the text cursor or select a range of characters and insert or delete text. The polygon and pencil are two other basic tools that support superselection.
Multiple Selection
Multiple Selection can be done two ways: Clicking and dragging the mouse over a range of the report. Everything the selection rectangle touches becomes selected. Hold the shift key while making a selection or dragging a selection rect. Shapes hit by that action will be added or removed from the currently selected shapes.
Alignment
2012 Inductive Automation
Project Design
348
Alignment is accomplished by selecting multiple objects, then choosing "Make ..." from the shapes menu or right click menu. Shapes Menu Item Make Row Top/Center/ Bottom Make Column Left/Center/ Right Make Same Size, Width, Height Equally Space Row/Column
Function Quickly align several shapes in a row, either by their top, center, or bottom border. Useful when shapes are of different heights. Same as above, but for columns, aligning their sides or center.
Shift Drag
Holding the shift key while you drag shapes will constrain movement to: horizontal, vertical, or 45 degrees.
TIP
Getting used to selection and superselection is one of the most important concepts to master to become proficient with Ignition Reporting.
Object layout is an important aspect in creating a professional report. Ignition Reporting uses a WYSIWYG (what you see is what you get) approach.
Z Order
Z order defines relative order of objects when they overlap. Simply select the object and click "Bring to front" or "Send to back" in the shapes menu or right click menu.
Project Design
349
Object Grouping
Grouping makes a set of object behave as one with respect to: selection, moving, and resizing. To "drill down" to individual objects, superselect the grouped object.
Alignment
Alignment is simple. As you move an object around, the Report Designer will draw in a blue dashed line and snap to position when similar edges align. Below the top edge aligns.
Project Design
350
Layers
Layers are logical "layers" that take up the space of the entire screen, but contain a subset of the objects on it. They allow you to work on certain parts of your report independently of the rest. Selecting a layer, even a hidden one, will show it Show displays a layer and allows you to work on it Hide hides a layer and doesn't allow you to work on it Lock displays a layer, but doesn't let you select any objects on it
TIP
Text editing is pretty straightforward. A few things to know: Superselection is key here. Distinguish between selecting a text label versus superselecting the text itself. Text properties that are modified on the font attribute panel (color, bold (C ntl+B), italics
(C ntl+I), font,
size) apply
selected prior to making a text property change, all text in that object will be modified.
Project Design
351
Properties that are modified on the text inspector panel such as: text alignment, shadows, fill and stroke, and transparency are object properties. Changes will usually affect all text in that object regardless of specific text selection.
TIP
Most text properties can be set in the Font Attribute Panel or the Text Inspector Panel. The notable exception is font color, which is set by highlighting text and using the Color Attribute Panel.
The Report Designer is the Customizer (C ntl+U) for the Report Viewer. It is the window where you create your reports.
Major Sections
2012 Inductive Automation
Project Design
352
The menu provides various options, most for selected objects. The toolbar allows you to create shapes objects. The Report workspace is where you create your report. The Attribute Panel is where you modify common properties. The Inspector Panel gives you access to more specific object properties. Dynamic Properties bring Ignition data into your report
4.8.4.1.4.1 Menu
The menu provides quick access to many common functions. It is divided into five sections: Edit Format Pages Shapes Tools
Edit
The edit menu provides functions like cut, copy and paste. Menu Item Undo Redo Cut/Copy/ Paste Select All Undoes the last action. Re-does the last undo (assuming nothing was changed after the last undo). Allows you to easily duplicate or import document elements using the system clipboard. Selects all elements at the current level of selection (or all text, if editing a text field). Function
Format
The format menu is used for text formatting. Menu Item Font Panel... Bold, Italic, Underline, Outline Function This selects up the Font Panel tab of the Attributes panel. Modifies or unmodifies currently select text or text fields. This functionality is also available in the font panel.
Project Design
353
Aligns currently selected text or text fields to the left, center or right. This functionality is also available in the Text Inspector. Modifies or unmodifies currently select text or text fields.
Pages
The pages menu allows you to add or remove pages to the report and change the zoom level Menu Item Add Page Add Page Previous Remove Page Zoom In/Out Zoom 100%/200% Zoom Toggle Last Zoom... Function Adds a page to the current open document, after the currently selected page. Adds a page to the current open document, before the currently selected page. Removes the currently selected page in the current open document. Increases/decreases document zoom by 10%. Zooms to the specified percent of actual document size. Zooms to the last specified Zoom. Brings up a zoom panel that allows you to exactly specify a zoom as a percentage of actual document size.
Shapes
This shapes menu allows you to modify the layout of objects in a report Menu Item Group/ Ungroup Function Allows you to merge the currently selected shapes into a single shape for convenient management. Contained shapes are still accessible, via double-click super-select. Ungroup separates grouped shapes.
Bring to Front/ All shapes have an order on the page that determines what is Send to Back drawn on top when two shapes overlap. These options allow you to alter that order.
Project Design
354
Make Row Top/Center/ Bottom Make Column Left/Center/ Right Make Same Size, Width, Height Equally Space Row/Column Group in Switch/3D Shape Move to new layer
Quickly align several shapes in a row, either by their top, center, or bottom border. Useful when shapes are of different heights. Same as above, but for columns, aligning their sides or center.
Equalizes the distance between shapes horizontally or vertically. This feature groups selected shapes in a Switch Shape, which has the same features as Table Row Versions. It's a powerful way to conditionally provide a different look for a specific element. Creates a new page layer with the currently selected shapes.
Combine/ Takes multiple overlapping shapes (such as a rectangle and an Subtract Paths oval) and combines them into a single shape using the combined paths. A powerful tool to construct complex shapes. Convert Into Image Converts the selected shape into an image. Be sure to group shapes first if you want to convert multiple shapes into a single image.
Tools
The tools menu contains layout tools Menu Item Color Panel Font Panel Formatter Panel Keys Panel Toggle Rulers Image Placeholder Function Selects the color tab in the Attribute Panel. Selects the font tab in the Attribute Panel. Selects the format tab in the Attribute Panel. Selects the keys tab in the Attribute Panel. Adds rulers to the page borders to assist in precise layout. Adds an empty image placeholder object to the document, which can be positioned, sized and configured with a substitution key.
Project Design
355
4.8.4.1.4.2 Toolbar
The toolbar allows you to drag shapes and objects into your report
Toolbar Icons
Ico n Name Toggle Preview/ Edit Mode Description Toggles between Preview and Edit modes. This is equivalent to going between Preview and Design mode in the Ignition designer. Edit mode will allow you to make changes to the layout of the report. Preview mode will populate the report with data and show you what it will look like in the runtime. Default tool. Clicking on objects with the selection tool will select them for movement or modification. Click and drag to create a line. Click and drag to create a rectangle. The Rect inspector will allow you to set rounding radius. Click and drag to create an oval. The oval inspector will allow you to select sweep and start angle. Click and drag to create text. Click for more on text editing. The polygon tool lets you click points that will be joined with straight lines. Alternatively, you can click-drag-release to position line segments interactively. If you hold down the alt key while adding points the polygon tool will behave like pencil for added segments. Editing stops under the following conditions: clicking the same point twice, clicking close to the start point or clicking a new tool in the tool bar (like the selection tool) .
Selection Tool Line Tool Rect Tool Oval Tool Text Tool Polygon Tool
Pencil Tool The pencil tool lets you click and draw free-hand path segments, automatically smoothing the curve on mouse up. If you hold down the alt key, it will behave like polygon for added segments. Editing stops under the same conditions as polygon.
Project Design
356
Ico n
Name Table
Description Arguably the most powerful Reporting feature. Tables will occupy a fixed size on the screen but create as many pages in the report as the dataset requires. Useful for a downtime report that may cover one day or six months, for example. The graph is a dynamic bar or line graph. It is simple, yet conveys much information. Labels are printable labels that are compatible with standard Avery label sizes. Crosstabs summarizes a cross section of data, such as total downtime by both equipment and location. The Simple table is a table of a fixed size that doesn't support DataSets. It is easy to work with and ideal if you don't need the flexibility of a table. Images make your report look good. Image Placeholders provide different images based on conditions.
TIP
Know your basic shape tools and their properties. They can be used to produce professional reports!
The attributes panel is the top right panel on the Report Designer that is used to modify common attributes for simple objects, especially text. Single click to select your object then make changes in the attributes panel. Often times you will have to double click to drill down to the simple object or property that you want to modify.
Project Design
357
Color Tab
The color tab is used to change any color in your report. Suppose you wanted to change the fill (background) color of a text label. There are several ways to accomplish this: 1. Left click the label to select it. Click a color on the attribute panel. You'll notice that fill property gets enabled and the background color set to your choice. 2. Select the label. Click on the colored square under the fill tab of the inspector panel to select the color. Choose a color on the attribute panel. 3. Select the label. Drag a color down from the color panel to the colored square under the fill tab of the inspector panel. All of these changed the fill color. To change the font color of that label you would double click the text label, highlighted the text, then changed the color. The key is getting used to the selection model to change the color of the desired property.
Project Design
358
Font Tab
The font tab is used to change the family, size, and options of fonts. Selection tends to be much more forgiving since there are relatively few font properties. For example, selecting a label is the same as double clicking that label then highlighting all of the text, with respect to the font panel. To change the color of text, highlight it, then go to the color tab.
Project Design
359
Format Tab
The format tab is used to apply formatting to dates and numbers. Highlight desired text and choose formatting. Dates are formatted like the expression dateFormat function (shown below). None removes formatting.
For the following table, assume the Date is 7/8/2005 3:05:00 PM (July 8th, 2005). Date Pattern Components Character M MM
2012 Inductive Automation
Example
Project Design
360
Name of month, abbreviated. Name of month, full Day of the month. Day of the month, forced 2 digits. Day of the week, abbreviated. Day of the week, full. Year - abbreviated. Year - Full Hour of the day (0-23) Hour of the day (1-12) Minute Seconds AM/PM marker Time zone, full
Keys Tab
The keys tab is a convenience that displays your data and builtin functions. Clicking "Built-ins" will toggle between user data and builtin functions. The typical use of the Keys Tab is dragging keys into your report. Here are a few examples of how that could work: Dragging last, a string data key, to your report will create the text label, @last@ Dragging last to text in a selected text label will add in the text @last@. Dragging a DataSet will open a window prompting to create a table, labels, graph, or crosstab.
Project Design
361
TIP
Get to know the attribute panel. Most shared properties reside here. The only other panel to know is the inspector panel, where more complex or object specific settings reside.
The inspector panel is the bottom right panel on the Report Designer. It is used to modify object attributes.
Project Design
362
Document Inspector
The Document Inspector is where you set your page layout, paper size, margins, and other top level properties.
Project Design
363
Page Inspector
The Page Inspector deals with document layers. "Layers" are logical grouping containing anything between no objects and every object that takes the space of the whole report. For example, you could create a background layer that contains borders and graphics. You would then create a main layer that is the bulk of the dynamic report. When working on one layer, you could make the other invisible. You can also lock a layer once you're finished with it.
Project Design
364
Table Inspector
The Table Inspector defines the dataset, sorting, grouping, and filtering for tables. It is where you choose to display a table's header, detail, and summary. The Table Inspector can modify data processed by the table, as well as the general look of it.
Project Design
365
Paginate - Has three setting (Off , On , N/A ) option that determines whether or not a table will use page breaks. Paginating tends to be useful for pdf files, not paginating tends to be good for Flash and CSV files. Typically leave this setting alone.
Project Design
366
Row Property Structured Switch/ Column Count Sync with parent/ alternates
Function Sets row to unstructured or defines number of columns. This can also be done with table icons. With structured tables, it's often convenient to have column resizing be reflected in the row immediately above the current row (the parent) or with a table row's different versions (alternates). Once enabled, individual column resizing will affect the corresponding parent or alternate row width. This is useful for synchronizing detail/header row changes. This is the heart of widow/orphan control. By default, a row is guaranteed to have at least one child in its group on the same page. This prevents such rows from being printed by themselves, which can be confusing. Increase this number for additional family bonding. If it exceeds the number of objects in a group, the group will never be broken across a page boundary. When data overruns the bottom of the page and starts on a new page, upper level grouping details and headers are reprinted to retain context. Occasionally this doesn't makes sense. Select the row and click this switch to suppress this behavior. An alternative is to configure a Reprint version.
Print even if no By default headers and summary rows for empty lists are objects in suppressed. If you want an indication of the missing data turn this group switch on.
Project Design
367
Normally the Summary row will share a border with the last row on the table. Move to Bottom will move it down slightly so that it's always resting on the bottom border of the page. This is commonly used with the Running Summary feature. An advanced form of widow/orphan control is to be able to control how an exceptionally tall table row will break across a page (usually only the case when a large text block is involved). By default rows will only be split when at least an inch (72pts) was available on the first page (min split height) and at least an inch will be carried over to the successive page (min remainder height). Most table rows will never use these settings. If you prefer to have table rows use all of the potential page space and don't care about trying to keep related text on the same page, you would set both of these to 10pts. If you never want a row to split, set these to 999.
Allows you to configure different looks for the same table row based on some condition to provide visual hints. The version key expression should return a string that is the name of a version that you've defined. Details here or example here.
Text Inspector
The Text Inspector is where you specify text alignment. More details under text editing. You can use this larger textbox to edit text instead of making text changes directly on objects.
Project Design
368
Function This thumbwheel allows you to set the rounding radius for the text border. It's immediately reflected in the editor window. Text can be set to paginate for form letters, shrink text to fit for static text boxes that may receive arbitrarily long text, or Grow for text fields in table rows (which can grow to accommodate large text blocks). Draws a gray border around text even when not selected. Sometimes useful as a visual cue while editing, without marking generated reports. Coalesced newlines will make sure text uses the minimum lines necessary. Useful for substituted data that might contain missing keys, eg, "@name@\n@address1@\n@address2@\n@phone@\n@fax@". If you turn on rulers for the editor window (Tools->Toggle Rulers menu), you will notice that it shows tab markers while editing text. These can be dragged and reset to change the tab stops of the text field.
Tab Stops
Project Design
369
Project Design
370
Project Design
371
Project Design
372
Animation Inspector
The Animation Inspector is used to set up animation, which works, but will not be useful unless Reporting enables Macromedia flash based reports. You set up snapshot times and the report will morph the scene from one time to the other.
Project Design
373
TIP
The inspector panel varies on an object by object basis. If you have trouble changing a property on a complex object, chances are it's here. Try clicking on different parts of the object then going through the Inspector Panel.
Copyright 2001-2005 Inductive Automation, Inc. All Rights Reserved. 4.8.4.2 Basic
Dynamic Properties are user defined variables and DataSets attached to a report viewer. They allows your report to be populated by data within Ignition. This paradigm is powerful because it gives you the flexibility of Ignition features: use any database connection for SQL queries, expression functions, bindings, etc. This also allows selection changes within Ignition to automatically update your report's data. Reporting dynamic properties work similarly to the dynamic properties of a graph or container.
Project Design
374
2. Click "Ok" to get out of the Report Designer and back into the Ignition designer. 3. Populate your dynamic properties as you would any other Ignition properties. 4. Go back into the Report Designer. Your data is listed under the Keys Attribute Panel
5. Your keys may now be referenced in the Report. For example, @StartDate@
Project Design
375
would display 08/25/2006. It can be formatted however you wish via the Formatter attribute panel.
TIP
Dynamic Properties bring data into your report in the form of keys. To reference these keys, see substitution keys, a fundamental aspect of reporting
The most important part of any reporting system is data substitution. Ignition Reporting uses a familiar mail-merge paradigm, allowing the user to intermingle keys with static text. Keys are delineated by "@" symbols, for example: @Date@ or @myVariable@. An example of mixed keys and text, might be "@Page@ of @PageMax@", perhaps resulting in the text "1 of 10". An interesting thing about keys is that they can be @anything@! You can type any string between two "@" symbols and the Reporting engine will treat it as a key. At run-time it evaluate the key to your dynamic property or a built in key. The syntax for keys follows the rules of Java expressions, described here If a key cannot be evaluated it will return the String for Null property on the document inspector (set to "N/A" by default) .
Your Keys
Your keys are the most important data in the report! Browse through them with the Keys Attribute Panel. Read more about dynamic properties the way to bring data into the report.
Project Design
376
Builtin Keys
The following builtin keys may be typed or dragged from the keys panel Menu Item Date Row Page PageMax PageBreak Function The current date/time. Can be formatted in the formatter panel The current row number (only in tables). The current page The total number of pages in the generated report The number of explicit page breaks encountered
PageBreakMax The total number of explicit page breaks in generated report PageBreakPag The number of pages since last explicit page break e PageBreakPag The total number of pages in current explicit page break eMax
Formatting Keys
Keys that return: dates, currency, or numbers can be formatted by highlighting then using the formatter.
Array Indexing
You can reference an individual object in a list using standard array indexing syntax (brackets) like this: "@Data[0].firstName@".
Project Design
377
The Keys Browser contains a list of built-in keys at the bottom of any given list: total, average, min, max and count. These allow the user to easily specify aggregate calculations on a set of objects. Suppose we want to see @Data.total.revenue@ or the @data.min.runtime@ or perhaps just @data.count@. When performing an aggregate calculation on the objects in a table the DataSet Data is set as the Dataset Key so you can use @total.revenue@ instead of @Data.total.revenue@.
Project Design
378
"Credit/Debit: @amount@ Current balance: @Running.total.amount@" The remaining key is conceptually the same, but results in a virtual array of remaining objects.For example: "Credit/Debit: @amount@ Remaining Activity: @Remaining.total. amount@"
TIP
Check out substitution keys - expressions, operators, and functions for even more substitution keys!
Key Expressions
You can type in expressions within the "@" symbols to perform calculations on the keys. Here are the operators in order of precedence. Operator Parenthesis Function (expr) Nested expressions *, /, % Multiply, divide, modulo Example Any portion of a Key Chain can be enclosed with parenthesis to guarantee precedence. These are the most common and intuitive operators. You might want to display @quantity*price@ in an invoice line-item or calculate a percent like this @profit/ revenue*100@. See multiplicative above
Multiplicative
Additive Relational
+, - Add, subtract
>, <, >=, <= GreaterThese are most useful for conditionals: than, less-than, @amount>=0? "Credit" : "Debit"@ or greater/less-than-equal @name=="this"? "that" : name@. ==, != Equal, not-equal AND && See Relational above These operators make it possible to test multiple conditions: @revenue>100 && budget<50? "Winner!"@ or @name=="Jack" || name=="Sam"? "Good Name!"@. See and above Provides IF/THEN/ELSE expressions. Note: a false expression is optional. 'null' will be evaluated to false and non-null as true. You can provide null substitutions like this: @name? name : "(None provided)"@. You can also nest conditionals for more conditions. For example, @age>=21?"Adult": (age>12?"Teen":"Child")@.
Equality Logical
Logical Conditional
Project Design
379
Assignments
=, +=
For the brave, you can create temporary variables for use in a report. Most of the functionality you might use this for is covered in more intuitive ways (such as the Running key), but it is possible to define a variable in a header row: @revTotal=0@ and update it in details rows @revTotal+=revenue@.
Math Functions
The following functions return floats. Menu Item floor(float) ceil(float) round(float) abs(float) min(float, float) max(float, float) pow(float, float) Function Round input down to the nearest whole number. Round input up to the nearest whole number. Round input to the nearest whole number. Returns the absolute value of the input (if number < 0 return number * -1). Returns the input number with the least value. Returns the input number with the greatest value. Returns first number to the second number power.
String Functions
The following functions return strings. Menu Item Function
startsWith Returns true if the first string starts with the second. (String, String) endsWith Returns true if the first string ends with the second. (String, String) substring (String, int start) join(List aList, String aKeyChain, String aDelimeter) substring (Object aString, int start, int end) Returns a substring of String beginning at position start.
Used to display an individual attribute of individual objects as a single String. Suppose you have a list of movies and want to show their titles in a comma separated list: @join(getMovies, "getTitle", ", ")@ obtain a subset of a given string. This could be useful if you wanted to restrict a text field to a certain number of chars: @substring(title, 0, 10)@
Project Design
380
Saving a report is simply a matter of right clicking on the report in the Ignition runtime or preview mode of the designer and selecting the format you wish to save it as.
You have the following options: Print - print your report to a printer PDF - Adobe Acrobat formatted document HTML - web page PNG - image file
Create images by clicking on the image button on the add shapes button of the toolbar. Double click on an image in the Image Browser window.
Project Design
381
Image Options
Image options are specified in the shape specific inspector for images. Option Key Page Margins Function Specify a string expression that returns an image path to change the image. Useful for a multistate image within a table. Applicable to pdfs only. Selects page number of multipage pdf to display. Specifies how many pixels you want of margins around the image.
Style - stretch Stretches the picture to the image object's size, regardless of aspect ratio. Style - tile Style - fit Style - fit if needed Tiles the original sized picture within the image object, cutting off sides as necessary. Resizes picture to image object maintaining aspect ratio. Resizes picture to image object maintaining aspect ratio, shrinking if necessary, but never enlarging.
Size borders to Applicable to fit and fit if needed. image Rounding Radius Turns stroke (border) from rectangle, to rounded rectangle, to circle as the number is increased.
Image Placeholders
Images can be populated with BLOB data from an SQL database. They are referred to as Image Placeholders when used in this fashon. Simply define the Key to the Blob image.
Project Design
382
Using an Image Placeholder and blobs to dynamically illustrate table row based on department.
Project Design
383
TIP
Extract only the pdf pages that you are going to use before putting them into your report.
The attributes panel is the top right panel on the Report Designer that is used to modify common attributes for simple objects, especially text.
Project Design
384
Single click to select your object then make changes in the attributes panel. Often times you will have to double click to drill down to the simple object or property that you want to modify.
Color Tab
The color tab is used to change any color in your report. Suppose you wanted to change the fill (background) color of a text label. There are several ways to accomplish this: 1. Left click the label to select it. Click a color on the attribute panel. You'll notice that fill property gets enabled and the background color set to your choice. 2. Select the label. Click on the colored square under the fill tab of the inspector panel to select the color. Choose a color on the attribute panel. 3. Select the label. Drag a color down from the color panel to the colored square under the fill tab of the inspector panel. All of these changed the fill color. To change the font color of that label you would double click the text label, highlighted the text, then changed the color. The key is getting used to the selection model to change the color of the desired property.
Project Design
385
Font Tab
The font tab is used to change the family, size, and options of fonts. Selection tends to be much more forgiving since there are relatively few font properties. For example, selecting a label is the same as double clicking that label then highlighting all of the text, with respect to the font panel. To change the color of text, highlight it, then go to the color tab.
Project Design
386
Format Tab
The format tab is used to apply formatting to dates and numbers. Highlight desired text and choose formatting. Dates are formatted like the expression dateFormat function (shown below). None removes formatting.
For the following table, assume the Date is 7/8/2005 3:05:00 PM (July 8th, 2005). Date Pattern Components Character M MM Month Month, forced 2 digits Function 7 07
2012 Inductive Automation
Example
Project Design
387
Name of month, abbreviated. Name of month, full Day of the month. Day of the month, forced 2 digits. Day of the week, abbreviated. Day of the week, full. Year - abbreviated. Year - Full Hour of the day (0-23) Hour of the day (1-12) Minute Seconds AM/PM marker Time zone, full
Keys Tab
The keys tab is a convenience that displays your data and builtin functions. Clicking "Built-ins" will toggle between user data and builtin functions. The typical use of the Keys Tab is dragging keys into your report. Here are a few examples of how that could work: Dragging last, a string data key, to your report will create the text label, @last@ Dragging last to text in a selected text label will add in the text @last@. Dragging a DataSet will open a window prompting to create a table, labels, graph, or crosstab.
Project Design
388
TIP
Get to know the attribute panel. Most shared properties reside here. The only other panel to know is the inspector panel, where more complex or object specific settings reside.
The Graph is a DataSet element like the table. It shows a 2D or 3D graphical representation of data in the form of bar graph or pie graph. Graphs are useful for illustrating relative amounts of summarized data. Populating data including the concepts of data keys, sorting, and filtering are nearly identical to that of a table. The look of the graph has a much deeper superselection model than a table.
Example
We will explore graph options with a total downtime by equipment example. The same data is used as the table example. A downtime summary can be retrieved with the following SQL query: SELECT equi pm ent , s um t i m ( e) AS t ot al Downt i m FROM downt i m GROUP BY e e equi pm ent ;
Project Design
389
Project Design
390
Graph Settings
Basic graph settings can be found on the Graph Tab of the graph shape specific inspector . Graph Menu Item Graph Type Choose Bar Show Legend Show Bar/ Wedge Labels , Horizontal Bar , or Pie type graph. Displays a legend object to label series Builtin graph labels. You may want to rotate them to create space. Drag colors to define graph series colors. Colors will repeat if rightmost color is white.
2012 Inductive Automation
Function
Project Design
391
Draw 3D
Project Design
392
Custom Children
The Graph shape supports additional custom children. Add axis labels or arbitrary text by superselecting the graph and using standard tools such as Text, Rect, Polygon, etc. You can reference keys in added text children which will be evaluated against the group of objects provided for the graph. TIP The best way to get the hang of graphs is to create a huge one and experiment with it.
Let's go through the process of creating a simple table! We will cover: getting data into the report, creating a table, defining data, and explore basic parts. Make sure you understand how the Dataset key defines the table's DataSet.
Project Design
393
Project Design
394
Creating a Table
1. Open the Report Designer by selecting the Report Viewer in the Ignition Designer and applying the customizer (C ntl+U). 2. Click the table icon on the add shapes button of the toolbar. 3. Size and position table as desired.
Project Design
395
Defining Data
The Dataset Key is the name of the DataSet that a table or graph is getting its input from. @yourSubstitutionKey@ in the table with a defined Dataset key will work as if it were @DataSet_Key.yourSubstitutionKey@ 1. Click the table to select it 2. Select the Table Inspector
3. Under Dataset Key:, type Data or drag the Data DataSet from the Keys Attribute Panel, choose table and click ok. This is the step that defines which DataSet this table will use. You may only define one per table. If you created the table by
2012 Inductive Automation
Project Design
396
dragging the DataSet, you will not need to fill in the DataSet Key in the next section. With a defined dataset key, your table can reference that data without explicitly defining the path. For example, in this table, @Data.comment@ is the same as @comment@. 4. Drag Keys to the table columns from the Keys Attribute Panel. We appended the string "minutes" to the time label and formatted the date.
5. Click
6. Click "Header" and "Summary" check boxes in the Table Inspector. Add text labels to Header and Summary. 7. Select Data Header, add a Fill Color (Background) in the Fill & Stroke Inspector. 8. Select Data Details, add a Stroke Color (Outline) in the Fill & Stroke Inspector. 9. Adjust text, fill, and stroke as desired. 10.Click to view your table.
Project Design
397
Anatomy of a Table
There aren't many parts to a table. You have the entire table to define the region on the report that the table occupies. Much area of simple tables often end up as a placeholder. Header, detail, and summary rows are optional for each level of Grouping. The Table Inspector and Table Row Inspector are where table configuration occur.
Project Design
398
Tables can also be created by dragging a DataSet to your report. This will automatically set the Dataset Key.
4.8.4.3
Advanced
Blob (Binary Large Object)is a data type for storing large amounts of binary data in an SQL database. Ignition Reporting can use Blobs to display dynamic images within reports. This example will illustrate using blobs with MySQL and the free MySQL Query Browser.
Project Design
399
Using an Image Placeholder and blobs to dynamically illustrate table row based on department.
Example
We begin with the employee table from Tutorial #1 and emp_images, a table that maps departments to images Employee data can be retrieved with the following SQL query: SELECT * FROM em oy ees ; pl
Images data can be retrieved with the following SQL query: SELECT * FROM em p_i m ages ;
Project Design
400
The MySQL Query Browser allows you to upload files as Blobs and view images
The following query will SELECT employees with the image as defined by their department SELECT e. f i r s t , e. l as t , e. i nc om e, e. depar t m ent , i . i m age FROM em oy ees e, pl em p_i m ages i W HERE e. depar t m ent = i . dept ;
Project Design
401
Create a table. Select a column and create an image in it. Set the Key value to your key, image
Create images by clicking on the image button on the add shapes button of the toolbar. Double click on an image in the Image Browser window.
Project Design
402
Image Options
Image options are specified in the shape specific inspector for images. Option Key Page Margins Function Specify a string expression that returns an image path to change the image. Useful for a multistate image within a table. Applicable to pdfs only. Selects page number of multipage pdf to display. Specifies how many pixels you want of margins around the image.
Style - stretch Stretches the picture to the image object's size, regardless of aspect ratio. Style - tile Style - fit Style - fit if needed Tiles the original sized picture within the image object, cutting off sides as necessary. Resizes picture to image object maintaining aspect ratio. Resizes picture to image object maintaining aspect ratio, shrinking if necessary, but never enlarging.
Size borders to Applicable to fit and fit if needed. image Rounding Radius Turns stroke (border) from rectangle, to rounded rectangle, to circle as the number is increased.
Image Placeholders
Images can be populated with BLOB data from an SQL database. They are referred to as Image Placeholders when used in this fashon. Simply define the Key to the Blob image.
Project Design
403
Using an Image Placeholder and blobs to dynamically illustrate table row based on department.
Project Design
404
TIP
Extract only the pdf pages that you are going to use before putting them into your report.
Property Expressions are a way that you can dynamically change object properties based on key expressions.
Project Design
405
Properties
Option URL IsVisible Font FontColor/ FillColor/ StrokeColor X/Y Width/Height Function Used for Macromedia Flash based reports. Presently N/A. 1 makes the shape visible, 0 makes the shape invisible. String based font name to use. Property should evaluate to a string that is a font name in the Font Attribute Panel. Changes color of font, fill, and stroke, respectively. Expects colors by name or "#RRGGBB" (Hex) format. Object position that expects a number. Dynamically Size an object
Simple Example
Project Design
406
Dynamic Example
We will use 2 object's Property Expressions to illustrate their uses. Add an image of a check box. This is included under Builtin/icons/check2.png. We want a check box is the employees income is greater than the arithmetic average of employees. Set the isVisible property to "income > Up.average.income". Notice that we neglect the @ for properties in the Inspector Panel. Add a rectangle with a gradient fill. We want the width of the rectange to be 100 pixels * the ratio of the employee's income versus the employee with the max income. Set the Width property to "100 * income / Up.max.income"
Project Design
407
TIP
Scripting
Part V
Scripting
409
5
5.1
Scripting
About Scripting
Scripting is used in many places in Ignition to add a significant degree of flexibility and customization where pre-canned options fall short. There are two major scripting languages in Ignition, Python and the Expression Language. It is important to understand the differences between the two, and to know where each is used.
Python Scripting
What is Python? Most of the time when we talk about "scripting" we're talking about Python scripting. Python is a general purpose programming language that was developed in the early 90's and has gained significant popularity in the 2000's. We like it because it is extremely readable, elegant, powerful, and easy to learn. As an added bonus, it gracefully interacts with Java, giving programmers an extremely powerful tool when paired with Ignition, which is written in Java. Python or Jython? You'll often hear Python referred to as "Jython" by advanced users of Ignition. Python is the language, Jython is the implementation of the language that we use. Most users of Python use the implementation called "CPython" - they just don't realize it. See http://en.wikipedia.org/wiki/Python_ (programming_language)#Implementations Why not VBA? Many HMI/SCADA packages use VBA, or Visual Basic for Applications. As such, many engineers switching to our software inquire about it. There are a variety of reasons we don't use VBA: 1. It is not compatible with Java, the language that Ignition is written in. This also means that it is not cross-platform. 2. It is a dying language (Microsoft is phasing it out as of July, 2007) 3. It is full of security holes 4. It is an ugly language Where is Python Used? Python is used in many places in Ignition. The most apparent place is in component event handlers. Project event scripts are another major place where Python is used. Which version of Python is Used? Ignition uses Python 2.5. When looking at outside documentation, such as on www.python.org, verify that you are looking at the correct version of the documentation.
Expression Language
The expression language is a simple language that we invented. An expression language is a very simple kind of language where everything is an expression - which is a piece of code that returns a value. This means that there are no statements, and no variables , just operators, literals, and functions. The most common expression language that most people are familiar with is the one found in Excel. You can have Excel calculated a cell's value dynamically by typing an expression like =SUM(C5:C10). Our expression language is similar. It is used to define dynamic values for tags and component properties.
Scripting
410
5.2
5.2.1
Python
About Python
While it is entirely possible to create a complete and powerful project in Ignition without writing a line of script, many designers will find that in order to complete projects with specific requirements, they need to learn at least a little Python. In our experience, most industrial projects involve lots of very complex and specific requirements. The good news is that learning Python is easy and enjoyable. Python is one of the most beautiful programming languages we've ever encountered. It is very easy to read - even if you don't know it at all, you will probably be able to understand a basic Python script. It is frequently called it "executable pseudocode". We've included a short tutorial here which should help get you started. If you find yourself doing a lot of scripting, you may want to pick up a basic reference book about Python.
Scripting Help
Scripting is one of the topics in Ignition that users frequently need help with, because it is used to achieve some of the most complex requirements of a project. If you get stuck designing a script, or would like help getting started, don't hesitate to get some help. Our user forum at http://www. inductiveautomation.com/forum is by far the best place for scripting help. When asking for scripting help - be precise and complete. If you're working through an error - include the text of the error, the circumstances, and the offending code. If you're stuck on something, it is helpful to describe the broader goals of what you're trying to accomplish - there is often an easy way and a hard way. Don't be shy to simply ask for some direction getting started.
5.2.2
5.2.2.1
Python Tutorial
Basic Syntax The basic syntax of python is easy to learn, because there isn't much of it.
Hello World
Lets get right to everyone's favorite example: the following script will print out "Hello World" to the output console.
print "Hello World"
The print keyword is a handy tool in Python, allowing you to put text into the output console. This is useful for debugging your scripts. You can print multiple things by separating them with commas.
2012 Inductive Automation
Scripting
411
Variables
Variables are created by simply assigning a value to them. Variables do not need to be declared, because Python has a dynamic type system. That means Python figures out the type of the variable on the fly, when the script is executed. The following script would print out: 15
x=5 y=3 print x*y
Lists
In Python, lists (arrays) are a built-in type that contains multiple other values. Lists can contain any type of items, and the items in a list do not all need to be the same type. You can create a list by enclosing multiple items in square brackets ([]), separated with commas. You can pull items out of a list with the square-bracket list index notation. Note that lists are zero-indexed, meaning that the first item in the list is at position 0. This code will print out "a list".
a = ['this', 'is', 'a list', 8, 93.928] print a[2]
Basic operators
Python has all of the normal arithmetic operators you'd expect, addition(+), subtraction(-), division(/), multiplication(*), modulus(%), etc. The comparison operators are just like in C: equals(==), not equals(!=) greater than (>), greater than or equal(>=), etc. The logical operators are just typed in plain text: and, or, not. These are just the basics. There are other operators, like bit shift operators. Read about them at: http:// docs.python.org/library/stdtypes.html
Comments
Comments start with a hash sign. Add comments to your code so that when you go back to it after a long time, you know what the code is trying to do.
# Prints out 'Hello World' 5 times.
Scripting
412
Whitespace
Perhaps its most unique feature, logical blocks are defined by indentation in Python. A colon (:) starts a new block, and the next line must be indented (typically using a tab of 4 spaces). The block ends when the indentation level returns to the previous level. For example, the following will print out "5 4 3 2 1 Blast-off". The final print is not part of the loop, because it isn't indented.
countdown=5 while countdown > 0: print countdown, countdown = countdown - 1 print "Blast-off!"
5.2.2.2
Control Flow Control flow are the parts of a language that make it do things differently based upon various conditions. In other words: ifs and loops. Python has all of the basic control flow statements that you'd expect.
if Statements
If statement should be familiar to anyone with a passing knowledge of programming. The idea of an if is that you want your script to execute a block of statements only if a certain condition is true. For example, this script won't do anything.
x = 15 if x < 10: print "this will never show"
You can use the if...else form of an if statement to do one thing if a condition is true, and something else if the condition is false. This script will print out "this will show!"
x = 15 if x < 10: print "this will never show" else: print "this will show!"
Lastly, you can use the if...elif form. This form combines multiple condition checks. "elif" stands for "else if". This form can optionally have a catch-all "else" clause at the end. For example, this script will print out "three":
x = 3 if x == 1: print "one" elif x == 2: print "two" elif x == 3: print "three" else: print "not 1-3"
while Loops
A while loop will repeat a block of statements while a condition is true. This code will print out the contents of the items in the list. This code uses a function called len, which is a built-in function that returns the length of a list or string.
listOfFruit = ['Apples', 'Oranges', 'Bananas'] x = 0
Scripting
413
for Loops
Python's for loop may be a bit different than what you're used to if you've programmed any C. The for loop is specialized to iterate over the elements of any sequence, like a list. So, we could re-write the example above using a for loop eliminating the counter x:
listOfFruit = ['Apples', 'Oranges', 'Bananas'] for item in listOfFruit: print item
Much more graceful! You'll often see the for loop used instead of the while loop, even when you simply want to iterate a given number of times. To do this with the for loop, you can use the built-in function range. The range function returns a variable-size list of integers starting at zero. Calling range(4) will return the list [0, 1, 2, 3]. So, to have a for loop repeat 4 times, you simply can do:
for x in range(4): print "this will print 4 times"
You can use the continue statement to make a loop stop executing its current iteration and skip to the next one. The following code will print out the numbers 0-9, skipping 4
for x in range(10): if x == 4: continue print x
5.2.2.3
String Formatting String formatting is a somewhat minor feature of Python, but turns out to be incredibly useful in Ignition. String formatting is used to manipulate strings, specifically to insert the values of variables inside a string without a bunch of concatenation. The % operator is used in Python not just for modulus, but also for string formatting. Suppose we wanted to print a weather report. We could use concatenation, like this:
temp = 65.8 city = "Sacramento" windSpeed = 25 windDir = "east" print city + " weather: " + str(temp)
Yuck! This kind of concatenation is really a pain to write and to read. With string formatting, we could have written it like this:
temp = 65.8 2012 Inductive Automation
Scripting
414
city = "Sacramento" windSpeed = 25 windDir = "east" print "%s weather: %fF, wind %dmph from the %s" % (city, temp, windSpeed, windDir)
Ah, that's much easier on the eyes. What is happening here is that the % operator is applying the variables on its right-hand side to the format string on its left-hand side. It looks for placeholders (called format specifiers) inside the format string, and replaces them with corresponding values from the variables on the right-hand side. There are various format specifiers that can be used for different types of variable types. If you actually want a % sign inside the final string, use the special format specifier: "%%" Format Specifier %% %c %d or %i %f %s %u %x or %X Meaning Inserts a % sign into the final string A single character. Value must be a string of length 1 or an integer Signed integer Floating point, decimal format A String, converts the value to a string using str() Unsigned decimal Unsigned hexadecimal
You can also put some extra information in the format specifiers between the % and the format specifier character. The most useful thing to do is to specify the number of decimal places to use to print floating point numbers. For example, "%.3f" would always put three digits after the decimal point. 5.2.2.4 Functions Functions are code that can be called repeatedly from other places. Functions can have parameters passed into them, and may return a resulting value. Some functions, like len, are built-in. Some functions, like system.gui.messageBox(), are part of the scripting libraries provided by Ignition. Some functions, like math.sqrt(), are provided by the Python standard libraray. Functions are invoked by using their name followed by an argument list surrounded in parentheses. If there are no arguments, you still need an open and close parenthesis.
Defining Functions
Functions are defined using the def keyword. A function needs a name, and needs a list of the arguments that it can be passed. For example, this code defines a function that tests whether or not a number is odd. It returns a true value (1) if the number is odd. It is then used in a loop to print out the odd numbers between 0 and 9.
def isOdd(num): return num % 2 == 1 # uses the modulus (or remainder) operator for x in range(10): if isOdd(x): print x
Function Arguments
When a function accepts arguments, the names of those arguments become variables in the function's namespace. Whatever value was passed to the function when it was invoked becomes the value of those variables. In the example above, the value of x inside the for loop gets passed to the isOdd function, and becomes the value of the num argument.
2012 Inductive Automation
Scripting
415
Arguments can have default values, which makes them optional. If an argument is omitted, then its default value will be used. The following code defines a function called cap, which will take a number, and make sure it is within an upper and lower limit. The limits default to 0 and 100.
def cap(x, min=0, max=100): if x < min: return min elif x > max: return max else: return x # This will print out "0" print cap(-1) # This will print out "100" print cap(150) # this will print out "150", because it uses a max of 200 print cap(150, 0, 200)
Keyword Arguments Arguments can also be specified by k eyword instead of by position. In the above example, the only way someone would know that the 200 in the last call to cap specified the max is by its position. This can lead to hard-to-read function invocations for functions with lots of optional arguments. You can use keyword-style invocation to improve readability. The following code is equivalent to the last line above, using 200 for the max and the default for the min.
print cap(150, max=200)
Because we used a keyword to specify that 200 was the "max", we were able to omit the min argument altogether, using its default. Note that not all functions in the standard library and the Ignition library can be called with keyword invocation. Functions that accept keyword invocation, like system.tag.queryTagHistory, will say so in their documentation.
Scripting
416
newList = [] for entry in list: if filterFunction(entry): newList.append(entry) return newList # prints out [0, 2, 4, 6, 8] # notice that isEven as not _invoked_, but passed to the filter function print extract(isEven, range(10))
Now, it just so happens that Python has a built-in function that does exactly what our extract function does - its called filter. We would also be remiss at this point if we didn't mention another language feature called list comprehensions. This is a great little bit of syntax that helps make new lists out of other lists. Instead of using our filter function, we could have simply done this:
def isEven(num): return num % 2 == 0 print [x for x in range(10) if isEven(x)]
If that looks cool to you - read more about list comprehensions at http://docs.python.org/tutorial/ datastructures.html#list-comprehensions In Ignition, you'll most commonly see functions used as objects when using the system.util.invokelater function. This function takes a function and executes it after all pending event handling has finished processing. 5.2.2.5 Scope and Import The concept of scope is very important in all programming, and Python is no exception. Scope defines what names are directly accessible without any qualifiers. Another way to put this is that the scope determines what variables are defined. When you define a new function, that function gets its own scope. The statements within the function don't operate in the scope of the enclosing code. An example should make this clear:
x = 5 print x def fun(): x = 3 # this 'x' is not the same as the outer 'x' print x fun() print x
The assignment x = 3 within the function did not affect the x defined outside the function's scope. Furthermore, if you tried to access x within the function fun without the x = 3 line, you would receive a NameError, because x would not be defined.
Global Scope
2012 Inductive Automation
Scripting
417
Besides your immediate scope, there is also the global scope. By declaring a name preceded with the keyword global, your variable will be resolved using the global scope, which is shared by all scripts.
global x # will print whatever value some other script # assigned to x in the global namespace print x
For example, suppose you wanted to use the java.util.Calendar class for some date manipulations. You could import this in a number of different ways. These examples are equivalent, printing out a date 8 hours before the current date.
import java cal = java.util.Calendar.getInstance() cal.add(java.util.Calendar.HOUR, -8) print cal.getTime() from java.util import Calendar cal = Calendar.getInstance() cal.add(Calendar.HOUR, -8) print cal.getTime()
5.2.2.6
Sequences and Dictionaries Python offers a variety of sequence types. We've already seen one - the List. There are other kinds of sequences, most notably tuples and strings. There is also the dictionary type, which contains a list of key-value pairs.
Lists
Lists are a very handy kind of sequence. They can hold any number of items, can be resized on the fly. After creating a list using the square bracket notation, there are a number of functions that you can call on the list. Some common list functions are listed here. Visit http://docs.python.org/tutorial/ datastructures.html#more-on-lists for a complete list. append(x) - takes a single argument, which will be appended to the end of the list. insert(i,x) - inserts an item x at index i remove(x) - will remove the given item from the list. index(x) - returns the index of the value x. Throws an error if the list doesn't contain the item. Use
2012 Inductive Automation
Scripting
418
the in operator to check if an item is contained in a sequence. sort() - sorts the items in the list.
myList = ['a', 'b', 'c', 'd'] print myList # --> [a, b, c, d] myList.append("Q") print myList # --> [a, b, c, d, Q] myList.insert(1, "Z") print myList # --> [a, Z, b, c, d, Q] myList.remove("c") print myList # --> [a, Z, b, d, Q] print myList[2] # --> b print myLIst.index("b") # --> 2 if 'Z' in myList: print 'Z is in the list' if 'c' not in myList: print 'c was removed from the list'
Tuples
A tuple is similar to a list, but you use parenthesis instead of square brackets to define one. The major difference between a tuple and a list is that tuple's are immutable. That is, once created, they cannot be altered. Tuples are very useful for passing multiple things to and from functions. For example, you could pass a point to a function using a tuple like so:
def printPoint(point): print "x = ", point[0] print "y = ", point[1] printPoint((28,89))
This can also be handy for returning multiple values from a function. For example, if you had a mouse event, you could write a function that found the component's center point, and return that point as a tuple. You could then use unpack ing assignment to extract the values into separate values.
def findCenter(event): w = event.source.width h = event.source.height return (w/2, h/2) # point will be a tuple point = findCenter(event) # x and y will be numbers, using unpacking assignment x,y = findCenter(event)
Dictionaries
A dictionary is a very useful type that holds a set of key-value pairs. You may have used these in other languages and know them as hashmaps, maps, associative memories or associative arrays. Dictionaries are not ordered sequences - you reference any item via its k ey value. The keys can be
2012 Inductive Automation
Scripting
419
numbers, strings, or tuples of these types. Any given key may only appear once in a dictionary. Trying to set another value for that key will overwrite any previous value for that key. Dictionaries are created using braces ({}). Key-value pairs are separated by commas, and the keys are separated from the values with a colon. You can use the .keys() function to have a set of the keys. For example:
myDict = {'Bob': 89.9, 'Joe': 188.72, 'Sally': 21.44} print myDict['Bob'] # --> 89.9 myDict['Amir']=45.89 # Adds a key for 'Amir' names = myDict.keys() names.sort() print names # --> ['Amir', 'Bob', 'Joe', 'Sally']
You can loop through dictionaries using a for loop. You can use the keys() to loop through the dictionary, and then use the key values to look up the value. For example:
for name in myDict.keys(): print name, myDict[name]
5.2.2.7
Exception Handling Exception handling is a language feature of many high-level languages that allows you to "catch" a runtime error and deal with it as you see fit. On the flip side, it allows you to "raise" or "throw" an error in your code, which will break out of whatever code is currently executing and jump to the nearest enclosing catch block that knows how to handle your error. For example, dividing by zero raises a ZeroDivisionError. You can catch this error using a try... except block, like this:
try: result = 8 / 0 print "this will never get called" except ZeroDivisionError: print "oops - can't divide by zero"
You don't have to specify a particular type of error to catch - you can use the except keyword by itself to catch any kind of exception. You can also assign the details of the exception to a tuple of variables, which you can use in your error reporting. You can also have multiple except blocks for one try block, each that handle different kinds of exceptions. This example shows these variations:
def someDangerousFunction(): raise IOError(42,"oh no") try: someDangerousFunction() except IOError, (errno, description): print "An I/O error occurred: "+description except: print "An unexpected error occurred"
You can learn more about exceptions at http://www.python.org/doc/2.1/tut/node10.html. 5.2.2.8 Learn More
Online Tutorials
Since Python is such a popular and well-regarded language, there are many high-quality tutorials
2012 Inductive Automation
Scripting
420
available on the web. The official python tutorial, written by the inventor of Python himself, Guido van Rossum, is very good. http://www.python.org/doc/2.1/tut/tut.html The Non-Programmers Tutorial For Python by Josh Cogliati is also very good for those with no previous programming experience. http://www.oopweb.com/Python/Documents/easytut/VolumeFrames.html You can go and download a printable Python "cheat sheet" from the Added Bytes website, available here: http://www.addedbytes.com/cheat-sheets/python-cheat-sheet/
Recommended Books
Sometimes a good reference book is invaluable. The following books have gotten good reviews from us and our customers: Learning Python (O'Reilly, 2007) Python Pocket Reference (O'Reilly, 2005) Core Python Programming (Prentice Hall, 2006) Python Power (Course Technology, 2007)
Using Java
This book would be useful for anyone who finds themselves accessing the Java standard library frequently from Python: Python Programming with the Java(TM) Class Libraries (Addison-Wesley, 2002) You can also find the excellent API documentation for the Java standard libraries from Sun here: http://java.sun.com/j2se/1.5.0/docs/api/index.html
Online Forum
Our online forum at http://www.inductiveautomation.com/forum is a great place to go for scripting help. Not only do we, the Inductive Automation staff, monitor it actively, but we have a thriving user community who can help you with any scripting questions.
5.2.3
5.2.3.1
Python in Ignition
Working with Different Datatypes You'll encounter lots of different datatypes when scripting in Python. This guide should help you through the snags of working with some of the more complex types.
Numbers
Working with numbers is very easy in Python, and requires no special considerations. You can use the built-in function int() to attempt to coerce values to integers, and float() to coerce values to floating-point values. Both will throw ValueError if the coercion fails. If you are new to programming, the following might throw you off. Python, like nearly all programming languages, uses integer division when dividing two integers. This means that 1/2 will result in 0. This is because both 1 and 2 are integers, so the result of the division must be an integer. The result of 0.5 gets truncated to 0. If either operand is a float, the result will be a float, so 1 / 2.0 will result in 0.5.
Scripting
421
Strings
Strings are used frequently in scripting. Strings can be defined using double quotes or single quotes. Learning how to use String Formatting is a very useful technique. You can user the built-in function str () to coerce values into strings.
Colors
Working with colors in Python is remarkably easy. You can simply use any tuple of 3 or 4 integers to represent a color in RGB or RGBA. For example, to set a label's text color to red, you can simple do something like this:
label = event.source label.foreground = (255,0,0)
Dates
Dates are one of the trickier datatypes to deal with in scripting. It turns out that it is easier to deal with dates using the Java classes java.util.Date and java.util.Calendar than it is to use Python's time module. Creating Dates To create an arbitrary date, you can use the java.util.Calendar class. It has various functions to alter the calendar fields, like Calendar.HOUR, Calendar.MONTH, etc. After you're done manipulating the Calendar, you can use its getTime() function to retrieve the Date represented by the calendar. It also has a handy set() function that takes the common parameters of a Date. The one major gotcha here is that January is month zero, not month one. For example:
from java.util import Calendar cal = Calendar.getInstance() # set year, month, day, hour, minute, second in one call # This sets it to Feb 25th, 1:05:00 PM, 2010 cal.set(2010, 1, 25, 13, 5, 0) myDate = cal.getTime()
Date Arithmetic Often you'll have a Date object from a component like the Popup Calendar and want to alter it programmatically. Say, subtracting 8 hours from it, or something like that. The java.util.Calendar class is used for this as well. Following the example above, this code would subtract 8 hours from the variable myDate.
from java.util import Calendar cal = Calendar.getInstance() cal.setTime(myDate) cal.add(Calendar.HOUR, -8) myNewDate = cal.getTime()
Date Formatting To format a date as a String, you can use the system function system.db.dateFormat. This function uses a format string to give it a hint as to how you want your date formatted. The format string is full of various placeholders that will display different parts of the date. These are case-sensitive! The most common placeholders are:
Scripting
422
y M d E a H h m s S z
Year Month Day Day of Week am/pm marker Hour of day (0-23) Hour in am/pm (1-12) Minute Second Millisecond Time zone
These placeholders can be repeated for a different effect. For example, M will give you 1-12, MM will give you 01-12, MMM will give you Jan-Dec, MMMM will give you January-December. Here are some examples:
from java.util import Date now = Date() # creates a new date, for right now # Common format for databases print system.db.dateFormat(now, "yyyy-MM-dd H:mm:ss") # Nice human-readable format for just the date print system.db.dateFormat(now, "MMM d, yyyy") # Formating just the time in am/pm style print system.db.dateFormat("h:mm a")
Datasets
It is very common to deal with datasets in scripting, as datasets power many of the interesting features in Ignition, like charts and tables. The system.dataset library provides various functions for manipulating and creating datasets. The main confusion when dealing with datasets is the difference between the DataSet object and the PyDataSet object. DataSet is the kind of object that Ignition uses internally to represents datasets. When you get the data property out of a Table, for example, you'll get a DataSet. The PyDataSet is a wrapper type that you can use to make DataSets more accessible in Python. You can convert between the two with system.dataset.toPyDataSet and system.dataset.toDataSet. Accessing data in a DataSet DataSets have various properties and functions that you can access through Python. rowCount - returns the number of rows in the dataset columnCount - returns the number of columns in the dataset getColumnName(index) - returns the name of the column at the given index getValueAt(row, column) - returns the value from the dataset at the given location. column can be either an integer or a column name, which is treated case-insensitive. For example, you could iterate through every item in a DataSet in scripting like this:
# Pull the dataset property off a Table component data = event.source.getComponent("Table").data for row in range(data.rowCount): for col in range(data.columnCount): print data.getValueAt(row, col)
Scripting
423
or you could find specific values from each row in a DataSet like this:
# Pull the dataset property off a Table component data = event.source.getComponent("Table").data for row in range(data.rowCount): temp = data.getValueAt(row, "Temperature") speed = data.getValueAt(row, "Speed") print temp, speed
Accessing data in a PyDataSet You can convert a dataset to a PyDataSet, which lets you use it more like a Python sequence. You don't have to do this, its purely a convenience. A PyDataSet is like a list of dictionaries, and so it can use the normal for loop syntax. These examples are equivalent to the examples above. Iterating through a PyDataSet
# Pull the dataset property off a Table component data = event.source.getComponent("Table").data # Convert to a PyDataSet pds = system.dataset.toPyDataSet(data) for row in pds: for value in row: print value
Altering Datasets Technically, you cannot alter a dataset. Datasets are immutable, meaning they cannot change. You can, however, create new datasets. So to alter a dataset, you really create a new one and then replace the old one with the new one. Because this is so common, there are special functions under system. dataset that are designed for this. You can use the following functions to create datasets that are altered version of existing datasets: system.dataset.addRow system.dataset.deleteRow
2012 Inductive Automation
Scripting
424
system.dataset.setValue system.dataset.updateRow The important thing to realize about all of these datasets is that, again, they do not actually alter the input dataset. They return a new dataset. You need to actually use that returned dataset to do anything useful. For example, this code would set the "Quantity" column in the selected row of a table to 15.8:
table = event.source.parent.getComponent("Table") selRow = table.selectedRow if selRow != -1: # Create a new dataset newData = system.dataset.setValue(table.data, selRow, "Quantity", 15.8) # Replace the Table's data property with the new dataset table.data = newData
Creating Datasets Sometimes you'll want to create a new dataset from scratch. This can be easily done with the system. dataset.toDataSet function. All it needs are the column headers and a list of the rows in the dataset. Each row must have the same number of elements as the header list. For example, this code would create a dataset that contained some information about US cities:
headers = ["City", "Population", "Timezone", "GMTOffset"] data = [] data.append(["New York", 8363710, "EST", -5]) data.append(["Los Angeles", 3833995, "PST", -8]) data.append(["Chicago", 2853114, "CST", -6]) data.append(["Houston", 2242193, "CST", -6]) data.append(["Phoenix", 1567924, "MST", -7]) cities = system.dataset.toDataSet(headers, data)
5.2.3.2
Working with Components When you're writing component event handlers, you'll do a lot of work with components. You'll need to reference various components on the window or on other windows, you'll need to reference and set properties of the component, you may even want to move components around on the screen.
Finding Components
When you have an event object, that object becomes your window into the entire component hierarchy. event.source references the component that fired whatever event you're responding to. event.source.parent references the container that component is in. event.source.parent. getComponent("Name") finds a sibling component with a certain name. The manual page for the event object covers this topic in more detail.
Scripting
425
# Referencing properties of a component row = table.selectedRow system.gui.messageBox("The selected row is : %d" % row) # Setting properties of a component. table.selectedRow = -1 # Calling functions on components table.print()
Scripting
426
try: window = system.gui.getWindow("Popup3") window.setSize(250,600) window.setLocation(0,0) except ValueError: # ignore error with a pass keyword pass
See also: The 'event' object 5.2.3.3 Global Script Modules Your project can have a set of global script modules that any other script can reference. These modules all reside under the app namespace. These modules are available in bath Gateway and Client scope scripts. This is a great way to extract common logic into a central place - a core tenet of a well designed code. To use your global script module, you'll need to have app imported into your current scope. Event handler scripts get this automatically, but user defined functions and other scripts will have to use import app to use global script modules. See also: Script Modules 5.2.3.4 Gateway vs Client Scripts Your project can execute scripts under two different scopes: Gateway and Client. Gateway scripts execute on the Ignition Gateway, which means that they will always execute in exactly one place. Client scripts execute on each running Client. Because Clients are full-fledged applications, this means that the scripts are running on the computer running the client, not on the Gateway's host server computer. This means that they don't have access to the Gateway's filesystem, etc. It also means that if no clients are launched, the scripts will not be executing. See also: Project Event Scripts 5.2.3.5 Timer, Keystroke, and Tag Change Scripts You can have scripts run for all sorts of global events. These are called project event scripts. You can have a script run every time a tag changes value, a key is pressed etc. See also: Project Event Scripts 5.2.3.6 Python Standard Library You can use much of the Python standard library in Ignition. The available modules are listed here. Learn more about the python standard library at http://www.python.org/doc/2.1/lib/lib.html base64 htmlentitydefs site
Scripting
427
bdb bisect calendar cmd colorsys commands ConfigParser copy copy_reg difflib dircache dospath fileinput fnmatch formatter fpformat ftplib gzip
5.2.3.6.1 Component Event Handlers
htmllib httplib javaos javapath linecache marshal mimetypes ntpath nturl2path pdb pickle posixpath pprint Queue random re repr shutil
socket sre sre_compile sre_constants sre_parse stat string StringIO tempfile urllib urlparse UserDict UserList UserString xmllib zipfile zlib __future__
Using scripts to handle component events is one of the most common places to use scripting in Ignition. When an event occurs for a component, like a mouse click or a key press, you can have your script (the event handler) be called. When your event handler is executed, it already has three names in scope: event - the event object system - the root of the Ignition Scripting API app - the root of your project's script modules See also: Event Handlers Overview 5.2.3.7 Accessing Java When programming Python in Ignition, your code executes in the Jython implementation of Python. (See About Scripting - Python or Jython?). While this doesn't have any great effect on the Python language itself, one of the great side benefits is that your Python code can seamlessly interact with Java code, as if it were Python code. This means that your Python code has access to the entire Java standard library, which is saying a lot. To use Java classes, you simple import them as if they were Python modules. For example, the following code will print out all of the files in the user's home directory. This code uses the Java classes java.lang.System and java.io.File to look up the user's home directory and to list the files. Notice that we can even use the Python-style for loop to iterate over a Java sequence.
from java.lang import System from java.io import File homePath = System.getProperty("user.home") homeDir = File(homePath) for filename in homeDir.list(): print filename
Scripting
428
You can find the reference documentation for the Java standard class libraray (a.k.a. the "JavaDocs") here: http://java.sun.com/j2se/1.5.0/docs/api/index.html
Subclassing Java
You can even create Python classes that implement Java interfaces. If this is greek to you - don't worry, it isn't crucial. You'd need some understanding of Java and object-oriented programming concepts, which are outside the scope of this manual. To create a Python class that implements a Java interface, you simply use the interface as a superclass for your Python class. For example, we could augment the example above to use the overload java. io.File.list(FilenameFilter). To do this, we'll need to create a FilenameFilter, which is an interface in Java that defines a single function: boolean accept(File dir, String name) To implement this interface, we create a Python class that has java.io.FilenameFilter as its superclass, and implements that Java-style function in a Python-esque way.
from java.lang import System from java.io import * class ExtensionFilter(FilenameFilter): def __init__(self, extension=".txt"): self.extension=extension.lower() def accept(self, directory, name): # make sure that the filename ends in the right extension return name.lower().endswith(self.extension)
homePath = System.getProperty("user.home") homeDir = File(homePath) # prints out all .txt files for filename in homeDir.list(ExtensionFilter()): print filename # prints out all .pdf files for filename in homeDir.list(ExtensionFilter(".pdf")): print filename
5.2.4
5.2.4.1
Scripting
429
web service will return a formatted XML string that you will have to parse through manually in order to make the data presentable.
A Simple Example
If you read through the SUDS documentation you'll see that the Client object is the primary interface for most users. It is extremely simple using this object and a few print statements to view a list of available methods provided by the web service you are connecting to. This example will illustrate how to make an initial connect to a web service, print out the list of available methods, and then call one of these methods and display the resulting value in a label on an Ignition window at the push of a button. The below example uses a public web service and is available for anyone to test against. First, we can use the script playground to test out some scripting calls and see the output. The below example shows how to get a reference to a client object. By printing this client object to the console we get an output of all the available methods, types and other information about the web service as defined in the WSDL file.
Scripting
430
This WSDL defines two functions: CelsiusToFahrenheit(string Celsius) and FahrenheitToCelsius(string Fahrenheit). These are the functions that this web service makes available to you. Don't worry about the fact that the methods are listed twice. This is just because the WSDL has two definitions of the functions that are formatted for different SOAP version standards. To call these functions in Ignition scripting you have to make use of the "service" member of the client object.
Scripting
431
To make a simple conversion window in an Ignition project you can add two buttons, a numeric textbox, and a lable to a window. Then on the button to be used to calculate a Fahrenheit to Celsius calculation you would place something like the following:
Scripting
432
Scripting
433
With your scripts in place your window should now function as a simple temperature conversion tool!
Scripting
434
This example is extremely simple and rather straight forward. The main steps to remember when attempting to use the SUDS library in scripting are as follows: 1. Import the SUDS Client object
from suds.client import Client
5.2.4.2
Complex Arguments In the overview example the methods provided by the web service were very simple and took simple argument types. Sometimes however the web service will describe complex types and allow you create instances of these types that can then be added to the system/machine that the web service is providing an interface for. A simple, hypothetical example of this would be a system that stores contact information of clients and can be used as an address book of sorts by other systems on the network. It may provide not only a way to pull contact information for a certain individual out but also a way to insert new contacts. We'll keep the example simple and say that contacts have only a name and a phone number.
Scripting
435
This example is completely hypothetical. It is intended to give insight into complex types. It does not make use of an an actual functional web service. A very similar example can be found in the SUDS documentation. Say we create and print the client object we associated with our web service in the following manner
from suds.client import Client url = 'http://localhost:7575/webservices/hypothetical_webservice?wsdl' client = Client(url) print client
Service (hypothetical_webservice) Prefixes (0): Ports (1): (Soap) Methods: addContact(Contact contact, ) getContactList(xs:string str, xs:int length, ) getContactByName(Name name, ) Types (3): Contact Name Phone
Here you can see that, while not too complicated the web service defines more than just methods that take simple type arguments and return the same. Under the Types section you can see there are three "complex" types. These are basically just objects like one creates in an object oriented programming language like java. The SUDS Client object has an instance variable called "factory" that allows you to create these complex types so you can use them to invoke methods defined by your web service that take complex arguments. If we wanted to add a contact using the addContact() method we have to create a contact object first:
contact = client.factory.create('Contact') print contact
The create function creates a new contact object that knows its own structure. We can view this structure by calling print on this new object and see that it prints the following:
(Contact)= { phone = [] age = NONE name(Name) = { last = NONE first = NONE } }
By examining the Contact type object we can see its structure and know what we need to create in order to have a valid Contact to add to the address book. We could then do the following to supply the necessary information for the Contact object and then call our addContact function.
phone = client.factory.create('Phone') phone.arecode = '916' phone.number = '5557777'
Scripting
436
name = client.factory.create('Name') name.first = 'John' name.last = 'Doe' contact.name = name contact.phone.append(phone) client.service.addContact(contact)
After execution a new contact will have been added via the web service. There is also a way to use python dictionaries to specify complex arguments that is detailed in the SUDS documentation. Steps to remember when using complex types: 1. Create a new type object using the factory instance variable of the Client object
my_type = client.factory.create('MyType')
2. If you don't know the structure of the newly created object then print it to the console
print my_type
5.2.4.3
Parsing XML Results It's quite easy deal with return values of method calls when they are simple none structured values like floats or integers. However it's not always the case that you will have simple single values returned from a method call. Many times web services will return values that have some sort of structure to them like a dataset. Since there is no way for the web service to know how this value should be represented in the language/environment that called the method it is common that the result will be returned in an XML formatted string. Dealing with these strings is not really part of the SUDS library but an example of XML string handling is included here for completeness. This example makes use of the xml.dom.minidom python module to parse the XML string and pull out the data.
2. The elements variable will now contain a structured string of the following format. We take note of this format so we will know how to parse the string.
<NewDataSet> <Table> <ElementName>Actinium</ElementName> </Table> ... </NewDataSet>
Scripting
437
3. Now we can parse the string and create a list of the element data
dom = parseString(xml_string) xmlTags = dom.getElementsByTagName('ElementName') xmlData = [] for tag in xmlTags: xmlData.append(tag.firstChild.data)
4. The xmlData list now contains all of the names of the elements from the periodic table. Now let's get separate lists for all of the atomic numbers, atomic weights, and element numbers in the same order as our element list
element_weights = [] element_numbers = [] element_symbols = [] for name in element_names: weight = parseString(client.service.GetAtomicWeight(name)).getElementsByTagName('AtomicWeig number = parseString(client.service.GetAtomicNumber(name)).getElementsByTagName('AtomicNumb symbol = parseString(client.service.GetElementSymbol(name)).getElementsByTagName('Symbol')[ element_weights.append(weight) element_numbers.append(number) element_symbols.append(symbol)
5. With our four lists we can now go about building a dataset and then use the dataset to set the data property on a table
headers = ["Name", "Symbol", "Weight", "Number"] i = 0 rows = [] for name in element_names: oneRow = [name,element_symbols[i],element_weights[i],element_numbers[i]] rows.append(oneRow) i += 1 data = system.dataset.toDataSet(headers, rows) event.source.parent.getComponent('Table').data = data
6. Put all of that together and throw it on a button's actionPerformed event inside a window with a table on it and test away! It should be noted that this script will take a couple minutes to run since there is no function to get all of the weights, numbers or symbols in one method call. Be patient.
5.3
5.3.1
Expressions
Overview
The expression language is used to define dynamic values for component properties and expression tags. Expressions often involve one or more other values that are used to calculate a final value. Expressions don't do anything, other than return a value. The classic example for an expression is to change a temperature that is stored in Celsius to Fahrenheit in order to display it. Suppose you had a tag, Tank6/Temp that was in Celsius. If you wanted to display that tag in Fahrenheit on a Label, you would use an Expression Binding on the label's text property using the following expression:
1.8 * {Tank6/Temp} + 32
Every time that the temperature tag changes, the expression will re-calculate the value and push it into the Label's text property. Now lets say that you wanted to append a "F" to the end of the label so that
Scripting
438
the user knew the units of the temperature. You could simply use some string concatenation in your expression, like this:
(1.8 * {Tank6/Temp} + 32) + " F"
Lets suppose that you wanted to give the user an option to display the value in Celsius or Fahrenheit, based on checking a checkbox. You could add a Check Box component to th screen called DisplayFahrenheit. Then you could use this expression to dynamically display either unit, based upon the user's selection:
if({Root Container.DisplayFahrenheit.selected}, (1.8 * {Tank6/Temp} + 32) + " F", {Tankf/Temp} + " C")
5.3.2
Syntax
As its name suggests, everything in the expression language is an "expression". This means that everything returns a value. 5 is an expression. So is 5+1. So are {MyTags/TankLevel} and {MyTags/TankLevel}+1. Expressions can be combined in many powerful ways. Lets take a look at how expressions are written. More formally, an expression is: A Number A Boolean A String A bound SQLTag A bound property A function call A Dataset access An equation involving any of these
Literal Values
Literal values are things like numbers, booleans, and strings that are represented directly in the language. In the expression language, numbers can by typed in directly as integers, floating point values, or using hexadecimal notation with a 0x prefix. Examples:
42 8.927 0xFFC2
Strings are represented by surrounding them with double or single quotes. You can use the backslash character to escape quotes that you want to be included in the string. Examples:
"This is a regular string" 'This one uses single quotes' "This string uses \"escaping\" to include quotes inside the string"
Scripting
439
Operators
You can use these arithmetic, logical, and bit-shifting operators to combine expressions. - Unary Minus Negates a number. ! Not Logical opposite of a boolean ^ Power Raises a number to the power of another number. a^b is ab % Modulus Modulus or remainder of two numbers. a%b is the remainder of ab * Multiply / Divide + Add / If both operands are numbers, this will add them together. Otherwise treats Concatenate arguments as strings and performs concatenation. - Subtraction & Bitwise AND | Bitwise OR xor Bitwise XOR << Left Shift A signed bitwise left shift >> Right Shift A signed bitwise right shift > Greater Than Logical greater-than test between two numbers. Returns a boolean. < Less Than >= Greater or Equal <= Less or Equal = Equal Tests for equality between two operands. != Not Equal Tests for equality, returning true when not equal && Logical AND Returns true when both operands are true. Anything non-zero is considered true. || Logical OR Returns true when either operand is true. Anything non-zero is considered true. like Fuzzy string Compares the left-hand value with the pattern on the right side. The pattern may matching consist of %,*, and ? wildcards.
Bound Values
Bound values are paths to other values enclosed in braces. These will appear red in the expression editor. When you are writing an expression for a Expression Binding, you can reference tag values and property values using the brace notation. When you are writing an expression for an Expression Tag, you can only reference other tag values. You can use the Insert Property ( ) and Insert Tag Value ( ) buttons to build these references for you.
Dataset Access
If you have an expression that returns a Dataset, you can pull a value out of the datatset using the dataset access notation, which takes one of these forms: Dataset_Expression returns the value from the first row at the given column name ["Column_Name"] Dataset_Expression [Row_Index] returns the value from the given row at the first column Dataset_Expression [Row_Index, returns the value from the given row at the given column name "Column_Name"] Dataset_Expression [Row_Index, returns the value from the given row at the given column index Column_Index] For example, this expression would pull a value out of a Table at row 6 for column "ProductCode":
{Root Container.Table.data}[6, "ProductCode"]
Scripting
440
Note that you'll often have to convince the expression system that what you're doing is safe. The expression language can't tell what the datatype will be for a given column, so you may have to use a type-casting function to convince the expression language to accept your expression, like this:
toInt({Root Container.Table.data}[6, "ProductCode"])
Functions
The expression language's functions are where much of the real power lies. A function may take various arguments, all of which can themselves be any arbitrary expression. This means that you can use the results of one function as the argument to another function. In general, the syntax for a function call is: functionName(expression1, expression2, ...) The rest of this user manual section is devoted to the various functions available.
442
6
6.1
Label Component
The Label component is one of the components that accepts HTML, making it very versatile. A label can display text, images, or both. The text can be HTML formatted. Here are the steps to add HTML to a label: 1. Open the Ignition Designer and drag the Label component from the Display tab of the Component Palette. 2. The Label component has a Text property for what is displayed. By default the text is a single line. We can add HTML to make the label multi-line, bold certain text, underline certain text and more. Set the text property to the following:
<HTML>First Line<BR>Second Line
Button Component
The Button component also accepts HTML: 1. Open the Ignition Designer and drag the Button component from the Buttons tab of the Component Palette. 2. The Button component also has a Text property for what is displayed. By default the text is a single line. Set the text property to the following:
<HTML>Export<BR>To <B>CSV</B>
443
Mouseover Text
One of the most powerful places to use HTML is on the Mouseover Text property that exists on every component. The Mouseover Text is the text that is displayed in the tooltip, which pops up on mouseover of the component. You can display information about the component or the signal it is bound to. 1. Open the Ignition Designer and drag a Label component from the Display tab of the Component Palette. 2. The Label component has a Mouseover property. By default the text is a single line. Set the Mouseover property to the following:
<HTML>Instructions<BR><UL><LI>Step 1</LI><LI>Step 2</LI><LI>Step 3</LI></UL>
3. Open the client (runtime) and hover your mouse over the component to see the tooltip.
(*NOTE: Here the tooltip w as added to the label from the first example)
Table Component
Another place you can add HTML is the Table component. You can add HTML to the header row or to each of the individual cells of the table. To add HTML to the header: 1. Open the Ignition Designer and drag the Table component from the Tables tab of the Component Palette. 2. In the Property Editor, check the checkbox on the Test Data property to fill in some test data. 3. To change the table's header we need to use the Table Customizer. Right click on the table and select Customizers > Table Customizer. 4. In the header row you can add HTML to the display text in each column. Note: If you are using line breaks, you must put them in the first visible column header to set the height. Set the header value of the first column to the following:
444
<HTML>Column<BR>1
6.2
445
446
2. Navigate to the Server Endpoints tab. 3. If there is already an endpoint present, click Edit, otherwise click Add 4. Choose the correct network adapter for your system. Leave the port alone. 5. Check Basic128Rsa15 and uncheck None and Basic256. 6. Press OK.
447
8. There will be a certificate from the Ignition gateway already present but with a red X through it, right click the certificate and select trust. 9. If there are more than one items in this list named 'Ignition OPC-UA Client', delete all of them and wait for Ignition to recreate one. You may have to close this screen and reopen it.
Connected!
After following these steps you should have created a successful connection to KEPServerEX and the you should see a status of "CONNECTED" listed next to your new server connection in the Ignition gateway. If the status does not read connected try clicking the edit link next to the server connection, scrolling down to the bottom of the connection configuration page and then clicking save. In the case where the status of the connection is still reading something other than "CONNECTED" click the "OPC Connection Status" link at the bottom of the OPC Server Connections page and see if there are any useful messages to help troubleshoot the issue. Also ensure that your firewall is not blocking traffic on the port
448
Other UA Servers
While this example is specific to KEPServerEX, the same concepts apply to connecting to any other third party OPC server that accepts OPC-UA client connections. The only difference may be in the way that the certificates are accepted on the server. The Ignition OPC-UA server sends the client certificate to the third party OPC server when it tries to make the connection, however if the OPC server is not designed to expect these certificates then there may not be a straight forward way to accept them. In these cases you can manual download a client ticket from Ignition and supply it to the OPC server in the appropriate manner. To download a client certificate manually follow these steps: 1. Navigate to the Ignition Gateway Configuration page 2. Click the "Certificates" topic link under the "OPC-UA" section. 3. There will be three certificate options under the "This Gateway" tab. Click the download link under the "Ignition OPC-UA Client" section and save the certificate somewhere to disk. 4. This certificate is then supplied to your third party OPC server in a way specific to that server. This can usually be found in the respective server's documentation.
6.3
Ignition's wrapper.log
All of the error messages from your Gateway Event Scripts are logged to one file: wrapper.log. You can find this file in the install directory under Version 7.3+ <INSTALL DIR>\Inductive Automation\Ignition\logs\wrapper.log Version 7.2- <INSTALL DIR>\Inductive Automation\Ignition\wrapper.log When you open this file, scroll to the bottom to see the newest messages. If you have just started Ignition for the first time you will see something like this:
STATUS STATUS STATUS STATUS STATUS STATUS STATUS INFO | INFO |
| wrapper | 2011/11/23 10:47:09 | --> Wrapper Started as Service | wrapper | 2011/11/23 10:47:09 | Java Service Wrapper Standard Edition 32-bit 3.5.4 | wrapper | 2011/11/23 10:47:09 | Copyright (C) 1999-2010 Tanuki Software, Ltd. All Ri | wrapper | 2011/11/23 10:47:09 | http://wrapper.tanukisoftware.com | wrapper | 2011/11/23 10:47:09 | Licensed to Inductive Automation for Ignition Gatewa | wrapper | 2011/11/23 10:47:09 | | wrapper | 2011/11/23 10:47:09 | Launching a JVM... jvm 1 | 2011/11/23 10:47:09 | WrapperManager: Initializing... jvm 1 | 2011/11/23 10:47:10 | Nov 23, 2011 10:47:10 AM org.apache.catalina.startup.Embed
449
INFO | jvm 1 | 2011/11/23 10:47:10 | INFO: Starting tomcat server INFO | jvm 1 | 2011/11/23 10:47:10 | Nov 23, 2011 10:47:10 AM org.apache.catalina.core.Standard INFO | jvm 1 | 2011/11/23 10:47:10 | INFO: Starting Servlet Engine: Apache Tomcat/6.0.18
This file is in constant use by the Ignition system and is being modified in realtime. It is recommended that you download a tool like Wintail that will allow you to view the tail-end (hence the name) of the changing wrapper.log without having to constantly reopen the file. Output to the wrapper.log file Gateway Event Script errors are not the only handy bits of information logged to the wrapper file. Print statements that you add to your Gateway Event Scripts are also output to the wrapper.log file. Print statements can be extremely helpful in troubleshooting tricky pieces of scripting. Adding a few simple print statements can help you see values of variables as a script is being executed, or even allow you to see how far your script is getting if it is seeming to merely stop with out throwing an error. 1.In the designer go to the Gateway Event Scripts found under Projects > Event Scripts (Gateway) 2.Click on the Timer option and add a new timer script with the default settings. 3.Add this code to you Timer Script:
print "Hello World"
4.Click OK and then save your project. Your script will now be running every second and you will begin to see messages appear in the wrapper. log file similar to the following:
INFO INFO INFO INFO INFO | | | | | jvm jvm jvm jvm jvm 1 1 1 1 1 | | | | | 2012/8/23 2012/8/23 2012/8/23 2012/8/23 2012/8/23 11:12:56 11:12:57 11:12:58 11:12:59 11:13:00 | | | | | INFO [Project[IADemo] ] [11:12:56,044]: Restarting gateway Hello World Hello World Hello World Hello World
If an error is generated in your script is will show up in the wrapper looking something like:
INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO INFO | | | | | | | | | | | | | | | | | | | | | | jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm jvm 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | | | | | | | | | | | | | | | | | | | | | | 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 2011/11/23 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36 11:20:36
| ERROR [TimerScriptTask ] [11:20:36,310]: Error executing g | Traceback (innermost last): | File "<TimerScript:IADemo/test (1000) [Delay, Shared]>", | TypeError: write(): expected 2-3 args; got 1 | | at org.python.core.Py.TypeError(Py.java) | at org.python.core.PyReflectedFunction.throwError(PyRe | at org.python.core.PyReflectedFunction.throwArgCountEr | at org.python.core.PyReflectedFunction.throwError(PyRe | at org.python.core.PyReflectedFunction.__call__(PyRefl | at com.inductiveautomation.ignition.common.script.Scri | at org.python.core.PyObject.__call__(PyObject.java) | at org.python.core.PyObject.invoke(PyObject.java) | at org.python.pycode._pyx1.f$0(<TimerScript:IADemo/tes | at org.python.pycode._pyx1.call_function(<TimerScript: | at org.python.core.PyTableCode.call(PyTableCode.java) | at org.python.core.PyCode.call(PyCode.java) | at org.python.core.Py.runCode(Py.java) | at com.inductiveautomation.ignition.common.script.Scri | at com.inductiveautomation.ignition.common.script.Time | at java.util.TimerThread.mainLoop(Unknown Source) | at java.util.TimerThread.run(Unknown Source)
450
Here the error message is split over two lines: File "<TimerScript:IADemo/test (1000) [Delay, Shared]>", line 1, in ? and TypeError: write(): expected 2-3 args; got 1 There was no code snippet here but there should be enough information presented to get a pretty good idea of what went wrong. The first part of the error gives the type of script, project name, and script name in which the error occurred. The line number of the script on which the error occurred is also presented. Part two of the error is a little more cryptic but still decipherable if you are familiar with some of Ignition's built in scripting functions. One of the built in functions is system.tag.write(), this function takes 2 - 3 arguments as per its documentation in the user manual under Appendix C. This error message is reporting that only one argument was received. With this information one should be able to locate the script that's causing the error and make the appropriate edits to resolve the issue.
6.4
451
machine that Ignition is being installed and if the proposed solution is rather limited then the default 1024MB may be excessive; the initial heap size may also be too large. Ignition makes these memory settings available for you to adjust to best fit your personal requirements. These settings are found in the ignition.conf file which is located: <INSTALL_DIRECTORY>Inductive Automation\Ignition\data (Windows installations) or /var/lib/ignition/data (default Linux installations)
452
Ignition Service Will Not Start After Modifying Java Heap Space Settings
If you run into the case where the Ignition service fails to start after you have adjusted the Java Heap space settings it merely means that you have likely allocated too much (or too little) memory. This is something that is common when adjusting the heap space settings on a 32-bit machine. While the upper limit on a 32-bit machine is 1536MB, sometimes the operating system won't be able to allocate this much contiguous space in memory. Just follow the steps from above and start lowering the memory incrementally (remember, multiples of 8) until the Ignition service is able to start and function normally.
6.5
Other Notes: Un-map drive on shutdown: wrapper.share.1.shutdown.unmap=TRUE How often to retry server connection: wrapper.share.1.startup.max_retries=2 What interval (seconds) between retries: wrapper.share.1.startup.retry_interval=10
2012 Inductive Automation
453
Set wrapper to fail to startup if network share not found: wrapper.share.1.startup.failure=SHUTDOWN Troubleshooting: Here a couple of the common problems that are encountered when mapping network shares: Server not found The debug output will show something like this if a drive can't be reached: wrapper | Attempting to map the "\\fileserver\folder" share to "S:"... wrapper | Unable to map "S:". Attempt #1 (The network name cannot be found. (0x43)) wrapper | Attempting to map the "\\fileserver\folder" share to "S:"... wrapper | Unable to map "S:". Trying to continue. (The network name cannot be found. (0x43))
Incorrect Login Data If the configured account or password are incorrect (or are missing) then the mapping will fail with a message like the following: wrapper | Attempting to map the "\\myfileserver\commonshare" share to "S:"... wrapper | Unable to map "S:". Trying to continue. (Access is denied. (0x5))
6.6
454
2. Link the Table to an SQL Query Once the table is in the window, the next step is to bind the Data property to a SQL query pointing to the table you want to edit in the database. To do this click on the Bind icon to the right of the data property and select the SQL Query binding type. Then, type in a SQL query for that table and click OK.
3. Select Which Columns are Editable Now that the table component is showing data, you need to set which columns will allow the user to edit in the run-time. This way a user can double-click in any cell in those columns to change the value. To do this, right-click on the table component and select Component Customers -> Table Customizer. The Table Customizer is where you configure the columns' display properties, as well as any row mapping configuration. When you open the Table Customizer, you will see a table that has all of your data's columns across the top, and all of the column display properties across the left. You can
455
configure each column to have its own display properties. Once such column display property is called Editable. By checking the box you are allowing that column to become editable in the run-time.
456
col = event.column # The column's name colName = event.source.data.getColumnName(col) # The new value value = event.newValue # The primary key's value (first column), so that the appropriate row can be updated in the db id = event.source.data.getValueAt(row, 0) # Run an update query to the table that is being edited to reflect any changes system.db.runPrepStmt("UPDATE customers SET %s = ? WHERE ID = ?" % colName, [value, id])
Again, this script will run any time a user makes a valid edit to one of the editable cells in the table.
6.7
457
system.nav.goForward system.nav.goHome We will cover a few of these functions in this how-to. Next, let's look at the three typical window types in Ignition. By manipulating a window's properties, you can transform it into various configurations. Typically, you choose what kind of window you want when you create the window. However you can also alter the window's Dock Position, Border Display Policy, Titlebar Display Policy, and Start Maximized properties to change windows into one of three categories: Main Windows Docked Windows Popup Windows A main window is one that is set to start maximized, and has its border and titlebar display policies set to When Not Maximized or Never. This will make the window take up all available space (minus space used by any "docked" windows). This makes the window act much like a typical "HMI screen." You may also see these referred to as "main" windows, typically when referring to the currently visible one. You can create a main window by right clicking on the Windows section in the project browser and then selecting "Main Window". A "docked window" has the Dock Position set to anything but Floating. This will make the window stick to one side of the screen, and nothing can overlap it. It will also typically have its border and titlebar display policies set to Never. This makes the "docked" window appear to be joined seamlessly with the current "screen" window. These windows are usually tall and skinny or short and wide, depending on the side they're docked to. The purpose of a docked window is to make some information always available; typically navigation controls and overall status information. Using docked windows can help eliminate repetitive design elements from being copied to each screen, making maintenance easier. You can create a docked window by right clicking on the Windows section in the project browser, selecting "Docked Window", and then specifying it's dock position and window size.
A "popup window" is a window with the Dock Position set to Floating and is not maximized. Its border and titlebar display policies are usually set to When Not Maximized or Always, so that they can be manipulated by the end-user. These windows are often opened by components in the current "screen" window, and are meant to be on top of the screen. To this end, they may have their Layer property set to a number higher than zero so they don't get lost behind the "screen" window. You can create a popup window by right clicking on the Windows section in the project browser, then selecting "Popup Window". Popup windows are often parameterized so they can be re-used.
458
This style of project is so common, that the default operation of the Tab Strip component expects it. When it is in its default automatic operation, it expects that each tab represents a main window, and will automatically swap from the current screen to the desired screen. Furthermore, the [System]/Client/ User/CurrentWindow tag is calculated based upon this strategy: its value is the name of the current maximized window. If you have more than one main window open a time this navigation strategy will fail since the system expects a single main window. * Note: If your Tab Strip or swapTo function is not work ing as you expect, check to see if you have more than ONE main window opened. The Tab Strip component works off of the current window variable. When a project first loads, the variable will hold the main window set to open on startup. The Tab Strip utilizes the system.nav.swapTo function which swaps from the current window (stored in that variable) to a new window and updates the current window variable. At any time you can perform a system.nav.getCurrentWindow() or check the [System]/ Client/User/CurrentWindow tag to see what Ignition thinks the main window is. If you have two main windows opened Ignition will be confused as to which one you want to perform the swap. If you want to use your own buttons or other component to perform the navigation just make sure to use the system.nav.swapTo instead of the system.nav.swapWindow. The system.nav.swapWindow function takes a window to swap from and a window to swap to. The function does not utilize the current window variable in Ignition. * Note: The system.nav.swapWindow is the default function when swapping is selected on the Event Handler Navigation tab. As swapping occurs in the client a history of windows is stored internally. You have the ability to go backwards or forwards through this history (array) using the system.nav.goBack and goForward functions. The system.nav.goHome function simply takes you to the first main window that was opened in the client, which typically is the main window set to open on startup. To open popup windows you just simply need to open the window using the system.nav.openWindow or openWindowInstance.
459
2. Right click on the new window in the Project Browser and select Rename or press F2. Rename the window to Navigation. 3. We need this window to open on startup so right click on the window in the Project Browser and check the Open On Startup box if it is not checked. 4. You can add your company logo and navigation buttons to this window, but this example will use the tab strip. Drag in the Tab Strip component from the Buttons tab of the Component Palette. 5. Now we need to configure the tabs. Right click on the Tab Strip component and select Customizers > Tab Strip Customizer. There you can alter, add, or delete tabs. In order to make swapping work select the window to swap to from the dropdown menu. The Display Name can be whatever you want.
6. Now we just need some main windows. Create a main window by right clicking the Windows section
460
in the Project Browser and selecting Main Window 7. Go ahead and make more main windows. Make sure the main window you want to open on startup has the flag checked like we did with the Navigation window above. 8. With your new main windows created, go back to the tab customizer and set up the other tabs to point to these new windows like we did in step 8.
6.8
461
single valve control screen. There are two concepts that are required to achieve this in Ignition: indirect data binding and parameter passing.
462
You can add as many references you want. Each reference you add (e.g. {5}) will add a row into the references table. This reference will then be replaced by whatever property value that you map it to. Essentially all you are doing is building a tag path using references as placeholders that are replaced with dynamic values at runtime. To take advantage of this feature though requires some forethought as to how you are going to structure your tags. A good naming convention can make the design process a lot easier. Indirect Expression Binding The second kind of indirection is through the expression binding. This is an extremely versatile binding type. In particular, there is the tag() expression, which will return the value of a tag path. The tag path itself can be constructed using other expressions, which can easily be indirect. For example, if we wanted to bind to the valves' "OpenPct" tag and also multiply by 100, we could use an expression like:
tag( "Facility/Valves/Valve" + {Root Container.ValveNumber} + "/OpenPct" ) * 100.0
SQL Query Indirection Lastly it is worth mentioning that the SQL query binding is also a capable of indirection. The query itself can be altered by embedding the value of other properties. For example, suppose we logged all of our valve's flow rates to a table. We could use a query binding like this to calculate the average flow over the last 15 minutes for our current valve:
463
SELECT AVG(Valve{Root Container.ValveNumber}Flow) FROM ValveFlowHistory WHERE t_stamp > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 15 MINUTE)
Window Parameters
Putting indirect designs like those described above into popup windows is a great way to maximize the benefit of indirection. By passing the ValveNumber into a popup window, we can re-use the same window across our entire project simply by altering the valve number that we pass to the popup window. Passing parameters to windows is simple. Any dynamic property on the root container of a window can be used as a window parameter. On a button or other control that opens the window, simply call one of the navigation functions via scripting in the following manner:
value_to_pass1 = event.source.parent.ValveNumber value_to_pass2 = event.source.parent.TankNumber
In the above example TheValveNumber and TheTankNumber are the name of properties residing on the root container of the window that is to be opened. You can only pass parameters to properties that reside on the root container of the window that you want to open. That's it! When the window is opened, its TheValveNumber property will be set to the appropriate value and the bindings will target the correct valve.
6.9
464
Check your SQL Server "auto grow" and "auto shrink" settings
Some database systems, such as Microsoft SQL Server, allow the database to dynamically grow and shrink as data is inserted and deleted. By default, the "auto grow" setting for Microsoft SQL Server is set to grow by 1MB at a time. When data is inserted at a fast rate, the database constantly has to increase the size, leading to disk fragmentation. A general rule of thumb to you can use for testing is to set your "auto grow" setting to about one-eight of the size the table will get. Also, turn off any "auto shrink" settings to prevent that database from constantly growing and shrinking, again leading to disk fragmentation.
465
how the database system will execute a given query, and statistics after the query is executed. This tool can help better optimize slower performing queries.
6.10
Background
We're going to learn about TCP/IP and networking with Ignition by example. Our setup uses the address range 192.168.0.1-254. This is an example of a non-routable Class C IP network. Class C means that we have 255 addresses to deal with and a 24 bit subnet mask (255.255.255.0). Non-routable means that we're using addresses have been reserved for private (non-Internet) use. This means that Internet routers will ignore requests that use these addresses. Make sure that you use non-routable addresses when setting up private control networks! We have a router set up that has a single legal IP address and provides Internet access to our network with Network Address Translation (NAT). This article is relevant to any setup where you use NAT, port forwarding, or a DMZ (Demilitarized zone, a subnetwork that sits between the internal and external network). Example Settings The Ignition gateway uses the static (non-DHCP) address 192.168.0.2 and currently runs over port 8088 The router uses the LAN address 192.168.0.1 The router uses the WAN (Internet) address 69.19.188.26 Clients' addresses are assigned via DHCP in the range 192.168.0.100-150. They need to access the Ignition project We want to be able to access our application over the Internet
Setup
Our first step to allow access to the Ignition gateway is by setting up a port forward rule in the router. It should specify that TCP traffic directed to 69.19.188.26 over port 8088 be forwarded to 192.168.0.2. You may also need to add an incoming firewall rule to support this with the same settings. To test, open http://69.19.188.26:8088 in a web browser. If you see the default Ignition Gateway web site it worked. If not then you can try loosening up your firewall policy and using 192.168.0.2 as the DMZ host. Keep in mind that a home router DMZ host is not a true DMZ in terms of network segmenting - it is a feature that will pass all traffic to our Gateway, with the exception of certain attacks. This is much
2012 Inductive Automation
466
more wide open than a single port forward - more geared toward Internet games that require numerous ports to be open. Incrementally tighten back security as you determine what works. Next make sure that your firewall doesn't block outbound TCP traffic from your local network over port 8088. In most cases it shouldn't, but our network is very secure so we'll set up an outbound firewall rule to allow TCP traffic from 192.168.0.x to 69.19.188.26 over port 8088. Without this rule, Internet users won't have a problem, but your local clients won't be able to access the system. Your clients should address 69.19.188.26 instead of 192.168.0.2 when using the Ignition runtime. Then restrict gateway configuration access to either 127.0.0.1 (localhost) or 192.168.0.*. You should now be able to access your Ignition gateway via the internet and launch clients on remote systems.
Deployment
Part VII
Deployment
468
7
7.1
Deployment
Licensing and Activation
One thing to consider when deploying an Ignition installation to production use is the manner in which it will be licensed. If you anticipate that the installation might move from server to server frequently you may want to consider purchasing a USB license key to ease transition to new servers. This also makes things more convenient when the server is being deployed in an area without an active internet connection. Otherwise a file-based licensing scheme can be used. If you have an internet connection you can activate the installation online. Otherwise you can download an activation request file and put it on a portable memory device and take it to a workstation with an active internet connection. From there you can upload the file to the Inductive Automation website and you will receive a license file, called license.ipl, in return. Take this file back to the gateway you are trying to activate and under System > Licensing you can upload and activate the license.
7.2
Making Backups
Backups can be made by going to System > Backup/Restore on the Ignition Gateway. Click the "Download Backup" button and save the file somewhere safe -- ideally somewhere that DOES NOT reside on the same machine running the gateway. Backups save the user data inside the Ignition Gateway server. This includes all projects, drivers, images, and configuration, but not the modules.
7.3
7.4
Transferring Servers
There are only two things to consider when transferring your installation to a new server.
Deployment
469
You need either a copy of the most recent backup (You are making backups, right? See the Making Backups section for more information) or to go ahead and make a backup at this point in time. This backup file is how you will transfer your existing settings to the new server.
7.5
7.6
SSL
You can turn on SSL mode in the Gateway Configuration section under Configuration > Gateway Settings > Use SSL. This will make all communication for Clients, Designers, and web browsers using the web interface use encrypted SSL connections.
Password Protection
By default, the Configuration section is password protected, and this cannot be removed. You can also optionally protect the Status and the Home sections of the Gateway. You can also alter the roles that are required to access any of these sections. These settings are altered under Configuration > Gateway Settings.
7.7
Gateway Monitoring
The Ignition Gateway can be monitored in detail under the Status section or from the Gateway Control Utility.
Deployment
470
Overview
The overview provides a top-down view of many of the components of your Gateway. This view is also useful for determining what step might be next when setting up your Ignition Gateway for the first time. You can view the status of your database connections, device connections, OPC connections, the number of open clients and the number of open designers.
Modules
A list of installed modules, their status, as well information about their version and current license state.
SQLTags
The SQLTags section lists information and statistics about all configured SQLTags Providers as well as a view into the SQLTags subscription model, scan classes, and what tags it is currently subscribed to.
Database Connections
This important section shows your database connections, their status, and their current load. Each status panel has information about the connection such as queries/second, total queries, and the average query duration.
OPC Connections
All of your OPC connections and any subscriptions you have made through these connections will be shown in this section. You can view the status of any connection as well as find details for trouble shooting when the status is bad. Statistics on the number of reads, writes, and updates are also kept.
Sessions
This section shows details about all of the Designer and Client sessions that are communicating with this Gateway. You can see detail about their subscriptions, user credentials, etc.
Deployment
471
7.8
3. Create your keystore SSL certificates for Ignition are stored in a file called a k eystore. You'll need to create your own keystore file with a certificate in it before you can purchase the SSL certificate. a. Enter the following command: keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 -keystore C: \ssl.key (you can put the file wherever you want for now but it should be called "ssl.key") b. It will prompt you to enter a password. Use the password: ignition c. You will then be prompted for your "first and last name". Do not actually use your first and last name. This value must be one of these for your Ignition Gateway: 1. Fully Qualified Domain Name (e.g. "secure.yourdomain.com") 2. Public IP address (e.g. "202.144.8.10") 3. Full Server Name of your internal server (e.g. "scadaserver") 4. Private IP address (e.g. "192.168.0.1") d. It will then prompt you for information about your company. Input all data accurately, as the certificate authority will need to verify this information. e. Lastly, it will ask you for the password for alias <tomcat>. Press RETURN to use the same password as the keystore file 4. Generate a Certificate Signing Request At this point, you have a keystore file named "ssl.key" at the root of your C:\ drive (or wherever you specified it to be in step 3a ) In your command prompt window, enter this command:
Deployment
472
keytool -certreq -alias tomcat -file C:\csr.txt -keystore C:\ssl.key It will prompt you for the keystore password (ignition). You now have a certificate request file at C:\csr.txt 5. Buy the SSL certificate Now you need to get your SSL certificate signed by a certificate authority. When you go to a certificate authority (Verisign, GoDaddy, Comodo, etc), they'll ask for your CSR, which is the csr. txt file that you created in step 4. Typically they'll ask you to paste your CSR into their web form. Open csr.txt in notepad, and copy-and-paste it into the certificate authority's form. If prompted what software generated the CSR, choose Tomcat or Java After the certificate authority has processed your payment and reviewed your CSR, they will send you your certificate via email. 6. Install the SSL certificate After your SSL certificate has been emailed to you, you will want to follow the instructions provided for installing the certificate into a Java keystore. Your certificate authority will provide these instructions. The following is the procedure for installing a Comodo SSL certificate, provided as an example: a. Extract the certificate files that were emailed to you, in this example they were extracted to C:\cert b. Install the root certificate with the following command: keytool -import -trustcacerts -alias root -file C: \cert\AddTrustExternalCARoot.crt -keystore C:\ssl.key c. Install the COMODO intermediate certificate: keytool -import -trustcacerts -alias INTER -file C:\cert\COMODOHighAssuranceSecureServerCA.crt -keystore C:\ssl.key d. Install your server's certificate: keytool -import -trustcacerts -alias tomcat -file C:\cert\192_168_1_7. crt -keystore C:\ssl.key 7. Replace Ignition's default keystore You now have a keystore file at C:\ssl.key that holds your SSL certificate. The certificate alias is "tomcat" and the password is "ignition". You can now replace the keystore file that ships with Ignition with your file. Make a backup of the file at C:\Program Files\Inductive Automation\Ignition\tomcat\ssl.key and replace it with your keystore file. You will need to restart the Ignition service after replacing this file. Make sure your SSL port is allowed through your server's firewall. The default SSL port is 8043, and can be changed to the standard SSL port (443) through the Gateway Control Utilitiy (GCU). If you have a redundant installation, you'll need to repeat this procedure on your backup server and buy a second certificate for it.
Appendix A. Components
Part VIII
Appendix A. Components
474
8
8.1
8.1.1
Appendix A. Components
Input
Text Field
A basic Text Field component Description The Text Field component is used for input of any single-line text. This component will accept any alpha-numeric input. If you're looking for a numeric field, see the Numeric Text Field. This field features a protected mode. When you enable the protectedMode property, the field is not editable even when it recieves input focus. The user must double click on the field or press enter in order to edit the field. When they are done (press enter again or leave the field), the field becomes non-editable again. The Text Field also supports the reject updates during edit feature. This feature ignores updates coming from property bindings while the component is being edited by a user. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background
Non-Editable Background
Styles
Appendix A. Components
475
Data type
boolean
Defer Updates
When true, the 'text' property will not fire updates while typing, it will wait for Enter to be pressed.
Scripting name Data type deferUpdates boolean
Protected Mode?
If true, users will need to double-click in the field in order to edit the text.
Scripting name Data type protectedMode boolean
If true, any pending edit will take effect when focus is lost. If false, the user must press ENTER for an edit to take effect.
Scripting name Data type commitOnFocusLost boolean
Reject Updates During Edit If true, this field will not accept updates from external sources (like DB bindings) while the user is editing the field.
Scripting name Data type Flags rejectUpdatesDuringEdit boolean expert
Maximum Characters
The text box will be limited to this number of characters. Use -1 for unlimited.
Scripting name Data type maxChars int
Touchscreen Mode
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
Appendix A. Components
476
this component.
Scripting name Data type toolTipText String
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Flags Values horizontalAlignment int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key Scripting Functions
Appendix A. Components
477
8.1.2
Description The Numeric Text Field is similar to the standard Text Field, except that it is specialized for use with numbers. Instead of a "text" property, it has four numeric "value" properties. Which one you use depends on the mode of the text box. Like the standard Text Field, this text field can operate in protected mode. When you enable the protected property, the field is not editable even when it recieves input focus. The user must double click on the field or press enter in order to edit the field. When they are done (press enter again or leave the field), the field becomes non-editable again. The Numeric Text Field also supports the reject updates during edit feature. This feature ignores updates coming from property bindings while the component is being edited by a user. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background
Non-Editable Background
Decimal Format
Suffix
Appendix A. Components
478
Styles
Behavior Use Bounds? Only allows user-entered values between a minimum and maximum. Unless you turn on "Error on out-of-bounds", user-entered values will be silently modified to be in-bounds.
Scripting name Data type useBounds boolean
Error on Out-of-Bounds
Editable?
Protected Mode?
If true, users will need to double-click in the field in order to edit the value.
Scripting name Data type protectedMode boolean
If true, any pending edit will take effect when focus is lost. If false, the user must press ENTER for an edit to take effect.
Scripting name Data type commitOnFocusLost boolean
Reject Updates During Edit If true, this field will not accept updates from external sources (like DB bindings) while the user is editing the field.
Scripting name Data type Flags rejectUpdatesDuringEdit boolean expert
Touchscreen Mode
Appendix A. Components
479
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Number Type What type of numbers should this field accept?
Scripting name Data type Values mode int 0 Integer 3 Double 1 Long 2 Float
Maximum
Minimum
Value (Integer)
The value as an integer. Make sure you use the value property that corresponds to your Number Type setting.
Appendix A. Components
480
Value (Double)
The value as a double. Make sure you use the value property that corresponds to your Number Type setting.
Scripting name Data type Flags doubleValue double bindable
Value (Long)
The value as a long. Make sure you use the value property that corresponds to your Number Type setting.
Scripting name Data type Flags longValue long bindable
Value (Float)
The value as a float. Make sure you use the value property that corresponds to your Number Type setting.
Scripting name Data type Flags floatValue float bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Flags Values horizontalAlignment int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key Scripting Functions
Appendix A. Components
481
8.1.3
Spinner
Description The spinner component represents a value that is part of a series of values, such as numbers and dates. It allows you to not only edit the value directly, but to 'spin' the value up or down, using the up and down buttons that are part of the component. When setting up property bindings, make sure you use the value property that corresponds to the spinner mode. For example, if you chose the Double spinner mode, you should bind the doubleValue property. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Number Format
Date Format
Styles
Behavior Spinner Mode The mode controls which data type this spinner accepts
Scripting name Data type Values spinnerMode int 0 Integer 1 Double 2 Date
Appendix A. Components
482
2 3 5 10 12 13 14
Touchscreen Mode
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Data Numeric Minimum The minimum value this spinner will accept when in 'Integer' or 'Double' mode.
Scripting name Data type minValue double
Numeric Maximum
The maximum value this spinner will accept when in 'Integer' or 'Double' mode.
Scripting name maxValue
Appendix A. Components
483
Data type
double
Value (Integer)
Value (Double)
Value (Date)
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. propertyChange Scripting Functions This component has no special scripting functions.
8.1.4
Description This specialized text field is used for alphanumeric text input that must match some specific pattern or needs to be formatted in a specific way. It operates in two modes: Formatted Mask In this mode, input is automatically formatted and restricted based on a format mask . For example, a format mask like: (###) ###-#### will allow the entry of a 10-digit US phone number. The formatting characters are automatically inserted if the user does not type them in. Any other characters are restricted. The following characters may be used in a formatted mask pattern: # Any valid number, Such as 0-9.
Appendix A. Components
484
' Escape character, used to escape any of the special formatting characters. U Any letter. All lowercase letters will be mapped to upper case automatically. L Any letter. All upper case letters will be mapped to lower case automatically. A Any letter or number. ? Any letter, case is preserved. * Anything. H Any hex character (0-9, a-f or A-F). Examples: ##UA product code with a specifc format, like 28E-8213/AR ####/UU 0xHHHH A hex digit, automatically prepends "0x" no the front. e.g. "0x82FF" #UUU### A California license plate, eg. 4ABC123 Regular Expression In this mode, input is validated against a regular expression. A regular expression is a special string that defines a set of allowed strings. See http://en.wikipedia.org/wiki/Regular_expression. Any input that matches the given regular expression is allowed, and input that doesn't match, is restricted. And yes, while powerful, regular expressions are decidedly difficult to decipher. Examples: \p{Upper}\p{Lower}*, \p{Upper} A name, formatted such as Smith, John \p{Lower}* \d{3}-\d{2}-\d{4} A US social security number, like 123-45-6789 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d A network IPv4 address, like 67.82.120.116 {1,3} ^[a-f0-9A-F]{6}$ A six-digit hexadecimal number. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Styles
Appendix A. Components
485
Data type
String
Reg Ex Pattern
Overwrites Text
Touchscreen Mode
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Appendix A. Components
486
Opaque
Cursor
Committed Value
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Flags Values horizontalAlignment int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange
Appendix A. Components
487
8.1.5
Password Field
Description A password field is like a text field that doesn't display the text that is being edited. You may alter the echo character ( * ) if you'd like. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Echo Character
Styles
Behavior Touchscreen Mode Controls when this input component responds if touchscreen mode is enabled.
Scripting name Data type Flags Values touchscreenMode int expert 0 None 1 Single-Click 2 Double-Click
Appendix A. Components
488
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion
2012 Inductive Automation
Appendix A. Components
489
focus propertyChange key Scripting Functions This component has no special scripting functions.
8.1.6
Text Area
Description Suitable for multi-line text display and editing. Will scroll vertically on demand. Will scroll horizontally if line wrap is off. Only supports plain-text, no HTML formatting or styled text. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Rows
The number of rows you expect to display (used as a hint for scrollbars).
Scripting name Data type rows int
Columns
The number of columns you expect to display (used as a hint for scrollbars).
Scripting name Data type columns int
Styles
Behavior Editable Controls whether or not the user can edit the text within this text area.
Appendix A. Components
490
editable boolean
Defer Updates
If true, bindings will not affect the component's text while a user is editing the text.
Scripting name Data type deferUpdates boolean
Line Wrap
Touchscreen Mode
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Appendix A. Components
491
5 6 7 8 9 10 11
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key Scripting Functions This component has no special scripting functions.
8.1.7
Dropdown List
Description The dropdown component is a great way to display a list of choices in a limited amount of space. The current selection is shown, and the choices are only presented when the user clicks on the dropdown button. The choices that are shown depend on the data property. This is a dataset, which can be typed in manually in the Designer, or (more commonly) it can be populated dynamically from a property binding, often a SQL Query binding. It is often the case that you want to display choices to the user that are 'dressed up' versions of the actual choices. For instance, suppose that you are selecting choices for a downtime tracking entry. The choices might be: "Operator Error", "Machine Malfunction", and "Other". But, you really want to map these choices to some numeric code which is how the choice is stored. So, for instance, when
Appendix A. Components
492
the user chooses "Other" you really want to get the number 3. The dropdown component is perfect for such a use. The data property can be set up in one of three fashions, which control how the "selected values" properties change. The 3 ways to set up the data dataset and the corresponding behavior is as follows: One Column Apples Dropdown displays values from the first column [String] Selected Value is undefined Oranges Selected String Value represents value from Bananas first column Selected Label represents value from first column Two Columns [Integer, String] 201 202 203 Apples Oranges Bananas Dropdown displays values from second column Selected Value represents value from first column Selected String Value is undefined Selected Label represents value from second column Dropdown displays values from second column Selected Value is undefined Selected String Value represents value from first column Selected Label represents value from second column
The dropdown component can operate in one of three Selection Modes. These modes affect how the dropdown's current selection (defined by the values of its Selected Value, Selected String Value, and Selected Label properties) behave when the selection properties are set to values not present in the choice list, or conversely, when the choice list is set to a new dataset that doesn't contain the current selection: Strict. Selected values must always correlate to an option in the list defined by the Data property. If an invalid selection is set (via a binding or a script), the selection will be set to the values defined by the No Selection properties. If the Data property is set to a list that does not contain the current selection, the current selection will be reset to the No Selection values. Lenient. (default) Selected values are independent of the list defined by the Data property. This mode is useful to avoid race conditions that can cause problems in Strict mode when both the Data and the Selected Value properties are bound. If the current selection is not present in the Data list, the read-only property Selected Index will be -1. Editable. The same selection rules as defined by Lenient mode, except that the dropdown itself becomes editable, allowing a user to type in their own arbitrary value. This value will be set as the dropdown's Selected Label. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Appendix A. Components
493
Data type
Color
Background Color
Selection Background
The number of rows to display in the dropdown list before displaying a scrollbar.
Scripting name Data type Flags maximumRowCount int expert
A comma separated list of columns to hide from the dropdown table, eg. 0,2 (only used in table mode)
Scripting name Data type Flags hideTableColumns String expert
Selects whether or not the dropdown table header is displayed. (only used in table mode)
Scripting name Data type Flags showTableHeader boolean expert
The maximum width allowed for the dropdown table. (only used in table mode)
Scripting name Data type Flags maxTableWidth int expert
The maximum height allowed for the dropdown table. (only used in table mode)
Scripting name Data type Flags maxTableHeight int expert
Styles
Behavior Selection Mode The selection mode determines the behavior of the dropdown: whether its selected value must strictly be in the underlying set of choices, whether it is flexible, or even user-editable.
Scripting name Data type selectionMode int
Appendix A. Components
494
Values
0 1 2
No Selection Value
No Selection String
No Selection Label
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
495
Data Data The data which fills up the combo box. Either a 1 or 2 column DataSet, with the first column being the value, and the second being the display
Scripting name Data type Flags data Dataset bindable
Selected Value
Selected Label
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the contents along the X axis
Scripting name Data type Flags Values horizontalAlignment int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Vertical Alignment
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more.
Appendix A. Components
496
mouse mouseMotion focus propertyChange key Scripting Functions This component has no special scripting functions.
8.1.8
Slider
A basic Slider
Description The slider component lets the user drag an indicator along a scale to choose a value in a range. The Defer Updates property determines whether or not the slider's Value changes as the user drags the mouse, or whether it waits until the user drops the slider handle. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Horizontal Slider
Appendix A. Components
497
Data type
int
Paint Track?
Paint Labels?
Paint Ticks?
Styles
Behavior Defer Updates Only publish updates to value when not actively being changed.
Scripting name Data type deferred boolean
Snap To Ticks?
Scripting name Data type snapToTicks boolean
Inverted?
Specify true to reverse the value range shown for the slider and false to put the value range in the normal order.
Scripting name Data type inverted boolean
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
Appendix A. Components
498
this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Minimum Value
The value when the slider is all the way left or down
Scripting name Data type Flags minimum int bindable
Maximum Value
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key
2012 Inductive Automation
Appendix A. Components
499
8.2
8.2.1
Buttons
Button
Description The Button component is a versatile component, often used for things like opening/closing windows, writing to tags, and triggering any sort of scripting logic. It can be used for showing status, as well. For example, if you have three buttons, Hand, Off, and Auto, not only can they set those modes, but their background color can display the current mode, although you'd be better off using the MultiState Button for this. To get buttons to do things, you add an event handler to the actionPerformed event. Many new users to the 1.0.0 module will configure an event handler for the mouseClicked event instead. While this will work, it is better to use the actionPerformed event. Why? Buttons can also be activated by tabbing over to them and hitting the space key, or they could be activated by pressing Alt and the button's mnemonic character. So, to make sure that your button works in all of these cases, configure your event handler on the actionPerformed event, not the mouseClicked event. See also: Typical Navigation Strategy Event Types Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Background 3D?
Fill Area?
Appendix A. Components
500
Border Painted?
Text
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Styles
Behavior Rollover If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Mnemonic
Default Button
If true, this button will be activated when the user presses enter on the window.
Scripting name Data type Flags defaultBtn boolean expert
Appendix A. Components
501
Enabled
Visible
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type Flags border Border expert
Opaque
Is this button completely opaque? Most aren't, so this should usually be false.
Scripting name Data type Flags opaque boolean expert
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Margin The space between a button's text and its borders.
Scripting name Data type Flags margin Insets expert
Appendix A. Components
502
Horizontal Alignment
Vertical Alignment
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion action focus propertyChange key Scripting Functions
doClick()
Virtually "clicks" the button, meaning that its actionPerformed event handler will run.
Parameters Returns none nothing
Appendix A. Components
503
8.2.2
2 State Toggle
Description This button is similar to the basic Toggle Button, but more finely tuned to work in realistic controls environments. Use this button any time you want to toggle a value between two states, such as On/ Off, Stop/Run, etc. If you have more than two states (for example, Hand/Off/Auto, use the Multi-State Button). If you have a tag whose value you want to toggle between 2 values (like zero and one), you can simply drag and drop the tag onto the button. This will bind both the Control Value and Indicator Value properties to that tag. Now set the State 1 Value and State 2 Value to your two states (they default to zero and one, respectively). Lastly, use the Styles Customizer to define the styles for your two states. This button has four integer values that you use to set it up: the Control Value, the Indicator Value, and values that define the 2 different states: State 1 Value and State 2 Value. Every time you press the button, one of the state values is written to the control value. The Indicator Value is used to determine which state you're in. For example, suppose that State 1 Value was zero and State 2 Value is one. If Indicator Value is zero and you press the button, it'll write a one to the Control Value. The Style of the component is typically driven by the read-only property Current State. Current State equals zero when Indicator Value=State 1 Value and one otherwise. See also: Bidirectional Bindings Component Styles Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Background 3D?
Fill Area?
Appendix A. Components
504
boolean expert
Border Painted?
Text
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Styles
Behavior Rollover If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Confirm?
Confirm Text
Mnemonic
Common
2012 Inductive Automation
Appendix A. Components
505
Name
Enabled
Visible
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type Flags border Border expert
Opaque
Is this button completely opaque? Most aren't, so this should usually be false.
Scripting name Data type Flags opaque boolean expert
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Control Value
Bind this to the tag that controls the state. (Typically, this is bound to the same location as Indicator Value)
Scripting name controlValue
Appendix A. Components
506
int bindable
Indicator Value
Bind this to the tag that indicates the current state. (Typically, this is bound to the same location as Control Value)
Scripting name Data type Flags indicatorValue int bindable
State 1 Value
The value that will be written to controlValue when the button is pushed in state 2.
Scripting name Data type Flags state1Value int bindable
State 2 Value
The value that will be written to controlValue when the button is pushed in state 1.
Scripting name Data type Flags state2Value int bindable
Current State
Read-only property that shows what state (0 or 1) this button is currently in.
Scripting name Data type Flags state int bindable | expert
Layout Margin The space between a button's text and its borders.
Scripting name Data type Flags margin Insets expert
Horizontal Alignment
Vertical Alignment
Appendix A. Components
507
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion action focus propertyChange key Scripting Functions This component has no special scripting functions.
8.2.3
Multi-State Button
Description This button is really a series of two or more buttons, arranged in a column, row, or grid. Each button represents an integer-valued state. Each state defines two styles for a button: the selected style, and the unselected style. Each button is automatically displayed with the correct style based on the current state (the value of Indicator Value). When a button is pressed, it's state's value is written to the Control Value. To configure a Multi-State Button, simply drag a tag that represents your state onto the Multi-State Button. This will bind both the Control Value and Indicator Value to that tag. Now open up the MultiState Button customizer, and define your states: their order, values and styles. Lastly choose if you want the buttons to be a column, row, or grid by setting the Display Style property. See also: Bidirectional Bindings Component Customizers Properties Appearance
Appendix A. Components
508
Font
Display Style
Horizontal Gap
Vertical Gap
Grid Rows
Grid Cols
Background 3D?
Confirm Text
States
Rollover
If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusableEnabled boolean expert
Appendix A. Components
509
Enabled
Visible
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Control Value Bind this to the tag that controls the state. (Typically, this is bound to the same location as Indicator Value)
Scripting name Data type Flags controlValue int bindable
Indicator Value
Bind this to the tag that indicates the current state. (Typically, this is bound to the same location as Control Value)
Scripting name Data type Flags indicatorValue int bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events
2012 Inductive Automation
Appendix A. Components
510
The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange key Scripting Functions This component has no special scripting functions.
8.2.4
One-Shot Button
Description The latched button is great for telling a PLC to do something. It simply writes a value, and then waits for it to be reset by the PLC before it is available again. Note that this is only applicable when the PLC is programmed to reset the value after reading it. If your PLC expects the HMI to reset the bit, use the Momentary Button. Also note that this component is considered safer than the momentary button, because it receives positive feedback from the PLC that the signal was received, avoiding the timing dangers associated with a Momentary Button. To use the latched button, bind an OPC tag bidirectionally to the latched button's Value property. When clicked, the button will write the value in its Set Value property to the Value property. Typically, Set Value is 1, and Value is 0 in a ready state, although the logic could be reversed or change simply by altering Set Value. The button can disable itself when it is writing, and will display different text. Note that the button considers itself to be writing whenever Value equals Set Value you must make sure that the PLC resets this value, otherwise the button will remain in a writing state. See also: Bidirectional Bindings Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Background 3D?
Appendix A. Components
511
Fill Area?
Border Painted?
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Styles
Behavior Rollover If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Idle Text
The text of the button while its value is not being written
Scripting name Data type Flags normalText String bindable
Writing Text
Appendix A. Components
512
Data type
boolean
Confirm?
Confirm Text
Mnemonic
Enabled
Visible
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type Flags border Border expert
Appendix A. Components
513
Opaque
Is this button completely opaque? Most aren't, so this should usually be false.
Scripting name Data type Flags opaque boolean expert
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Value
Set Value
The value to set the control value to when the button is pushed.
Scripting name Data type Flags setValue int bindable
Layout Margin The space between a button's text and its borders.
Scripting name Data type Flags margin Insets expert
Horizontal Alignment
Vertical Alignment
Appendix A. Components
514
Flags Values
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion action focus propertyChange key Scripting Functions This component has no special scripting functions.
8.2.5
Momentary Button
Description Momentary buttons are used to set a value for either a fixed amount of time, or however long the button remains held down, whichever is longer. Once the button is released, or the minimum time expires, the value is reset. The momentary button uses it's Control Value property to affect the underlying data. Typically, this property uses a bidirectional tag binding to an OPC tag. When pressed, it will write its On Value to Control Value. When released, it will either write Off Value to Control Value immediately, or wait until On Time has elapsed (since the pressed event). The button's Indicator Value, which is typically bound to the same OPC tag as Control Value, is used to draw an "active" indication border around the button. This gives the operator positive feedback that the value has written successfully. It also lets an operator at one terminal know if an operator at a different terminal is using the button currently. Note that you may want to use the Latched Button instead of the Momentary Button if you simply need to send a signal to a PLC, and the PLC is able to reset the value. This lets the PLC reset the value, avoiding the potential for the bit to be left high. This is possible with the Momentary Button if, for example, the power to the client was cut while the button was held down. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Appendix A. Components
515
Foreground Color
Background Color
Scripting name Data type buttonBG Color
Background 3D?
Fill Area?
Rollover?
If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Text
Indicator Width
The width of the indication border that shows whether or not the indicator value is currently set.
Scripting name Data type indicatorWidth int
On Color
The color of the indicator border when the indicator value is on.
Scripting name Data type onColor Color
Off Color
The color of the indicator border when the indicator value is off
Scripting name Data type offColor Color
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Styles
Appendix A. Components
516
Behavior Mnemonic A single letter that will activate the button using 'ALT-mnemonic'.
Scripting name Data type mnemonicChar String
On Value
Off Value
On Time
The minimum amount of time to keep the control value at the "On Value"
Scripting name Data type onTime int
Enabled
Visible
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Border
Cursor
Appendix A. Components
517
9 10 11
Data Control Value Bind this to the tag that you want to control. (Typically, this is bound to the same location as Indicator Value)
Scripting name Data type Flags controlValue int bindable
Indicator Value
Bind this to the tag that indicates the current state of the control value. (Typically, this is bound to the same location as Control Value)
Scripting name Data type Flags indicatorValue int bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment The horizontal alignment of the button's contents (text and/or image)
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Vertical Alignment
Scripting
Appendix A. Components
518
Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion action focus propertyChange key Scripting Functions This component has no special scripting functions.
8.2.6
Toggle Button
Description The toggle button represents a bit: on (selected) or off (not selected). Visually the button looks down or depressed when it is selected, and up when it is not selected. Logically, this component is very similar to the Check Box component. Note that for implementing a controls screen, the 2 State Toggle is usually more appropriate than this component. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Background 3D?
Opaque
Appendix A. Components
519
Fill Area?
Border Painted?
Rollover?
If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Label
Image Path
The relative path of the image to be displayed when this component is selected (toggled on).
Scripting name Data type selectedPath String
Styles
Behavior Focusable If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Enabled
Visible
Border
2012 Inductive Automation
Appendix A. Components
520
unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Margin The space between a button's text and its borders.
Scripting name Data type Flags margin Insets expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion item action focus propertyChange key
Appendix A. Components
521
8.2.7
Check Box
Description A CheckBox is a familiar component that represents a bit - it is either on (selected) or off (not selected). It is functionally equivalent to the Toggle Button component. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Text
Margin
The internal margin that provides padding for the contents of this button.
Scripting name Data type Flags margin Insets expert
Styles
Behavior Rollover If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Appendix A. Components
522
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout
2012 Inductive Automation
Appendix A. Components
523
Horizontal Alignment
Vertical Alignment
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion item action focus propertyChange key Scripting Functions This component has no special scripting functions.
8.2.8
Radio Button
Description The radio button is similar to the CheckBox component, except for one special property. All radio buttons in the same Container (including the Root Container) will automatically be mutually exclusive. This means that only one radio button can be selected at a time. Radio buttons are a good way to let the user choose just one of a number of options. Dropdown Lists are another good way to do this. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Appendix A. Components
524
Data type
Color
Background Color
Text
Margin
The internal margin that provides padding for the contents of this button.
Scripting name Data type Flags margin Insets expert
Styles
Behavior Rollover If true, the button may indicate that the mouse is hovering over it.
Scripting name Data type Flags rolloverEnabled boolean expert
Focusable
If a button is not focusable, you will not be able to interact with it with the keyboard. This means you can't "tab" over to it.
Scripting name Data type Flags focusable boolean expert
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Appendix A. Components
525
opaque boolean
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment The horizontal alignment of the button's contents (text and/or image)
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Vertical Alignment
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion item action focus
2012 Inductive Automation
Appendix A. Components
526
propertyChange key Scripting Functions This component has no special scripting functions.
8.2.9
Tab Strip
Description In general, a tab strip is just a single-selection multiple choice component. In practice it is used anywhere that a user needs to be able to select between multiple windows or screens. It is most commonly used in a docked window to provide automatic window navigation. To support this typical use-case, the tab strip has two navigation modes: 1. Swap to Window. (default) The tab strip will automatically call system.nav.swapTo() with the name of the selected tab. This facilitates very easy navigation for most common projects. 2. Disabled. The tab strip doesn't do anything when the tab selection changes. Users can implement their own via property bindings or by responding to the propertyChange scripting event. The tab strips visual style is highly customizable. There are different rendering styles, and things such as fonts, colors, line thicknesses, hover colors, and gradients are customizable within each rendering style. Use the Tab Strip's customizer to come up with a style that suits your project, as well as to manage the tabs that are present. The tabs and their styles are all stored in a dataset property (called Tab Data), so they can be modified at runtime as well. See also: Typical Navigation Strategy Properties Appearance Background Color The background color of the component.
Scripting name background
Appendix A. Components
527
Data type
Color
Orientation
Selected Tab
Name of the selected tab. This is also the name of the window that, if it exists, will be swapped to when this tab is pressed.
Scripting name Data type Flags selectedTab String bindable
Renderer
Size Mode
The sizing mode tabs use when deciding their size. Automatic means every tab is the same fixed size. Individual lets each tab decide its own size based on the size of its text.
Scripting name Data type Values sizeMode int 0 Automatic 1 Individual
Intertab Space
Text Padding
Rounding Radius
Separator Thickness
Thickness of the line drawn across the bottom and around each tab.
Scripting name Data type separatorThickness float
Separator Color
Color of the line drawn across the bottom and around each tab.
Scripting name Data type separatorColor Color
Antialias
Styles
Appendix A. Components
528
Flags
bindable | expert
Behavior Navigation Mode Navigation mode. Disabled does nothing when a tab is pressed. Swap to window swaps to the window whose name corresponds to the name of the selected tab, provided that window exists.
Scripting name Data type Values navigationMode int 0 Disabled 1 Sw ap to w indow
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Appendix A. Components
529
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3
8.3.1
Display
Label
Description The Label is one of the most versatile components. It can display text, images, or both. Its text can be HTML formatted (like most components). It can even be made to respond to user interaction through its events. Labels are one of the most common components that you will want to add dynamic properties to. For instance, you can put an integer dynamic property "state" on a label, and then bind the text to be "On" when the state=1 and "Off" otherwise, using an expression binding. Bind the background color to be red when the state is 0, and green when the state is 1 using a property binding. Now you have a re-usable binary state indicator. While you could have used the Multi-State Indicator to achieve the same effect, the exercise is good practice for creating custom components. You can see how the flexibility of bindings and dynamic properties make the Label extremely versatile. See also: Dynamic Properties Property Bindings Properties Appearance Font Font of text of this component
Appendix A. Components
530
font Font
Fill Background
If true, the label's background color will be drawn. If false, it will have a transparent background.
Scripting name Data type Flags fillBackground boolean bindable
Foreground Color
Background Color
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Rotation
Antialias
Styles
Enabled
Appendix A. Components
531
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Determines the horizontal position of the label's text, relative to its image
Scripting name Data type horizontalTextPosition int
Appendix A. Components
532
Values
2 0 4 10 11
Vertical Alignment
Determines the vertical position of the label's text, relative to its image
Scripting name Data type Values verticalTextPosition int 1 Top 0 Center 3 Bottom
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.2
Numeric Label
Description This component is a specialized label designed to display a number. It can include units, and has an integrated number format string. By default the number is displayed bold and the units are not. This can be customized, see the Prefix and Suffix expert properties. This label's text is constructed as follows: Prefix + numberFormat(Value, Pattern) + Suffix + Units It is important to note that you could customize the standard Label component using custom properties and bindings to mimic this component exactly. If this component doesn't do something that you need, you can make your own numeric label and use it everywhere in your project. Properties Appearance
Appendix A. Components
533
Font
Foreground Color
Background Color
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Rotation
Antialias
Styles
Enabled
Appendix A. Components
534
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Units
Prefix
Suffix
A string that will be placed after the number, and before the units.
Scripting name Data type Flags suffix String expert
Data Quality
The data quality code for any tag bindings on this component.
Appendix A. Components
535
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Determines the horizontal position of the label's text, relative to its image
Scripting name Data type Flags Values horizontalTextPosition int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Vertical Alignment
Determines the vertical position of the label's text, relative to its image
Scripting name Data type Flags Values verticalTextPosition int expert 1 Top 0 Center 3 Bottom
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
536
8.3.3
Multi-State Indicator
Description This component is a specialized label used to display a discrete state. The state must be represented by an integer, but the values and number of different states is customizable. Use the component's styles customizer to configure the different states. See also: Component Styles Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Image Path
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Icon-Text Spacing
The space (in pixels) between the icon (if any) and the text (if any)
Scripting name Data type iconTextGap int
Rotation
Antialias
Styles
Appendix A. Components
537
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Text
Appendix A. Components
538
String bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the label's contents along the X axis
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Determines the horizontal position of the label's text, relative to its image
Scripting name Data type Flags Values horizontalTextPosition int expert 2 Left 0 Center 4 Right 10 Leading 11 Trailing
Vertical Alignment
Determines the vertical position of the label's text, relative to its image
Scripting name Data type Flags Values verticalTextPosition int expert 1 Top 0 Center 3 Bottom
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
539
8.3.4
LED Display
Description The LED display is a stylized numeric or alphanumeric label. It has three different visual styles which all correspond to a kind of physical display: 7-segment, 14-segment, and 5x7 matrix. By default this component is in numeric mode, which means you should use its Value property. If you need to display characters as well, switch the mode to alphanumeric, and use the Text property. Properties Appearance Style The visual style of the display.
Scripting name Data type Values style int 7 7 Segment 14 14 Segment 34 5x7 Matrix
Background Color
LED Lit
LED Unlit
Styles
Appendix A. Components
540
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Value The numeric value of the display, used when Mode is Numeric
Scripting name Data type Flags value double bindable
Text
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Layout Horizontal Alignment Determines the alignment of the display's contents along the X axis
Scripting name Data type Values horizontalAlignment int 2 Left 0 Center 4 Right
Letter Gap
Appendix A. Components
541
Margin
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.5
Value Format
Value Font
Range Fill
Range Stroke
Appendix A. Components
542
Interlock Color
Setpoint Fill
Setpoint Stroke
Stroke Width
Reverse Indicator
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Appendix A. Components
543
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Range High The overall high value for the display
Scripting name Data type Flags rangeHi double bindable
Range Low
Process Value
Setpoint Value
High Interlock
High Alarm
Appendix A. Components
544
Desired High
Desired Low
Low Alarm
Low Interlock
Hi Alarm Active
True when the process value is greater than the hi alarm threshold
Scripting name Data type Flags hiAlarmActive boolean bindable | read-only
True when the process value is greater than the hi-hi alarm threshold
Scripting name Data type Flags hihiAlarmActive boolean bindable | read-only
Hi Interlock Active
True when the process value is greater than the hi interlock threshold
Scripting name Data type Flags hiInterlockActive boolean bindable | read-only
Lo Alarm Active
True when the process value is less than the lo alarm threshold
Scripting name Data type Flags loAlarmActive boolean bindable | read-only
True when the process value is less than the lo-lo alarm threshold
Scripting name Data type Flags loloAlarmActive boolean bindable | read-only
Lo Interlock Active
True when the process value is less than the lo interlock threshold
Scripting name Data type Flags loInterlockActive boolean bindable | read-only
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type dataQuality int
Appendix A. Components
545
Flags
bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.6
Image
Description The image component is a deceptively powerful component. While you can use other components, like the Label, to display images as well, this component gives you much more flexibility. In particular, this component has 4 important features for displaying images: 1. Scaling. 2. Rotation. You can use rotation to create spinning animations by binding it to a Timer component. 3. Color Tinting. Dynamically apply a color tint to an image to allow it to display realtime status. 4. Color Swapping. Use color swapping to change one specific color in an image to another, on the fly. Also used for realtime status display. To choose an image, simply press the browse button ( ) next to this component's Image Path property. You can drag new images (*.png, *.gif, *.jpg, *.bmp) into the Image Management window to upload them. Images are stored on the Gateway, not in your window or project. This means that you can alter an image globally, and it will affect all windows in all projects. It also means that you must be careful to migrate custom images if you do project backups (as opposed to Gateway backups, which will automatically include both projects and images) Properties Appearance Styles Contains the component's styles
Scripting name Data type Flags styles Dataset bindable | expert
Appendix A. Components
546
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
The relative path of the image to be displayed when this component is not enabled.
Scripting name Data type Flags disabledPath String expert
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type dataQuality int
Appendix A. Components
547
Flags
bindable | expert
Image Manipulation Stretch Mode Sets the stretch mode for this image.
Scripting name Data type Values stretchMode int 0 No Stretch 1 Bounds 3 % Bounds 2 Parameters
Stretch Width
If stretch mode is "Parameters", this will be the stretched width of the image If stretch mode is "% Bounds", this will be the percentage of the component's width.
Scripting name Data type Flags stretchWidth int bindable
Stretch Height
If stretch mode is "Parameters", this will be the stretched height of the image If stretch mode is "% Bounds", this will be the percentage of the component's height.
Scripting name Data type Flags stretchHeight int bindable
Swap From
If the Color Swap Filter is on, this color will be changed to the Swap To color.
Scripting name Data type Flags swapFromColor Color bindable
Swap To
If the Color Swap Filter is on, the Swap From color will be changed to this color.
Scripting name Data type Flags swapToColor Color bindable
Swap Threshold
Threshold (0-255) for the swap from color matching. 0 is no tolerance, 255 is max tolerance.
Scripting name Data type Flags swapThreshold int expert
Tint Filter
Tint the entire image a color (works best with greyscale images)
Scripting name Data type Flags useTint boolean bindable
Tint Color
Appendix A. Components
548
Flags
bindable
Flip Horizontal
Flip Vertical
Rotation
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.7
Progress Bar
Description Visually indicates the progress of some task. Can be used to display any value that has an upper and lower bound. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Horizontal?
If true, the progress bar will display horizontally, else it will display vertically
Scripting name horizontal
Appendix A. Components
549
Data type
boolean
Show Percentage?
Direction
Styles
Behavior Indeterminate? When true, the progressbar displays animation indicating that something is happening, but it will take an indeterminate amount of time
Scripting name Data type Flags indeterminate boolean bindable
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Appendix A. Components
550
2 3 12 13 4 5 6 7 8 9 10 11
Text Wait Hand Move SW Resize SE Resize NW Resize NE Resize N Resize S Resize W Resize E Resize
Maximum
Minimum
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.8
Cylindrical Tank
Description
2012 Inductive Automation
Appendix A. Components
551
A component that looks like a 3D cylindrical tank, with some liquid inside. The liquid rises and falls as the Value property changes. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Rotation
Anti Alias
Units
Show Value
Show Percentage
Font Color
Tank Color
Liquid Color
Styles
Appendix A. Components
552
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Capacity
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn
2012 Inductive Automation
Appendix A. Components
553
more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.9
Level Indicator
Description A component that displays the level of fullness of some container. This is basically a visually simplified version of the Cylindrical Tank component. By turning on and off the Gradient and Liquid Waves properties, you can control how fancy this component looks. This component is well suited to be put behind images of tanks with transparent cutaways. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Units
Show Value
Show Percentage
Orientation
Filled Color
Appendix A. Components
554
Background Color
Gradient
Liquid Waves
Wave Length
Wave Height
Font Color
Scripting name Data type fontColor Color
Anti Alias
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
555
cursorCode int 0 Default 1 Crosshair 2 Text 3 Wait 12 Hand 13 Move 4 SW Resize 5 SE Resize 6 NW Resize 7 NE Resize 8 N Resize 9 S Resize 10 W Resize 11 E Resize
Capacity
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
556
Description The linear scale component has two main purposes. The first is to display a series of tick marks and labels that visually represent a linear range between a minimum value and a maximum value. The second purpose is to display indicators that represent a value or range of values, correctly positioned in on the linear scale. In the example above, two linear scales are used to flank a level indicator. The scale on the left has only tick marks, and no indicators. The scale on the right is used to display three indicators and no tick marks. To configure the indicators, you use the Linea Scale's "Scale Indicators" customizer. To configure the tick marks, you use the scale's various properties that determine the minimum value, maximum value, and the various tick mark spans. Properties Appearance Mirror Mirror the scale so it paints against the opposite edge.
Scripting name Data type mirror boolean
Reverse Range
Reverse the scale so that values go from high to low instead of low to high.
Scripting name Data type reverseRange boolean
Label Angle
Margin
The margin to leave blank as a percentage of the total height or width of the scale.
Scripting name Data type margin double
Appendix A. Components
557
majorTickLength double
Label Format
The label format string. Examples: "%.1f" will render numbers like "15.0", "%.0f" will render numbers like "15". Using the empty string "" will disable the labels.
Scripting name Data type majorTickLabelFormat String
Label Font
Label Color
Visible
Appendix A. Components
558
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Max Value
The span length for major ticks. Should be a multiple of the minor and fine tick spans.
Scripting name Data type majorTickSpan double
The span length for minor ticks. Should be a factor of the major tick span and a multiple of the fine tick spans. Use zero to disable minor ticks.
Scripting name Data type minorTickSpan double
The span length for fine ticks. Should be a factor of the major and minor tick spans. Use zero to disable fine ticks.
Scripting name Data type fineTickSpan double
Indicators
This dataset stores the indicators (if any) for the scale.
Scripting name indicators
Appendix A. Components
559
Data type
Dataset
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.11 Barcode
Description The barcode component displays some text as a barcode. The supported formats are: Code 128 Code 39 Extended Code 39 Codabar Interleaved Code 25 MSI EAN-13 EAN-8 See also: system.print.createPrintJob Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Barcode Background
2012 Inductive Automation
Appendix A. Components
560
barcodeBackground Color
Show Text?
Barcode Height
Rotation
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Data Code The code string that is converted into a barcode to display
Scripting name Data type Flags code String bindable
Barcode Format
Appendix A. Components
561
9 10 11
Check Digit
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.12 Meter
A few gradient and transparent circles can give your m eter som e shine
Description A meter display shows a value on a needle-gauge. The gauge's range can be broken up into five intervals. The intervals can have their own edge and background colors. How the meter looks is affected by its appearance properties. You can modify colors, thicknesses, start and extend angles, needle size, etc to get the meter that you want. For example, the meter on the far right of the example has a Meter Angle Extent of 90, a Meter Angle of 45, a reversed range, and 2 intervals. Properties Appearance Units A string to describe the units for the current value label.
Scripting name Data type units String
Appendix A. Components
562
Dial Background
Needle Color
Needle Size
Value Color
Tick Color
Tick Size
Value Format
Tick Format
Arc Width
Appendix A. Components
563
arcWidth float
Meter Angle
The angle in degrees of the centerpoint of the meter (90 is straight up).
Scripting name Data type meterAngle int
Dial Shape
The shape of the dial. This property determines how the dial face looks in the area not covered by the meter angle extent.
Scripting name Data type Values dialType int 1 Chord 0 Circle 2 Pie
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
564
10 11
W Resize E Resize
Data Value The value to display in this meter. The needle and current value label will change to reflect this.
Scripting name Data type Flags value double bindable
Reverse Range?
If true, the meter will consider right to left needle movement as positive.
Scripting name Data type reverseRange boolean
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Interval 1 High
Interval 1 Outline
Interval 1 Background
Interval 2 Low
Interval 2 High
Interval 2 Outline
Appendix A. Components
565
Interval 2 Background
Interval 3 Low
Interval 3 High
Interval 3 Outline
Interval 3 Background
Interval 4 Low
Interval 4 High
Interval 4 Outline
Interval 4 Background
Interval 5 Low
Interval 5 High
Interval 5 Outline
Interval 5 Background
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse
2012 Inductive Automation
Appendix A. Components
566
mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.13 Compass
Com passes can have up to 3 needles and have m any needle types.
Description The compass is a component that displays up to three needles at once on a cardinal direction compass. This can be useful for plotting anything that has a cardinal direction, such as the wind direction. Each needle can be one of 9 different styles. Use the "Disabled" style to turn off any needle. Properties Appearance Value 1 Color The main color for Value 1's needle
Scripting name Data type value1Color Color
Value 1 Outline
Value 2 Color
Value 2 Outline
Value 3 Color
Value 3 Outline
Appendix A. Components
567
Label Font
Rose Color
Rose Highlight
Center Color
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
568
Value 1 Needle
Value 2
Value 2 Needle
Value 3
Value 3 Needle
Appendix A. Components
569
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.3.14 Thermometer
Description This component displays a temperature value depicted as a level in a mercury thermometer. Three temperature intervals can optionally be defined with their own colors. The mercury will change color based on the range that it is in. Properties Appearance Units A string to describe the units for the current value label.
Scripting name Data type Values units int 0 None 1 Fahrenheit 2 Celcius 3 Kelvin
Thermometer Color
Mercury Color
Appendix A. Components
570
Value Color
Thermometer Width
Controls whether or not the mercury color changes based on the range it is in
Scripting name Data type Flags useSubrangePaint boolean expert
Styles
Behavior Follow data in ranges If true, the thermometer's Y axis will scale itself to zoom in on the current range.
Scripting name Data type Flags followDataInSubranges boolean expert
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
571
3 12 13 4 5 6 7 8 9 10 11
Wait Hand Move SW Resize SE Resize NW Resize NE Resize N Resize S Resize W Resize E Resize
Data Value The value to display in this thermometer. The mercury level and value label will change to reflect this.
Scripting name Data type Flags value double bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Interval 1 High
Interval 1 Color
Interval 2 Low
Interval 2 High
Interval 2 Color
Appendix A. Components
572
Interval 3 Low
Interval 3 High
Interval 3 Color
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Description The document viewer is capable of loading and displaying a document that is available over the network at a URL. It is capable of displaying simple HTML and RTF documents. Although HTML links will be followed, it is not a fully functional interactive web browser. Its HTML support is rudimentary at best, and there is no JavaScript support. See the system.net.openURL function for a more robust solution for launching webpages, PDFs, etc. This is component is useful for viewing machine manuals or operator protocol in HTML or RTF format. Note that in addition to HTML URLs (like "http://www.google.com"), you can load files as well using the URL format for files. Some examples: file://localhost/C:/myfolder/file.txt file://MyFileServer/resources/manuals/instructions.rtf" Properties Appearance
Appendix A. Components
573
Font
Foreground Color
Background Color
Behavior Link Action What happens when the user clicks on a hpyerlink inside this document, if it is an HTML document.
Scripting name Data type Values linkAction int 0 Launch Externally 1 Launch Internally 2 Fire Event
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Data Page URL Set this to a URL to display that page. If the url startswith '/', it is assumed to be relative to the Gateway's HTTP address.
Scripting name Data type Flags page String bindable
Appendix A. Components
574
Content Type
text
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion hyperlink focus propertyChange key Scripting Functions This component has no special scripting functions.
Description The IP camera viewing component displays a video stream from a network camera directly in one of your windows. This can be a very powerful tool for allowing operators to view remote or inaccessible locations. Cameras can provide positive feedback about the state and position of machinery, weather, and other factors. This component is capable of displaying two types of video: MJPEG (a.k.a. Motion JPEG) is a streaming video protocol that compresses video frames using standard JPEG compression. Compression rates are quite good, requiring low network bandwidth utilization. Framerates depend greatly on the dimensions of the video, but typically range from 1-20 frames per second. JPEG stills is not a true video protocol, but is rather the practice of continually refreshing an image that a camera is constantly overwriting. Its simplicity means that many cameras support it (usually
Appendix A. Components
575
along with another protocol). Frame rates are typically lower than MJPEG because a new connection must be opened for each frame. Most network cameras on the market support one, if not both of these protocols. Even better, if you have an existing CCTV camera system, video server devices are available that CCTV camera inputs and provide MJPEG streams the network. Finding the URL for your network camera's video stream is usually the only challenge in connecting this component. Most, if not all, network cameras have an internal web server, allowing viewers to use web browsers to view their video stream. If you go to that webpage, and look at the HTML source of the page, you should be able to find the URL of the MJPEG or JPEG still stream. Some examples: Axis 2100 (MJPEG): http://ip.address.here/axis-cgi/mjpg/video.cgi? resolution=640x480 Panasonic BL-C10A (MJPEG): http://ip.address.here/nphMotionJpeg? Resolution=640x480&Quality=Standard StarDot Netcam (JPEG stills): http://ip.address.here/netcam.jpg Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Show Stats
If true, fps and Kbps statistical information will be overlaid on the video.
Scripting name Data type showStats boolean
Behavior Video Mode Choose what type of video stream the URL points to.
Scripting name Data type Values mode int 0 MJPEG Stream 1 JPEG Stills
Refresh Rate
The rate (in ms) to poll the image if mode is 'JPEG Stills'
Scripting name Data type refreshRate int
Use Authentication?
If true, the URL connection will try to authenticate using the given username and password.
Scripting name Data type useAuthentication boolean
Username
Appendix A. Components
576
Data type
String
Password
URL
User-Agent
Scale Video
Scale the video to the size of the viewer component. Warning: CPUintensive.
Scripting name Data type Flags scaleVideo boolean expert
Scale Mode
Connection Retries
Retry Delay
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Appendix A. Components
577
Cursor
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
578
8.4
8.4.1
Tables
Table
Description The Table component is very powerful and easy to configure. It is very flexible, allowing you to easily display your tabular data in a variety of ways. Important features include: Column Sorting. Your users can easily sort the data by clicking on the column headers. The sorting is a 3-mode sort: Ascending, Descending, and "Natural", which uses the default order of the data. Mapped Row Coloring. Map the background color of each row to a particular column. This allows you to give powerful visual indication of different types of rows in you tables, such as differentiating between alarm states. Column Translation. Allow the table component to handle all code mapping, such as mapping 0 to "Off" and 1 to "On". No fancy SQL knowledge required. Images. Map values to images, allowing intuitive visual cues. Progress Bar Indication. Display numeric data as progress bars inside cells, providing fast visual reference for bounded amounts. Number and Date formatting. Format numbers and dates to your exact specification. Column Hiding. Hide columns from view that contain identifying data used by the row coloring or by other components. Printing. Print tables directly to multi-paged printouts. Editing. Columns can be made editable. Changes will be reflected in the underlying dataset, at which point they can be mapped back to a database. Basic Usage The basic usage of the Table is to use a SQL Query binding on its Data property to let the table display data from a database. Often this query will by dynamic or indirect. See the Property Binding
2012 Inductive Automation
Appendix A. Components
579
section for more information. Binding to Selected Data It is common to want to bind other components to values in the selected row of the table. In order to do this safely, you need to write an expression binding that protects against the case when nothing is selected or there are now rows. An expression like this would bind a label to the selected row's value for a column named "ProductCode":
if({Root Container.MyTable.selectedRow} = -1, "n/a", // this is the fail case {Root Container.MyTable.data}[{Root Container.MyTable.selectedRow}, "ProductCode"])
If you're binding to an integer, date, or other non-String type value thats inside a dateset, you'll need to cast the value to the correct type to make the expression parser happy. This binding would cast the selected "Quantity" column to an integer:
if({Root Container.MyTable.selectedRow} = -1, -1, // this is the fail case toInt({Root Container.MyTable.data}[{Root Container.MyTable.selectedRow}, "Quantity"]))
Changing the Column Widths To change a table's column's widths, simply switch into preview mode and use your mouse to resize the columns, and then switch back to design mode. Simple! Editable Table By setting any column to editable in the Table's customizer, the user will be able to double-click in the cell and edit the data. You can the respond to the resulting cellEdited event with an event handler and persist the data. See the Event Types section for more information. Exporting to HTML You can export the table to an HTML file that retain's the table's formatting. To do this, use a script like this: (more about the table's exportHTML function is here.)
table = event.source.parent.getComponent("Table") # Get a reference to the table table.exportHTML("MyTable.html", "My Table Header", 500) # Prompt user to save the exported fil
Exporting to CSV You can export the table's raw data to a CSV file. To do this, use a script like this: (more about the fpmi.db.exportCSV function is here.)
table = event.source.parent.getComponent("Table") # Get a reference to the table system.dataset.exportCSV("mydata.csv", 1, table.data)
Printing Printing a table is a snap! Simply use the table's built in print function like this: table = event.source.parent.getComponent("Table") # Get a reference to the table table.print() See also: SQL Query Binding Expression Binding Event Types - cellEdited system.dataset.exportCSV system.dataset.dataSetToExcel system.dataset.dataSetToHTML system.print.createPrintJob
Appendix A. Components
580
Foreground Color
Background Color
Header Font
Header Visible
Row Height
Background Mode
This mode determines the color that this table's cell's backgrounds will be.
Scripting name Data type Values backgroundColorMode int 1 Constant 2 Alternating 3 Mapped
The color which odd rows will be colored if background mode is 'Alternating'
Scripting name Data type oddBackground Color
Selection Background
Selection Foreground
Appendix A. Components
581
Flags
expert
Behavior Selection Mode This mode determines if only one row/cell/column can be selected at once, or single or multiple intervals
Scripting name Data type Values selectionMode int 0 Single 1 Single Interval 2 Multiple Interval
This flag is used in conjunction with the Column Selection Allowed flag to determine whether not whole-rows, whole-columns, or both (singlecells) are selectable.
Scripting name Data type rowSelectionAllowed boolean
This flag is used in conjunction with the Row Selection Allowed flag to determine whether not whole-rows, whole-columns, or both (single-cells) are selectable.
Scripting name Data type columnSelectionAllowed boolean
Resizing Allowed
Auto-Resize Mode
The index of the row that should be selected by default when this table's data is filled in. Note that you must save the table with no selection in order for this to work.
Scripting name Data type Flags initialRowSelection int expert
Appendix A. Components
582
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Selected Column
Selected Row
Appendix A. Components
583
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Uncategorized TestData Toggle this property to fill in the table's data with random data.
Scripting name Data type Flags test boolean expert
Properties Loading
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse cell focus propertyChange key Scripting Functions
addRow(newRow)
Returns
exportHTML(filename, title, width) user to save the table's data as an html file. Prompts the
Parameters String filename - A suggested filename for the user. For example: "table_data.html" String title - The title for the HTML page. int width - The w idth (in pixels) for the "table" element in the resulting html page. String
Returns
Appendix A. Components
584
getDataAsHTML(title, width) an HTML page as a string in memory. This can then be written Creates
to a file, a database, emailed, etc.
Parameters String title - The title for the HTML page. int width - The w idth (in pixels) for the "table" element in the resulting html page. String - A string containing an HTML-formatted version of the table's data.
Returns
getRowsInViewOrder() a list of ints that represent the underlying dataset's rows as Returns
they appear in the current sort order that the user is viewing.
Parameters Returns none int[]
getSelectedRow() Returns the index of the currently selected row, or -1 if none is selected.
Parameters Returns none int
isCellSelected(row, column) Tests whether the cell at the given row and column is currently selected
or not.
Parameters Returns int row int column boolean - 1 or 0 meaning selected or not selected, respectively.
print(??, ??)
This specialized print function will paginate the table onto multiple pages.
Parameters PyObject[] ?? String[] ??
Appendix A. Components
585
Returns
boolean
setColumnLabel(column, label) a column's header label to a new string at runtime. Used to set
Parameters Returns int column String label nothing
setRowSelectionInterval(index0, index1) to be selected. If index0==index1, it will Sets the given range of rows
select a single row.
Parameters Returns int index0 int index1 boolean
setValue(row, column, value) value in the specified cell, altering the table's Data property. Sets the
Will fire a propertyChange event for the "data" property, as well as a cellEdited event.
Parameters int row - The index of the row to set the value at. int column - The index or name of the column to set a value at. PyObject value - The new value to use at the given row / column location. nothing
Returns
sortByColumn(columnName [, asc]) to sort the data by the named column. Instructs the table
Parameters String columnName boolean asc - 1 means ascending, 0 means descending. (default = 1) [optional] nothing
Returns
sortOriginal()
Instructs the table to clear any custom sort columns and display the data as it is sorted in the underlying dataset.
Parameters Returns none nothing
Appendix A. Components
586
table, and each value must be coercible into the correct datatype of the corresponding column. Returns nothing
8.4.2
List
A basic List
Description The List component displays a list of options, allowing freeform selection of the items. It is powered by a Dataset, from which it displays the first column. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Selected Foreground
Selected Background
Styles
Behavior Selection Mode This mode determines if only one cell can be selected at once, or single or multiple intervals
Scripting name Data type Values selectionMode int 0 Single 1 Single Interval 2 Multiple Interval 2012 Inductive Automation
Appendix A. Components
587
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data Data The data for the list. If multiple columns exist, the first will be used.
Scripting name Data type Flags data Dataset bindable
Selected Index
Appendix A. Components
588
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key Scripting Functions
addSelectionInterval(start, end)at indexes start through end (inclusive) to the selected Adds the options
options.
Parameters int start - The first index (stating at 0) to add to the selection. int end - The last index (stating at 0) to add to the selection. nothing
Returns
getSelectedValue() Returns the currently selected value, or None if the selection is empty
Parameters Returns none Object
getSelectedValues() Returns a list of the currently selected values. Returns an empty list if
the selection is empty.
Parameters Returns none Object[]
setSelectedValue(Sets the currently selected value to the argument, if found in the list. value)
Parameters Returns Object value nothing
Appendix A. Components
589
8.4.3
Description The alert summary table provides an easy way to display current and unacknowledged alerts, and to provide acknowledgement functionality for your alerts. Properties Alert Styles Active and Unacked Foreground 1 Active and Unacked Background 1 Active and Unacked Foreground 2 Active and Unacked Background 2 Active and Unacked Blink?
Scripting name Data type activeAndUnackedBlink boolean
activeAndUnackedForeground1 Color
activeAndUnackedBackground1 Color
activeAndUnackedForeground2 Color
activeAndUnackedBackground2 Color
Active and Acked Foreground 1 Active and Acked Background 1 Active and Acked Foreground 2
activeAndAckedForeground1 Color
activeAndAckedBackground1 Color
activeAndAckedForeground2 Color
Appendix A. Components
590
activeAndAckedBackground2 Color
activeAndAckedBlink boolean
Clear and Unacked Foreground 1 Clear and Unacked Background 1 Clear and Unacked Foreground 2 Clear and Unacked Background 2 Clear and Unacked Blink?
clearAndUnackedForeground1 Color
clearAndUnackedBackground1 Color
clearAndUnackedForeground2 Color
clearAndUnackedBackground2 Color
clearAndUnackedBlink boolean
clearAndAckedForeground1 Color
clearAndAckedBackground1 Color
clearAndAckedForeground2 Color
clearAndAckedBackground2 Color
clearAndAckedBlink boolean
Appendix A. Components
591
clearAndAckedFont Font
Appearance Header Visible? Should the alert table have a header row?
Scripting name Data type headerVisible boolean
Table Background
Table Border
The border around the table itself, not including the controls.
Scripting name Data type scrollPaneBorder Border
Selection Color
Selection Thickness
Row Height
Blink On-Time
Blink Off-Time
Date Format
Number Format
Appendix A. Components
592
ackAllText String
Behavior Refresh Rate The rate at which this table will poll for new alerts.
Scripting name Data type refreshRate long
Flatten Alerts
If true, only one alert state will be shown for any alert. The most recent and severe alert state will be chosen.
Scripting name Data type Flags flatten boolean expert
Auto-Resize Mode
Appendix A. Components
593
showSystem boolean
Appendix A. Components
594
Appendix A. Components
595
columnAckedText String
Appendix A. Components
596
int expert
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Alerts
A dataset holding the alerts that the table is currently displaying. Readonly.
Scripting name Data type Flags alerts Dataset bindable | expert
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Filters System Filter Filter alerts to a specific system. Use * and ? to match any characters or one character, respectively.
Scripting name Data type systemFilter String
Filter alerts by item path. Use * and ? to match any characters or one character, respectively.
Scripting name Data type Flags itemPathFilter String expert
Path Filter
Filter alerts by display path, or item path if no display path is set. Use * and ? to match any characters or one character, respectively.
Scripting name Data type pathFilter String
Min Severity
Appendix A. Components
597
Sort Order Sort by Active Sort priority for sorting by the alert's active state.
Scripting name Data type sortByActive int
Sort by Acked
Sort by Severity
Sort by System
Sort by Path
Appendix A. Components
598
sortByAckedTime int
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus propertyChange key Scripting Functions This component has no special scripting functions.
8.4.4
Tree View
Description The Tree View component can display any tree hierarchy. It is configured by filling in a dataset. Each row in the dataset will become a node in the tree. Each node has a path, for example, "West Area/ Process/Valve1" that determines its location in the tree. The Separation Character property (by default it is forward-slash), dictates how the paths are broken up. Any missing folder nodes needed by a leaf node are created implicitly. The other columns in the dataset besides "Path" are used to configure the look for the node, both when it is selected and when it is not. Columns with the following names (case-insensitive) in the dataset will be recognized: Path - the path determines the node's location. Broken up into a list by splitting on the separation character. Text - the text of the node while not selected. Icon - a path to an icon for the node. Use the value: "default" to use the tree automatic folder/ leaf icons. Background - a string column that will be coerced into a color for the unselected background. e.g.
2012 Inductive Automation
Appendix A. Components
599
"white" or "(255,255,255)" Use an empty string to use the default color. Foreground - a string representation of the unselected foreground color Tooltip - if not empty, will be used as the tooltip for the node. Border - a string that will be coerced into a Border for the node while unselected. May be empty. SelectedText - the text of the node while selected. SelectedIcon - a path to an icon for the node while selected. Use the value: "default" to use the tree automatic folder/leaf icons. SelectedBackground - a string representation of the selected foreground color SelectedForeground - a string representation of the selected foreground color SelectedTooltip - if not empty, will be used as the tooltip for the node while selected. SelectedBorder - a string that will be coerced into a Border for the node while selected. May be empty. The Selected Item property will be updated as the user selects different nodes in the tree. It represents the index in the Items dataset at which the node is defined. If the selected node was implicitly created, the Selected Item will be -1. You can use this index to get the path and name of the selected node with an expression binding like this:
if ({Root Container.Tree View.selectedItem}<0,"n/a", {Root Container.Tree View.data}[{Root Container.Tree View.selectedItem},"text"])
Background Color
Row Height
Appendix A. Components
600
Line Style
Auto Sort
Auto Expand
Selection Mode
Appendix A. Components
601
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Selected Item
Selected Path
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions
Appendix A. Components
602
collapseAll()
expandAll()
getSelectedItems() Returns a list of the selected item's indexes. These are the row indexes
that the selected tree nodes were found in the underlying dataset. Implicitly created folder nodes that have no index will not be included.
Parameters Returns none int[]
getSelectedPaths() Returns a list of the selected item's paths. A path to an item is the path
to its parent plus its normal (non-selected) text.
Parameters Returns none String[]
8.4.5
Comments Panel
Description The comments panel is used to power a blog-style comments system within your project. This can be useful for ad-hoc collaboration and communication between shifts, remote users, etc. This component is driven by a dataset that should be bound to a SQL query. Unlike most components, this component has built-in functionality to alter an external database. This is how the Add Note functionality works. You have the opportunity to alter the queries that the components uses by changing their properties. The schema that typically drives this component involves up to two tables. One table (by default: Notes) stores all of the notes across the board. The second table (by default, ItemNotes) is used to associate notes with other things. This allows you to have different sets of notes for different screens/ objects. Typically you'd bind the data to a query that joined these tables together restricting the second identifier in the ItemNotes table to the value appropriate for the window you're on. You'll also need to alter Insert Query 2's "YOURID" placeholder so that new notes get put in the right spot. You can opt out of this two-table system by simply clearing out Insert Query 2. Users can be given the choice to remove their own comments, and comments can have files attached. To allow attachments, make sure you have a BLOB field in your notes table. This component expects that its dataset is populated with the following columns. The names do not need to be exact, but the data type in your notes table must match.
2012 Inductive Automation
Appendix A. Components
603
ID - an integer that should be the primary key for the notes table. Used for deleting and looking up attachments. Username - the user who added the note. Must be a string/varchar. Timestamp - when the note was added. Must be a Date or DateTime data type. NoteText - The text of the note itself. Must be a string/varchar. AttachmentFilename - filename for a file attached to the note. Must be a string/varchar. Stick - 0 or 1 indicating whether or note the note is "sticky", which means it gets highlighted and put at the top. Must be a boolean or integer. A short explanation for each of the queries and what is passed into them automatically. Note that the column names here do not need to match the ones in the Data property. Insert Query 1: INSERT INTO Notes (Note, WhoID, TStamp, Attachment, Filename, Sticky) VALUES (?, (SELECT Id FROM Users WHERE Username='%s'), CURRENT_TIMESTAMP, ?, ?, ?) This query will insert into your note table using the runPrepStmtGetKey() function and will be given four variables in the following order: note text, attachment blob, attachment filename, and sticky value. Also, it will pass in one string denoted by the %s. This is the name of the user that entered the note and does not need to be placed in any specific spot. If you WhoID field is a string, you can replace (SELECT Id FROM Users WHERE Username='%s') with '%s' to pass the username in directly. Insert Query 2: INSERT INTO ItemNotes (AccountId, NoteId) VALUES (YOURID, %d) This query is optional and will insert the note id from Insert Query 1 into a mapping table of your choice. You must replace YOURID with something meaningful for your mapping table. This is most commonly done by binding this query to an expression. The reason for this second query is to have a mapping table to be joined to the note table to filter out which notes belong to a particular Comment Panel component. Delete Query: DELETE FROM Notes WHERE Id=%d This query will use the note id from the component to delete the selected note. Unstick Query: UPDATE Notes SET Sticky=0 WHERE Id=%d This query will use the note id from the component to set the sticky value to 0. Download Attachment Query: SELECT Attachment FROM Notes WHERE Id=%d This query will use the note id from the component to download the attachment blob from the database. Sample queries for the Data property binding: Note that the data types in the database must be correct and the columns must be in this order Assuming WhoID is a string that contains the username:
SELECT ID, WhoID as 'Username', TStamp as 'Timestamp', Note as 'NoteText', Filename as 'Attachm FROM notes ORDER BY TStamp DESC
Appendix A. Components
604
Foreground Color
Header Color
Note Color
Date Format
Cancel Text
Sticky Text
Padding
Behavior Database Connection Name of the database connection to run the queries against. Leave blank to use project's default connection.
Scripting name Data type datasource String
Appendix A. Components
605
Insert Query 1
This insert query will insert a new note into a notes table. The placeholder %s will be replaced with the current username. The query will be run as a prepared statement, so the query also needs to accept parameters by using the ? placeholder. If attachments are enabled it will use four parameters: Note Body, Attachment Bytes, Attachment Name, Sticky (0/1) When attachments are disabled, it will use two parameters: Note Body, Sticky (0/1)
Scripting name Data type insertQuery1 String
Insert Query 2
This optional insert query inserts the mapping for a new note into a mapping table. %d will be replaced with the ID of the new note. To disable this behavior, simply set this property to a blank string.
Scripting name Data type insertQuery2 String
Delete Query
This query is used for deleting a note. %d is replaced with the note's ID
Scripting name Data type deleteQuery String
Unstick Query
This query is used for changing a note's status to be not sticky. %d is replaced with the note's ID
Scripting name Data type unstickQuery String
Download Attachment Query This query is used for downloading binary attachments. %d is replaced with the note's ID
Scripting name Data type getAttachmentQuery String
Delete Mode
Controls if anyone can delete any note, noone can delete a note, or only owners can delete their notes
Scripting name Data type Flags Values deleteMode int expert 0 No Deletes 1 Ow ner Deletes 2 Any Deletes
Attachments Enabled
Download Mode
Touchscreen Mode
Appendix A. Components
606
Values
0 1 2
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Data Data Fill this DataSet in with the notes for the desired entity. Columns are: Id, Username, Timestamp, NoteBody, Filename, IsSticky
Scripting name Data type Flags data Dataset bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
607
8.5
8.5.1
Charts
Easy Chart
Description This component is used to make powerful and runtime-configurable timeseries charts. It is configured by defining a set of pens and axes. Each pen represents a series of data. Pens can be many different styles, such as line, area, bar, and shape. This chart automatically creates controls for picking the time range and for hiding or displaying pens. Features Easy configuration User-selectable set of pens Automatic time-selection controls SQL Query and/or SQLTags Historian data sources Automatic SPC and calculated pen support Zoom, Pan, X-Trace modes Any number of Y-axes and subplots Realtime or Historical Pens The are three kinds of pens in the Easy Chart: 1. SQLTags Historian Pens. These pens pull their data from the SQLTags Historian system. 2. Database Pens. These pens will automatically create SQL SELECT queries to pull data from a database table. Typically, this is a table that is the target of a Historical Transaction Group. 3. Calculated Pens. These pens display a calculated dataset based off another pen, such as a moving average or an SPC function such as the UCL (Upper Control Limit). Modes: Realtime vs Historical The Easy Chart can operate in 3 different modes. These modes affect the range of data that is displayed, the controls the user is shown, and whether or not the chart polls for data.
Appendix A. Components
608
1. Historical Mode. In this mode, the user is shown a Date Range component to pick the range of data to fetch and display. The initial values of this component are set through properties on the chart. In historical mode, the chart does not poll. 2. Realtime Mode. In this mode, the user is given the opportunity to pick the amount of time in the past to display. For example, the last 5 minutes or the last 2 hours. The chart will poll at a rate according to the Poll Rate parameter. 3. Manual Mode. In this mode, the chart will use the values if its Start Date and End Date parameters to govern what data is displayed. Polling is controlled by having the Poll Rate at zero (polling off) or greater than zero. Basic Chart Configuration The Easy Chart has many properties, like other components, that control its behavior. Things like its Mode, Polling Rate, etc are configured via the properties. All of the setup for adding pens, axes, subplots, etc is its Customizer. You can also drag and drop Historian-enabled SQLTags onto the chart directly in the Designer to add those tags as chart pens. Y-Axes The easy chart supports any number of Y-axes. To add an axis, go to the Axes tab of the chart customizer. When adding an axis, you get a number of options such as the type (numeric or logarithmic), label, color, autorange vs fixed range, and auto-ticks vs fixed ticks. You can also modify the position of the axis, but note that by default the Chart's Auto Axis Positioning property is enabled, which means that the chart will balance the axes automatically between left and right depending on demand. As pens are turned on and off by the user, only the axes that are used by visible pens are shown. After you add your axes, you edit any pens that you want to use your new axes. Simply choose the new axis in the axis dropdown of the pen editing window. Subplots The Subplots feature lets you break up the chart's plot area into multiple distinct subplots that share the X axis, but have their own Y axes. This is often useful for digital data, as shown in the screenshot above. By default the chart has 1 subplot (the main plot). To add a new subplot, simply hit the add button in the Subplots tab of the chart customizer. Subplots have relatively few options. The Weight option determines how much room the subplot gets relative to the other subplots. For example, in the screenshot above subplot #1's weight is 5, and subplot #2's weight is 1, leading to a 5-to-1 distribution of space. Just like axes, once you add your subplots you should go back to your pens and modify you pens' subplot property for any pens you want to appear on the subplot. Pen Groups You can put your pens in groups to break up the pens into some logical separation. For instance, in the screenshot above there are three pen groups: C1, C2, and Valves. The group name is used as the titled border for the pens' grouping container. Groups also have another purpose, but it is more advanced and most people won't have to worry about it. For more, read the Dynamic Pens section below. Advanced Configuration Dynamic Pens In is often the case that you'll want to make one chart window that services many similar pieces of equipment. For instance, if you have 30 tanks and they all have the same datapoints, you want to be
2012 Inductive Automation
Appendix A. Components
609
able to use one window for all 30 of them and simply pass the tank number into the chart window as a parameter. There are actually a number of ways to accomplish this, each method suitable for different scenarios. Database pens have 2 ways to be made dynamic. The first is the Chart's Where Clause property. This is a snippet of SQL where clause syntax, like "machine_num = 28" that will be included for all database pens in their queries. The second is to use a dynamic group. Any group can be made a dynamic group in the customizer. For each dynamic group, the easy chart will get a special dynamic property associated with that group. That property is another snippet of SQL where clause that will be applied to all database pens in that group. The other way to make your pens (and anything else about the chart) dynamic at runtime is to use dynamic configuration. Read on... Dynamic Configuration The Easy Chart is not just meant to be easy to configure, but also very powerful. In particular, there is an emphasis on the ability to make any configuration change dynamically in a client - not just statically in the Designer. While a bit of scripting or clever property binding may be required, the technique is very powerful. This is achieved by storing all of the settings that you alter in the customizer in a set of expert-level dataset properties. So altering the datasets alters the chart configuration. You can inspect these various datasets, which hold the pens, axes, and subplot information, to see their format. They all look up information by column name (case-insensitive). So, if you have pen configuration stored in a database, you can bind an indirect SQL Query binding to alter the chart's pen set at runtime. Properties Appearance Foreground Color The foreground color of the component.
Scripting name Data type foreground Color
Background Color
Plot Background
Plot Outline
Gridline Color
Gridline Width
Appendix A. Components
610
Border
Chart Border
Chart Title
Title Font
X Axis Label
X Axis Visible
Font
Axis Font
Tick Font
Behavior Chart Mode Affects the mode that the chart operates in.Manual Mode: the data selected is determined by the values of the Start Date and End Date properties, which must be set manually.Historical Mode: a date range component will be displayed by the chart, allowing the user to select the time peried they are interested inRealtime Mode: the user will be given the change to choose a span of time, like 15 minutes, and that span will be updated at the poll rate as the data scrolls across
Scripting name Data type Flags Values chartMode int bindable 0 Manual 2012 Inductive Automation
Appendix A. Components
611
1 2
Historical Realtime
Pen Control?
The style in which the pen control panel alters the chart configuration. In heavyweight mode, unchecked pens are not queried, but checking and unchecking pens refreshes the chart. In lightweight mode, all pens are queried, but checking and unchecking pens is quick.
Scripting name Data type Values penControlMode int 0 Heavyw eight 1 Lightw eight
Auto Apply
Poll Rate
The rate (in milliseconds) at which this chart's queries poll. Historical charts don't use this property.
Scripting name Data type pollRate int
X Axis AutoRange?
If true, the X axis will automatically fit the range of available data, if false, it will display a fixed range based on the start date and end date.
Scripting name Data type xAxisAutoRange boolean
X Axis Margin
A margin for the upper and lower ends of the x axis, expressed as a percentage of the total range.
Scripting name Data type xAxisMargin double
The group name to use for pens that are not in a pen group.
Scripting name Data type emptyGroupName String
Group Pens
If true, axes alternate automatically between left and right, rather than being placed explicitly.
Scripting name Data type Flags autoPositionAxes boolean expert
Appendix A. Components
612
Show Loading
Show Warnings
If true, warnings generated during chart configuration will be printed to the console.
Scripting name Data type Flags showWarnings boolean expert
Show Popup?
If true, a popup menu will be shown on right-click that allows the user to change mode, print, save, etc.
Scripting name Data type Flags showPopup boolean expert
Show Tooltips?
Chart Configuration DB Pens This Dataset defines all of the database pens for the chart.
Scripting name Data type Flags pens Dataset bindable | expert
Tag Pens
This Dataset defines all of the SQLTag History pens for the chart.
Scripting name Data type Flags tagPens Dataset bindable | expert
Calculated Pens
Axes
This Dataset defines all axis that can be used by the pens.
Scripting name Data type Flags axes Dataset expert
Subplots
Visible
Mouseover Text
Appendix A. Components
613
this component.
Scripting name Data type toolTipText String
Cursor
Data Selected X Value The selected domain axis value for X-Trace and Mark modes.
Scripting name Data type Flags selectedXValue String bindable | read-only
The number of datapoints to request for tag history pens. -1 means automatic, which uses the width of the chart.
Scripting name Data type Flags tagHistoryResolution int expert
Where Clause
A snippet of where clause that will be applied to all pens, like "TankNum = 2"
Scripting name Data type globalWhereClause String
Start Date
For manual-mode. The start date to use for selecting pen data
Scripting name Data type Flags startDate Date bindable
End Date
For manual-mode. The end date to use for selecting pen data
Scripting name Data type Flags endDate Date bindable
Historical Range Startup Range For historical-mode date range. If startup mode is Automatic, this will be the starting range of time available for selection.
Scripting name Data type startupRange String
Startup Selection
Appendix A. Components
614
Max Selection
For historical-mode date range. The maximum size of the selected date range
Scripting name Data type maxSelectionSize String
Date Style
Time Style
Show Density
For historical-mode date range. If true, a data density histogram will be shown in the date range.
Scripting name Data type showHistogram boolean
Today Color
For historical-mode date range. The color of the "Today Arrow" indicator
Scripting name Data type Flags todayIndicatorColor Color expert
Box Fill
For historical-mode date range. The fill color for the selection box.
Scripting name Data type Flags boxFill Color expert
Selection Highlight
For historical-mode date range. The focus highlight color for the selection box
Scripting name Data type Flags selectionHighlight Color expert
Track Margin
For historical-mode date range. The amount of room on either side of the slider track. May need adjusting of default font is changed.
Scripting name Data type Flags trackMargin int expert
Tick Density
For historical-mode date range. This is multiplied by the width to determine the current ideal tick unit.
Scripting name Data type tickDensity float
Appendix A. Components
615
Flags
expert
For historical-mode date range. The color used to indicate high data density.
Scripting name Data type Flags highDensityColor Color expert
Layout Date Range Affects the position of the date range control.
Scripting name Data type Values dateRangeLocation int 1 Top 2 Bottom
Legend
Horiz Gap
Vert Gap
Alphabetize Pens
Pen Style Options Bar Margin The margin to use for the 'Bar' pen style
Scripting name Data type Flags barMargin double expert
Gap Threshold
The relative threshold to use for determining continuity breaks for the 'Discontinous Line' pen style
Scripting name Data type Flags gapThreshold double expert
3D X Offset
The offset to use in the x direction for the '3D Line' pen style
Scripting name Data type Flags xOffset3D int expert
3D Y Offset
The offset to use in the y direction for the '3D Line' pen style
Scripting name yOffset3D
Appendix A. Components
616
int expert
Digital Gap
Realtime Range Unit Count For realtime-mode date range. The number of units back to display
Scripting name Data type unitCount int
Unit
For realtime-mode date range. The selected unit of the realtime date control
Scripting name Data type Values unit int 1 Seconds 60 Minutes 360 Hours 0 864 Days 00
Realtime Text
For realtime-mode date range. The text to display on the realtime date control.
Scripting name Data type rtLabel String
Total Datapoints
Utility Buttons Show Maximize Button? If true, a small maximize button will be displayed next to the chart.
Scripting name Data type showMaximize boolean
Button Size
Appendix A. Components
617
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.5.2
Chart
Description The Chart component (also called the Classic Chart when contrasted with the Easy Chart) provides a flexible way to display either timeseries or X-Y charts that are powered by any number of datasets. Typically, these datasets are bound to SQL Query bindings. Features SQL Query and/or SQLTags Historian data sources Zoom, Pan, X-Trace modes Any number of Y-axes and subplots Realtime or Historical Many different rendering styles Configuration The basic idea behind configuring the class chart is simple: add datasets, and fill them in with data in a format that the chart understands. You add datasets to the chart using the chart's customizer. You then use standard property binding to put data into these charts. Commonly you'll use a SQL Query binding. Since these datasets are just normal dynamic properties, you can also access them via
2012 Inductive Automation
Appendix A. Components
618
scripting. The Customizer also lets you add additional X and Y axes. There are various types of axes, and they each have a large number of properties. Lastly, you can configure additional properties for each dataset, such as which axes it maps to, its visual style, subplot, etc. Datasets Each dataset should define one or more "series" (a.k.a "pens"). The format for these datasets is quite simple. Each series in a dataset shares common X-values, defined by the first column. Each additional column are the Y-values for a series. For example: t_stamp 2010-01-13 8:05:00 2010-01-13 8:10:00 2010-01-13 8:15:00 motor_amps 16.8 16.8 16.9 motor_speed 223 245 244 motor_hoa_state 0 0 1
Note that it is certainly not a coincidence that this looks just like a database table that the Historical Group is logging to. It is also what the result datasets of a SQLTags Historian query looks like. Rows must be sorted in ascending order. The chart will draw and connect the points in whatever order you provide, them, so unless you want a jumbled mess - don't forget the ORDER BY clause in your query. Make sure that your timestamp column, as well as other columns that may appear in your WHERE clause, are indexed. This will help your chart queries run much faster. We've seen queries that literally take over 5 minutes of database-cranking reduced to a few seconds with the addition of an index. String values are not allowed (except in category chart x-values, see below). Make sure your database columns are numeric, or date/time for x-values. Binding Techniques The classic chart can be used to make almost any kind of chart, with some effort. Historical, realtime, dynamic pen selection, etc is all possible. Your job is just to fill the datasets with the pertinent data, and the chart will display it. The most common idea is to make the chart dynamic by varying the date range that the datas'ts SQL Query bindings run. This is easy to do by adding a Date Range component and using Indirect Bindings. Chart Type: XY vs Category The classic chart is typically in XY Plot mode. This means that the x-axis is either date or numeric, and the y-axes are numeric. If your x-axis is categorical (names, not numbers), you can switch the Chart Type property to Category Chart. Don't be surprised when you get a few errors you'll need to go and switch your x-axis to be a Category Axis, and fill your dataset in with valid category data, that is, String-based x-values. This is most often used with the bar-renderer (see the Customizer). Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Appendix A. Components
619
Foreground Color
Background Color
Plot Background
Chart Title
Chart Orientation
Show Legend?
If true, a legend will be shown for the series displayed in the chart.
Scripting name Data type legend boolean
Behavior Chart Type Choose the type for this chart: XY (Numeric X-axis) or Category (String X-axis)
Scripting name Data type Values chartType int 2 XY Plot 0 Category Chart
Extract Order
Subplot Mode
Show Tooltips?
Appendix A. Components
620
tooltips boolean
Show Popup?
If true, a popup menu will be shown on right-click that allows the user to change mode, print, save, etc.
Scripting name Data type Flags showPopup boolean expert
Selection Enabled?
If true, the user will be able to select datapoints on the chart. The selected datapoint will be highlighted, and the "selectedData" property will reflect it.
Scripting name Data type selectionEnabled boolean
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
621
Flags
bindable | read-only
Selected X Value
The selected domain axis value for X-Trace and Mark modes.
Scripting name Data type Flags selectedXValue String bindable | read-only
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.5.3
Sparkline Chart
Description The sparkline chart is a minimalistic chart component that displays a line-chart history for a single datapoint. Sparklines were invented by Edward Tufte as a way to show a great deal of contextual information in a very small amount of space. Sparklines are typically used to display the recent history (up to current time) of a datapoint so that the viewer can quickly discern the recent trend of a datapoint: is it rising? falling? oscillating? etc.. To use a sparkline, bind its Data property either to a SQLTag Historian realtime query, or to a database query. There should be two columns in this dataset: the first one a date column, the second a number. Each row will become a datapoint on the chart, and the dataset must be sorted by time in ascending order. Instead of using axes to convey scale, the sparkline can display a band of color across the back of
2012 Inductive Automation
Appendix A. Components
622
the chart which indicates the desired operating range of the datapoint. In this way, it is instantly obvious when a value is in its expected range, above that range, or below. The sparkline automatically configures its internal axes based on the data given to it. To give it a fixed range, simply fill in the Range High and Range Low properties. Properties Appearance Background Color The background color of the component.
Scripting name Data type background Color
Line Color
Line Width
The color of the desired operating range band. Only used if the desired operating range is configured.
Scripting name Data type desiredRangeColor Color
Border Inset
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
623
Values
0 1 2 3 12 13 4 5 6 7 8 9 10 11
Default Crosshair Text Wait Hand Move SW Resize SE Resize NW Resize NE Resize N Resize S Resize W Resize E Resize
Range High
A fixed value for the upper edge of the chart. If left blank (null), the upper range will be calculated automatically.
Scripting name Data type rangeHi Double
Range Low
A fixed value for the lower edge of the chart. If left blank (null), the lower range will be calculated automatically.
Scripting name Data type rangeLo Double
Desired High
The high value of the desired operating range. If left blank (null), no desired range band will be shown.
Scripting name Data type desiredHi Double
Desired Low
The low value of the desired operating range. If left blank (null), no desired range band will be shown.
Scripting name Data type desiredLo Double
First Value
Last Value
Min Value
Max Value
Appendix A. Components
624
Chart Max
Chart Min
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Markers First Marker Color The color of the first value marker
Scripting name Data type firstMarkerColor Color
Appendix A. Components
625
Data type
double
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
626
8.5.4
Bar Chart
Description The Bar Chart is a very easy-to-use chart that provides familiar bar charts. It also can be configured to display other kinds of category charts. A category chart is a chart whose X-values are categories (strings) rather than numeric values (numbers, dates). Like most chart components (other than the Easy Chart), the Data property drives the chart. The first column in the Data dataset defines the names of the categories. The rest of the columns define the values for each of the series (if there is more than one series per category), and thus should be numeric. Note - if your data is 'turned on its side', meaning that the columns define the categories and rows define the series, then set the Extract Order to "By Column". Extract Order Example The following two charts demonstrate the effects of the extract order property on the given dataset Label (String) Jan Feb Mar Apr May North Area (Integer) 15 21 17 11 16 35 36 23 39 32 South Area (integer)
Appendix A. Components
627
Properties Appearance Chart Title An optional title that will appear at the top of the chart.
Scripting name Data type title String
Chart Type
Plot Background
Series Colors
Legend?
Scripting name Data type legend boolean
Labels?
Gradient bars?
Shadows?
Foreground Transparency
Vertical
Category Margin
Item Margin
Appendix A. Components
628
Axes Value Axis Label The label for the value axis
Scripting name Data type valueLabel String
If true, the value axis range will be determined automatically. If false, the specified upper and lower bounds will be used.
Scripting name Data type valAxisAutoRange boolean
The lower bound of the value axis. Used only when auto-range is false.
Scripting name Data type valAxisLowerBound double
The upper bound of the value axis. Used only when auto-range is false.
Scripting name Data type valAxisUpperBound double
Category Axis Label Angle The angle for the value axis' labels.
Scripting name Data type Values catAxisLabelPosition int 0 Standard 1 Dow n 45 2 Dow n 90 3 Up 45 4 Up 90
Title Font
Legend Font
Appendix A. Components
629
valAxisTickFont Font
The upper margin, as a percentage, of the value axis. Only used when auto-range is true.
Scripting name Data type valAxisUpperMargin double
Category Axis Upper Margin The upper margin, as a percentage, of the category axis.
Scripting name Data type catAxisUpperMargin double
Category Axis Lower Margin The lower margin, as a percentage, of the category axis.
Scripting name Data type catAxisLowerMargin double
Behavior Tooltips?
Scripting name Data type tooltips boolean
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name border
Appendix A. Components
630
Data type
Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Extract Order
Controls whether the first row defines the categories or the series
Scripting name Data type Values extractOrder int 0 By Column 1 By Row
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
631
8.5.5
Radar Chart
Description Radar charts, also known as web charts, spider charts, spider plots, and a few other names, display multivariate data sets as two dimensional polygons. Each dataset, or series, contains values for three or more variables. The plot is then arranged as a set of spokes with equal angles between them. Each spoke represents a value axis for the variable it corresponds to. Each series is then drawn as a connected polygon, where the points of the polygon are arranged on the spokes according to their value. The intended use of radar plots is to display realtime information in such a way that outliers can be quickly identified. By displaying two series on top of each other, it quickly becomes apparent if one series deviates from the other, and upon which spokes. This can be an efficient way to convey if a process is running on-spec or off-spec at a glance. The radar chart gets its data from a dataset. Each row in the dataset will become a single series (polygon) on the chart. The dataset's first column represents the name of the series, and subsequent columns represent the values. To display realtime data on a radar chart, you can use a cell-update binding to bind individual values to tag values. Alternatively, you can have realtime information stored by a transaction group to a database table, and drive the radar chart's dataset with a query binding. Properties Appearance Background Color The background color of the component.
Scripting name Data type background Color
Series Config
Border Inset
The amount of area that the chart should be inset from the component bounds.
Scripting name Data type Flags borderInset double expert
Spoke Width
The line width for the chart's spokes and exterior ring.
Scripting name Data type strokeWidth float
Spoke Color
The color to use for the chart's spokes and exterior ring.
Appendix A. Components
632
foreground Color
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Cursor
Data Series Data Contains the datapoints for each series. Each row will become a polygon on the chart
Scripting name Data type Flags seriesData Dataset bindable
Spoke Min
The value that corresponds to the centerpoint of the chart. The low value for each spoke.
Scripting name Data type spokeMin double
Spoke Max
The value that corresponds to the outer edge of the chart. The high value for each spoke
Scripting name Data type spokeMax double
Appendix A. Components
633
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.5.6
Status Chart
Description The status chart component allows you to visualize the status of one or more discrete datapoints over a time range. The X-axis is always a timeseries axis, and the Y-axis is a category axis, with one entry per data series. The chart is populated with a single dataset, the first column of which must be a datetime column. Wide vs Tall Datasets. In Wide format, all of the columns but the first must be numeric. These "series" columns' headers will be used as the names on the y-axis. In Tall format, there should be exactly 3 columns. The first is the timestamp, the second is the series name, and the third is the value. For example: Wide Format t_stamp 2010-01-13 8:00:00 2010-01-13 8:02:00 2010-01-13 8:04:00 2010-01-13 8:06:00 2010-01-13 8:08:00 Valve1 0 0 1 1 0 Tall Format Valve2 t_stamp 2 2010-01-13 8:00:00 2 2010-01-13 8:00:00 2 2010-01-13 8:02:00 1 2010-01-13 8:02:00 1 2010-01-13 8:04:00 2010-01-13 8:04:00 2010-01-13 8:06:00 2010-01-13 8:06:00 2010-01-13 8:08:00 2010-01-13 8:08:00 Name Valve1 Valve2 Valve1 Valve2 Valve1 Valve2 Valve1 Valve2 Valve1 Valve2 Value 0 2 0 2 1 2 1 1 0 1
Color Mapping Apart from getting the data into the series chart, the only other commonly configured option is the mapping of discrete values to colors. This is done in the Series Chart Customizer. Each named series can have its own mapping of colors, if desired. These mappings are stored in the expert-level
2012 Inductive Automation
Appendix A. Components
634
dataset property Series Properties Data so they can be altered at runtime. Properties Appearance Background Color The background color of the component.
Scripting name Data type background Color
Chart Title
Title Font
Title Color
Series Spacing
Affects the amount of spacing between series. Can be between 0.0 and 1.0. The series present on this chart are given equal space to display themselves. Series spacing is the precentage of that space that they use to do so.
Scripting name Data type seriesSpacing double
Date Style
Time Style
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Appendix A. Components
635
border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Data Format Format of the incoming data. In "wide" format, the first column of the dataset needs to be a timestamp, and every subsequent column represents one series in the chart. In "tall" format, the first column is a timestamp, the second column is a series name, and the third a value.
Scripting name Data type Values dataFormat int 0 Wide 1 Tall
Series Data
Data about each series. Data can be in either "wide" or "tall" format.
Scripting name Data type Flags data Dataset bindable
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Appendix A. Components
636
domainAxisFont Font
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more.
2012 Inductive Automation
Appendix A. Components
637
mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.5.7
Pie Chart
Description The Pie Chart component displays a familiar-looking pie chart. A Pie Chart displays a list of named items, each of which has a value that is part of a total. The total is the sum of the value of each item. The key to the Pie Chart component is the Data property, which contains the items that will be displayed as pie wedges. Typically, this dataset will be bound to a SQL Query Binding to pull dynamic data out of an external database. Extract Order Similar to other charts, the pie chart can actually accept data in two formats. You can tell the pie chart which format to use via its Extract Order property. The two extract orders are By Column or By Row. The following table shows the two styles for the data that created the pie chart in the screenshot. By Column Label Grapefruit Apples Bananas Kiwis Value 7 15 56 19 Grapefruit 7 By Row Apples 15 Bananas 56 Kiwis 19
Labels In addition to the color-coded legend, the pie chart can annotate each wedge with a label. The format of the label is controlled via the Label Format property. For example, the format string used in the screenshot is "{0} = {2} ({3})" This is a pattern string that uses the following placeholders: {0} - the item label {1} - the item value {2} - the item percentage Properties
2012 Inductive Automation
Appendix A. Components
638
Appearance Chart Title An optional title that will appear at the top of the chart.
Scripting name Data type title String
Plot Background
Section Colors
Outline Colors
Outline Stroke
Legend?
Labels?
Label Format
Formatting String. '{0}' is the wedge name, '{1}' is the value, '{2}' is the percent.
Scripting name Data type labelFormat String
Tooltip Format
Formatting String. '{0}' is the wedge name, '{1}' is the value, '{2}' is the percent.
Scripting name Data type tooltipFormat String
Legend Font
Label Font
Title Font
Starting Angle
Rotation
Appendix A. Components
639
Enforce Circularity?
If true, the pie cannot be an oval, even if the overall chart is.
Scripting name Data type circular boolean
Style
3D?
Foreground Transparency
3D Depth Factor
Behavior Tooltips? Should tooltips be displayed when the mouse hovers over sections?
Scripting name Data type tooltips boolean
Selection Enabled?
If true, the user will be able to select wedges on the chart. The selected wedge will be highlighted, and the "selectedData" property will reflect it.
Scripting name Data type selectionEnabled boolean
Visible
Appendix A. Components
640
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Extract Order
Selected Wedge
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion
2012 Inductive Automation
Appendix A. Components
641
8.5.8
Description A Box and Whisker chart displays pertinent statistical information about sets of data. Each box represents a set of numbers. The upper and lower bounds of the box represent the 1st and 3rd quartiles. The line inside the box represents the median. The extends of the "whiskers" represent the max and min outliers. For a more detailed description, see http://mathworld.wolfram.com/Box-andWhiskerPlot.html. The configuration for setting up a box and whisker chart, like most charts, is populating the Data property. The dataset for a box and whisker chart contains sets of numbers. Each column defines a series of values, for which a "box" will be calculated. The column headers define the name for the box. You may also have an optional first column that is a String column, which can break up the series into categories. For example, the data that generated the plot in the screenshot would have looked like this: Key (String) Granite (Integer) Limestone (Integer) Lot Lot Lot Lot Lot Lot Lot Lot A A A A B B B B 23 24 93 76 21 4 76 89 39 23 54 72 83 21 98 102
Chart Title
Appendix A. Components
642
title String
Series Colors
Plot Background
Fill Boxes?
Legend?
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
643
2 3 12 13 4 5 6 7 8 9 10 11
Text Wait Hand Move SW Resize SE Resize NW Resize NE Resize N Resize S Resize W Resize E Resize
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.5.9
Equipment Schedule
Description The equipment schedule view is a mix between the status chart, gantt chart, and a calendar view. It conveys a lot of information about equipment, including current status, production schedule, production status, scheduled and unexpected downtime.
Appendix A. Components
644
The equipment schedule is powered by four datasets. Information is retrieved from the datasets by column name, case-insensitive. The order of the columns is not important. Optional columns may be omitted. The "Items" Dataset Describes the "items" or "cells" to display schedules for. Each entry in this dataset will become a row of the chart. Name Type Optional Description ID Any N The identifier for this item. May be any type, will referenced by each entry in the Scheduled Events dataset. Label String N The text to display in the header Foreground Color Y Text color Background Color Y Background color StatusImagePath String Y A path to an image to display to the right of the header label. The "Scheduled Items" Dataset Lists the scheduled events for each item described in the "Items" dataset. Each scheduled event can have a colored lead, or change-over time, a label, a background color, and a progress. Name Type Optional Description EventId String Y An identifier for the event, used for event selection. ItemId Any N The ID of the item to correlate this event with. If no such item is found, the event won't be shown. Label String N The text ot display in the event's box StartDate Date N The start-time for the event EndDate Date N The end-time for the event Foreground Color Y The text color of the event Background Color Y The background color of the event LeadTime Integer Y Time, in seconds, to display as lead time. LeadColor Color Y The color for the lead time, if any. PctDone Number Y A value from 0 to 100 to be displayed as a progress bar, use -1 to hide progress bar. The "Downtime" Dataset Entries in this dataset will be displayed as simple colored overlays on top of the events, correlated against an item defined in the "Items" dataset. Name Type Optional Description ItemId Any N The ID of the item to correlate this downtime event with. If no such item is found, the downtime event won't be shown. StartDate Date N The start-time for the downtime event EndDate Date N The start-time for the downtime event Color Color Y The color to use, typically transparent. Layer Integer Y 0 or 1, with 0 meaning that the rectangle gets painted below the events, and 1 means it will be painted above the events. The "Breaks" Dataset
Appendix A. Components
645
Entries in this dataset will be displayed as colored underlays beneath all events. Name Type Optional Description StartDate Date N The start-time for the break event EndDate Date N The start-time for the break event Color Color Y The color to use Properties Appearance Event Border The normal border for a scheduled event
Scripting name Data type eventBorder Border
Row Height
Event Margin
Schedule Background
Line Color
Header Font
Header Background
Appendix A. Components
646
Event Font
Behavior Drag Enabled Controls whether or not scheduled events can be dragged for rescheduling.
Scripting name Data type dragEnabled boolean
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Data Items The cells, or equipment items, to have their schedules displayed.
Scripting name Data type Flags items Dataset bindable
Scheduled Events
Downtime Events
Break Events
Appendix A. Components
647
Flags
bindable
Start Date
End Date
Selected Event ID
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion scheduleDrop propertyChange Scripting Functions This component has no special scripting functions.
Description A Gantt chart is used for task scheduling. It shows a list of named tasks, each of which have a start date, an end date, and a percentage complete. This allows an easy way to visualize tasks, workflows, and scheduling. The Gantt chart is configured by populating its Data property. Each row of the dataset represents a task. There should be four columns: the task label, the start date, the end date, and the percentage (0-100) complete. Properties Appearance
Appendix A. Components
648
Chart Title
Task Color
Complete Color
Incomplete Color
Plot Background
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
649
Values
0 1 2 3 12 13 4 5 6 7 8 9 10 11
Default Crosshair Text Wait Hand Move SW Resize SE Resize NW Resize NE Resize N Resize S Resize W Resize E Resize
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.6
8.6.1
Calendar
Calendar
Description Displays a calendar and time input directly embedded in your window. Most commonly used by
2012 Inductive Automation
Appendix A. Components
650
including one of the two date properties (immediate or latched) from the calendar in dynamic SQL Query Bindings. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Today Foreground
Today Background
Weekend Foreground
Weekend Background
Selected Border
Title Background
Styles
Behavior Time Style Select how this calendar should treat the time portion of the date.
Scripting name Data type Values timeStyle int 0 User Selectable 1 Start of Day 2 End of Day
Show OK Button
Turn this off if you don't want to show the OK button. The latched date and the immediate date will be equivalent.
Appendix A. Components
651
showOkButton boolean
Show Time
Turn this off if you don't want to show the time panel.
Scripting name Data type showTime boolean
Format String
The date formatting pattern used to format the string versions of the dates.
Scripting name Data type format String
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data
2012 Inductive Automation
Appendix A. Components
652
Date (immediate)
Date (latched)
Formatted Date
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.6.2
Popup Calendar
Appendix A. Components
653
Description The popup calendar is a popular way to provide date/time choosing controls on a window. Similar to the Calendar component, but takes up much less screen real estate. Most commonly used by including this component's Date property in dynamic SQL Query Bindings. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Today Foreground
Today Background
Weekend Foreground
Weekend Background
Selected Border
Title Background
Calendar Background
Styles
Behavior Time Style Select how this calendar should treat the time portion of the date.
Scripting name timeStyle
Appendix A. Components
654
int 0 1 2
Show OK Button
Turn this off if you don't want to show the OK button. The latched date and the immediate date will be equivalent.
Scripting name Data type showOkButton boolean
Show Time
Turn this off if you don't want to show the time panel.
Scripting name Data type showTime boolean
Format String
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
655
Text
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.6.3
Date Range
Description The date range component provides an intuitive, drag-and-drop way to select a contiguous range of time. The user is shown a timeline and can drag or stretch the selection box around on the timeline. The selected range is always a whole number of units, where the unit is determined by the current zoom level. For instance, in the screenshot the selected range is Feb 12, 2007 through Feb 20, 2007. This means from the beginning of the 12th through the end of the 20th. Using this component is as simple as using the Start Date and End Date properties that the component provides. Typically, you'll include these dates in a dynamic SQL query binding that drives whatever you're using the date range for, such as a table or chart. For instance, your query binding might look like this:
SELECT Column1, Column2, Column3 FROM MyTable WHERE t_stamp >= {Root Container.Date Range.startDate} AND t_stamp <= {Root Container.Date Range.endDate}
Appendix A. Components
656
As an advanced optional feature, the date range can display a data density histogram inside the timeline. This is useful for historical data with gaps in it, so that the end user isn't hunting for data. (Tip: this is also great for demos, to make it easy to find historical data in a database that isn't being continously updated). To use this feature, bind the Data Density dataset to a query that returns just the timestamps of the target table. These timestamps will be used to fill in the histogram behind the timeline. You can use the Outer Range Start Date and Outer Range End Date properties in your query to limit the overall return size for the query. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Today Color
Editor Background
The background color of the textual date range editor portion of this component.
Scripting name Data type editorBackground Color
Box Fill
Selection Highlight
Track Margin
The amount of room on either side of the slider track. May need adjusting of default font is changed.
Scripting name Data type Flags trackMargin int expert
Date Style
Appendix A. Components
657
Flags Values
Time Style
Styles
Behavior Startup Mode Controls whether or not this date range automatically assigns itself a starting range based on the current time
Scripting name Data type Values startupMode int 0 None 1 Automatic
Startup Range
If startup mode is Automatic, this will be the starting range of time available for selection.
Scripting name Data type startupRange String
Startup Selection
Max Selection
Tick Density
This is multiplied by the width to determine the current ideal tick unit.
Scripting name Data type Flags tickDensity float expert
Enabled
Visible
Appendix A. Components
658
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data Start Date The starting date of the currently selected range.
Scripting name Data type Flags startDate Date bindable
End Date
Data Density
Appendix A. Components
659
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.6.4
Day View
Description This component displays a timeline for a single day, similar to what you might find in a personal planner/organizer. By filling in the Calendar Events dataset property, the component will display events that occur on this day. Each event can have custom text and a custom display color associated with it. The format of the dataset requires 4 columns, as demonstrated by the following dataset: StartDate (Date) 2010-01-10 8:00:00 2010-01-10 13:30:00 Properties Appearance Working Start Hour The start hour of a working day
Scripting name Data type Flags workingStartHour int bindable
Appendix A. Components
660
24 Hour Format
Zoom
Grid marks
Week Day Foreground Color The color of the week day's text.
Scripting name Data type Flags weekDaysForeground Color bindable
Appendix A. Components
661
Flags
bindable
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
662
int bindable
Month
Day
Calendar events
Hovered Time
Selected Event
Hovered Event
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
663
8.6.5
Week View
Description Displays a full week's worth of events on a calendar. Configuration is achieved by populating the Calendar Events dataset. See the Day View for details. Properties Appearance Working Start Hour The start hour of a working day
Scripting name Data type Flags workingStartHour int bindable
24 Hour Format
Show Weekend?
Zoom
Appendix A. Components
664
boolean bindable
Grid marks
Week Day Foreground Color The color of the week day's text.
Scripting name Data type Flags weekDaysForeground Color bindable
Non-Working Hours
Appendix A. Components
665
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Month
Appendix A. Components
666
Day
Calendar events
Selected Day
Hovered Day
Hovered Time
Selected Event
Hovered Event
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
667
8.6.6
Month View
Description Displays a month's worth of events on a calendar. Configuration is achieved by populating the Calendar Events dataset. See the Day View for details. Properties Appearance Header Font The font of the header's text.
Scripting name Data type headerFont Font
Affects how events are displayed.Standard Mode: Displays each eventHighlight Mode: Highlights each day that contains events using the event highlight background color.
Scripting name Data type Flags Values displayMode int bindable 1 Standard 2 Highlight
Event Highlight Background The background color of a day with events. Used only in highlight mode.
Scripting name Data type Flags highlightBackground Color bindable
Appendix A. Components
668
Flags
bindable
Week Day Foreground Color The color of the week day's text.
Scripting name Data type Flags weekDaysForeground Color bindable
Day Font
The font for the number representing the day of the month.
Scripting name Data type dayFont Font
Day Other Foreground Color The foreground color for days not in this month
Scripting name Data type Flags dayOfMonthOtherForeground Color bindable
Event Font
Appendix A. Components
669
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Year
Appendix A. Components
670
Flags
bindable
Calendar events
Selected Day
Hovered Day
Selected Event
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7
8.7.1
Misc
Container
Description The container is a very important component. All components are always inside of a container,
2012 Inductive Automation
Appendix A. Components
671
except for the special "Root Container" of each window (see Anatomy of a Window). A container is different than normal components in that it can contain other components, including other containers. Uses for containers include: Organization. Containers can be used to group components together. These components can then easily be moved, copied, or deleted as a group. Furthermore, they will all be organized inside of their parent container in the project navigation tree, which makes them easier to find. Re-usability. Containers allow a unique opportunity to create a complex component that is made up of multiple other components. The Container's ability to have dynamic properties aids this greatly. For instance, if you wanted to make your own custom HOA control, you can put three buttons inside of a container and configure them to all use a 'status' property that you add to their parent Container. Now you have built an HOA control that can be re-used and treated like its own component. The possibilities here are endless. Create a date range control that generates an SQL WHERE clause that can be used to control Charts and Tables. Create a label/button control that can be used to display datapoints, and pop up a parameterized window that displays meta-data (engineering units, physical location, notes, etc) about that datapoint. Creating re-usable controls with Containers containing multiple components is the key to rapid application development. Layout. Containers are a great way to improve window aesthetics through borders and layout options. Grouping A container can be set as a "group" by right-clicking on it and choosing "Group Container". This will make the container act like a single component - you won't be able to select its children by clicking on them. This can help make window design easier, as you'll always pick the container by clicking anywhere inside it. You can still get to the individual sub-components by choosing them in the project navigation tree. You can un-group a container at any time by right clicking on it and choosing "Ungroup Container". See also: Component Layout Custom Palettes Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Background Color
Texture
Styles
Behavior
Appendix A. Components
672
Combine Repaints
Set this to true for containers with many sub-components that need to redraw frequently (flashing, rotating, animating).
Scripting name Data type combineRepaints boolean
Tile Optimized
If true, this container's children should never overlap, and you'll get better painting performance.
Scripting name Data type Flags optimizedDrawingEnabled boolean expert
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Cursor
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type dataQuality int
Appendix A. Components
673
Flags
bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7.2
Paintable Canvas
Description The Paintable Canvas component is a component that can be custom "painted" using Jython scripting. By responding to the component's repaint event, a designer can use Java2D to draw anything within the component's bounds. Whenever any dynamic properties on the component change, the component is re-painted automatically, making it possible to create dynamic, vectordrawn components that can represent anything. This component is an advanced component for those who are very comfortable using scripting. It is not user-friendly. The upside is that it is extraordinarily powerful, as your imagination is the only limit with what this component can be. When you first drop a Paintable Canvas onto a window, you'll notice that it looks like a placeholder. If you switch the Designer into preview mode, you'll see an icon of a pump displayed. The pump is an example that comes pre-loaded into the Paintable Canvas. By editing the component's event scripts, you can dissect how the pump was drawn. You will notice that the script uses Java2D. You can read more about Java2D here http://java.sun.com/docs/books/tutorial/2d/index.html. You will notice that as you resize the pump, it scales beautifully in preview mode. Java2D is a vector drawing library, enabling you to create components that scale very gracefully. Tips: Don't forget that you can add dynamic properties to this component, and use the styles feature. Use the values of dynamic properties in your repaint code to create a dynamic component. The component will repaint automatically when these values change. You can create an interactive component by responding to mouse and keyboard events You can store your custom components on a custom palette and use them like standard components. See also: Event Types - repaint
2012 Inductive Automation
Appendix A. Components
674
Foreground Color
Background Color
Styles
Behavior Focusable If the component is focusable, it will recieve keyboard input and can detect if it is the focus owner.
Scripting name Data type Flags focusable boolean expert
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
675
5 6 7 8 9 10 11
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion focus paint propertyChange key Scripting Functions This component has no special scripting functions.
8.7.3
Line
Description Description missing. Properties Appearance Anti Alias Draw component using anti-aliasing?
Scripting name Data type Flags antiAlias boolean expert
Color
Line Width
Line Mode
The line mode determines where in the rectangle the line is drawn.
Scripting name Data type Flags Values lineMode int bindable 0 Horizontal/Vertical
Appendix A. Components
676
1 2
Line Style
The line style determines how the shape of the line looks
Scripting name Data type Flags Values lineStyle int bindable 0 Plain 1 Dashed 2 Sinusoidal 3 Sinusoidal-Dashed 4 Loop 5 Loop-Dashed
Dash Pattern
Enter a string of comma-delimited numbers which indicate the stroke pattern for a dashed line. For instance, "3,5" means three pixels on, five pixels off.
Scripting name Data type strokePattern String
Sine Length
Sine Height
Left Arrow
Right Arrow
Styles
Visible
Appendix A. Components
677
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7.4
Pipe Segment
Description Description missing. Properties Appearance Center Fill The center of the fill gradient
Scripting name Data type Flags mainColor Color bindable
Edge Fill
Appendix A. Components
678
Color bindable
Outline Color
End 1 Top?
End 1 Cap?
End 1 Bottom?
End 2 Top?
End 2 Cap?
End 2 Bottom?
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
679
cursorCode int 0 Default 1 Crosshair 2 Text 3 Wait 12 Hand 13 Move 4 SW Resize 5 SE Resize 6 NW Resize 7 NE Resize 8 N Resize 9 S Resize 10 W Resize 11 E Resize
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7.5
Pipe Joint
Description Description missing. Properties Appearance Center Fill The center of the fill gradient
Scripting name Data type Flags mainColor Color bindable
Edge Fill
Outline Color
Appendix A. Components
680
Top?
Right?
Bottom?
Left?
Styles
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
681
Data Data Quality The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7.6
Sound Player
Description The Sound Player component is an invisible component that facilitates audio playback in the client. Each Sound Player component has one sound clip associated with it, and will play that clip on demand. There is a built in triggering system, as well as facilities to loop the sound while the trigger is set. Note that the sound clip needs to be a *.wav file, and that the clip becomes embedded within the window that the sound player is on - clients do not need access to a shared *.wav file. Properties Behavior Play Mode The Play Mode determines whether the sound is played automatically on trigger or manually
Scripting name Data type Values playMode int 0 Manual 1 On Trigger
Loop Mode
The Loop Mode determines how many times the sound is played when triggered.
Scripting name Data type Values loopMode int 0 Play Once 1 Loop Forever 2 Loop N Times
Loop Count
Volume
Mute
Appendix A. Components
682
Data type
boolean
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Data Trigger The clip will be played when the trigger is true, if Play Mode is "ON_TRIGGER"
Scripting name Data type Flags trigger boolean bindable
Sound Data
Data Quality
The data quality code for any tag bindings on this component.
Scripting name Data type Flags dataQuality int bindable | expert
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.7.7
Timer
Description The timer button is an invisible button that can be used to create repeated events in a window. This is often used for animations or repetitive scripts within a window. When running, the timer's Value property is incremented by the Step By value, until the value tis the Bound, at which point it repeats. It is often useful to bind other values to a timer's Value property. For instance, if you set the timer's Bound property to 360, and bind an object's rotation to the Value property, the object will spin in a circle when the timer is running. Or, suppose that you have images that make up frames of animation. Name your images: "Frame0. png", "Frame1.png", "Frame2.png". Set the timer's Bound to be 3, Then bind the image path of an image component to the following expression:
"Frame" + {Root Container.Timer.value} + ".png" 2012 Inductive Automation
Appendix A. Components
683
How fast the timer counts is up to the Delay property, which is the time between counts in milliseconds. Want to run a script every time the timer counts? First, make sure you don't actually want to write a project Timer Script, which will run on some interval whenever the application is running. In contrast, a script that works via a Timer component will only run while the window that contains the Timer is open, and the Timer is running. The way to do this is to attach an event script to the actionPerformed event. Properties Behavior Delay (ms) The delay in milliseconds between timer events.
Scripting name Data type Flags delay int bindable
The delay in milliseconds before the first event when running is set to true.
Scripting name Data type Flags initialDelay int bindable
Running?
Data Value The current value of this timer, for use as a counter.At each iteration, this value will be set to ((value + step) MOD bound)
Scripting name Data type Flags value int bindable
Step by
The amount added to the value each time this timer fires for use as a counter. (should be positive)
Scripting name Data type step int
Bound
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. action
2012 Inductive Automation
Appendix A. Components
684
8.7.8
Signal Generator
Description The signal generator is similar to the Timer component, but its value isn't simply a counter. Instead, you can choose from a variety of familiar 'signals'. You configure the frequency by setting the Period property, which is in milliseconds. You configure the resolution by setting the Values/Period property. For example, if you choose a sine wave signal with a period of 2000 milliseconds and 10 values/ period, your sine wave will have a frequency of 0.5 Hz, and its value will change 10 times every 2 seconds. Properties Behavior Signal Type The signal type (shape) of the signal value
Scripting name Data type Values signalType int 0 Sine 2 Triangular 1 Ramp 3 Square 4 Random
Running?
Period
Values/Period
Upper Bound
Appendix A. Components
685
Lower Bound
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. action propertyChange Scripting Functions This component has no special scripting functions.
8.8
8.8.1
Reporting
Report Viewer
Description This component is the heart of the Reporting Module. The customizer for this component is the Report Designer. See the Reporting section for more about creating dynamic reports. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Zoom Factor
Behavior Suggested Filename The filename that will come up by default when the user saves the report to disk.
Scripting name Data type suggestedFilename String
Print Mode
Sets the printing mode. Vector is fast and high-quality for printers that support it, but Raster mode can help the spool size with older printers.
Scripting name Data type Flags Values printingMode int expert 0 Vector
Appendix A. Components
686
Raster
Raster DPI
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Uncategorized Properties Loading The number of properties currently being loaded. When this is zero, no properties are awaiting data.
Scripting name Data type Flags propertiesLoading int bindable | read-only
Report Loading
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
687
8.8.2
Row Selector
Description The row selector is a component that acts like a visual filter for datasets. It takes one dataset, chops it up into various ranges based on its configuration, and lets the user choose the splices. Then it creates a virtual dataset that only contains the rows that match the selected splices. The most common way to splice the data is time. You could feed the row selector an input dataset that represents a large time range, and have it break it up by Month, Day, and then Shift, for example. Then you could power a report with the output dataset, and that would let the user dynamically create reports for any time range via an intuitive interface. To configure the row selector, first you set up the appropriate bindings for its input dataset. Then you use its Customizer to alter the levels that it uses to break up the data. In the customizer, you add various filters that act upon columns in the input dataset, sorting them by various criteria. For example, you could choose a date column, and have it break that up by quarter. Then below that, you could have it use a discrete filter on a product code. This would let the user choose quarterly results for each product. Each level of filter you create in the customizer becomes a level in the selection hierarchy. Note that the output data is completely unchanged other than the fact that rows that don't match the current user selection aren't present. This component is very handy for driving the Report Viewer, Table, and Classic Chart components, among others. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Appendix A. Components
688
Data type
Color
Selection Background
Text for any 'Unknown' nodes (nodes where the data didn't match filter)
Scripting name Data type Flags unknownNodeText String expert
Icon for any 'Unknown' nodes (nodes where data didn't match filter)
Scripting name Data type Flags unknownIconPath String expert
Behavior Show All Data Node Should the 'All Data' (root) node be shown or hidden?
Scripting name Data type showAllDataNode boolean
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Appendix A. Components
689
Data type
boolean
Cursor
Data Data In The input of the row selection tree. The filter tree changes based on this DataSet.
Scripting name Data type dataIn Dataset
Data Out
The output of the row selection tree. Changes based on user selection in the filter tree.
Scripting name Data type Flags dataOut Dataset bindable
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
Appendix A. Components
690
8.8.3
Column Selector
Description The column selector component is conceptually similar to the Row Selector, except that instead of filtering rows, it filters columns from its output dataset. Each column from the input dataset is shown as a checkbox. As the user checks and un-checks columns, the output dataset has those columns added or removed. This is very handy for driving the Table and Classic Chart components. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Normalize Widths
If true, all checkboxes will be assigned the same width, which causes them to line up in columns
Scripting name Data type Flags normalizeWidths boolean expert
Horizontal Gap
Appendix A. Components
691
Vertical Gap
Behavior Group by Dataset If true, checkboxes will be grouped by their dataset. Otherwise, checkboxes will be arranged flat.
Scripting name Data type grouping boolean
Alphabetize
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Scripting
Appendix A. Components
692
Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.8.4
File Explorer
Description The File Explorer component displays a filesystem tree to the user. It can be rooted at any folder, even network folders. It can also filter the types of files that are displayed by their file extension (For example, "pdf"). The path to the file that the user selects in the tree is exposed in the bindable property Selected Path. This component is typically used in conjuction with the PDF Viewer component, in order to create a PDF viewing window. This is very useful for viewing things like maintenance manuals from within your project. To use this component to drive a PDF Viewer component, follow these steps: 1. Bind the PDF Viewer's Filename property to the File Explorer's Selected Path property 2. Set the File Explorer's File extension filter to "pdf" 3. Set the File Explorer's Root Directory to a network folder that has your maintenance manuals in it. (Use a network folder so that all clients will be able to access the manuals). Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Appendix A. Components
693
Foreground Color
Background Color
Behavior File extension filter Semi-colon separated list of extensions to filter out files, such as pdf or txt. Example "pdf;html;txt" shows pdf, html and text documents.
Scripting name Data type fileFilter String
Root Directory
Enabled
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Cursor
Appendix A. Components
694
11
E Resize
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
8.8.5
PDF Viewer
The PDF View er show ing a schem atic in a m aintenance m anual 2012 Inductive Automation
Appendix A. Components
695
Description The PDF Viewer component displays a PDF that exists as a file in some accessible filesystem, or as a URL. Note that this component is simply for viewing existing PDFs. To create dynamic reports, use the Report Viewer component. This component is typically used in conjunction with the File Explorer component, in order to create a PDF viewing window. See the File Explorer's documentation for instructions on how to put these two components together. Warning. This component is not as high-quality as Adobe Reader. This component can only be guaranteed to correctly display reports generated by the Report Viewer. In practice, it is able to view many PDFs, but it does have trouble with some, especially PDFs created by AutoCAD. If this is a problem, use the free ActiveX module to embed an Adobe Reader control within your window. Of course, this will make your clients Windows-only. Properties Appearance Font Font of text of this component
Scripting name Data type font Font
Foreground Color
Background Color
Zoom Factor
Behavior Print Mode Sets the printing mode. Vector is fast and high-quality for printers that support it, but Raster mode can help the spool size with older printers.
Scripting name Data type Flags Values printingMode int expert 0 Vector 1 Raster
Raster DPI
Appendix A. Components
696
Visible
Border
The border surrounding this component. NOTE that the border is unaffected by rotation.
Scripting name Data type border Border
Mouseover Text
The text that is displayed in the tooltip which pops up on mouseover of this component.
Scripting name Data type toolTipText String
Opaque
Scripting Events The following event sets are fired by this component. See Component Event Handlers to learn more. mouse mouseMotion propertyChange Scripting Functions This component has no special scripting functions.
698
9
9.1
9.1.1
9.1.2
... would return 380 You can also use this function to find the maximum in fixed series of numbers, specified as arguments, like this:
max(0, 10/2, 3.14)
... would return 5. The following example is a great way to make sure a value never goes below zero:
max({SomeValue}, 0}
699
9.1.3
Severity 4 2 2
You could use this expression to get the date and time for the most recent alert:
maxDate({Root Container.Table.data}, "AlertTime")
9.1.4
9.1.5
700
FWL_220
322
7.889
9.1.6
... would return 120 You can also use this function to find the minimum in fixed series of numbers, specified as arguments, like this:
min(0, 10/2, 3.14)
... would return 0. The following example is a great way to make sure a value never goes above 180:
min({SomeValue}, 180}
9.1.7
Severity 4 2 2
You could use this expression to get the date and time for the oldest alert:
minDate({Root Container.Table.data}, "AlertTime")
701
9.1.8
9.1.9
9.2
9.2.1
Colors
brighter brighter(color)
Returns a color that is one shade brighter than the color given as an argument. Note that if you pass in a fully saturated color, like (255,0,0), it cannot be made brighter.
brighter(color(100,150,250))
702
9.2.2
9.2.3
darker darker(color)
Returns a color that is one shade darker than the color given as an argument.
darker(color(100,150,250))
9.2.4
...returns red.
gradient(100, 0, 100, toColor("red"), toColor("blue"))
...returns blue.
gradient(60, 0, 100, toColor("red"), toColor("blue"))
...will return a gradient from red to blue based on the level of a tank.
9.3
9.3.1
703
...returns a date eight days before the date in a Popup Calendar component.
9.3.2
...returns 15.5
dateDiff(toDate("2008-2-24 8:00:00"), toDate("2008-3-12 9:28:00"), "month")
...returns 1.0
dateDiff(toDate("2008-2-24 8:00:00"), toDate("2008-3-12 9:28:00"), "day")
...returns 17.02
9.3.3
...returns 2003
dateExtract(toDate("2009-1-15 8:00:00"), "month")
...returns 0
dateExtract(toDate("2008-1-24 8:00:00"), "month") + 1
...returns 1
704
9.3.4
9.3.5
now now([pollRate])
Returns the current time. The host computer's system clock is used, meaning that if this expression is being evaluated in a running client, the computer running the client's system clock is used. Note that this function is one of the few expression functions that will poll. If you do not specify a pollRate, it will default to 1,000ms. If you do not want this function to poll, use a poll rate of zero.
now()
...returns a string representing the current time, formatted like "Feb 12, 9:54 AM"
9.3.6
timeBetween timeBetween(date,date,date)
Checks to see if the given time is between the start and end times. The given times are expected as strings, and may include dates. Note: dates will be parsed according to the default system culture.
...returns true
timeBetween("2:00:00 pm", "9:00:00 am", "5:00:00 pm")
...returns true
2012 Inductive Automation
705
...returns true (Note: This example also shows the variety of date formats accepted)
...returns true
9.4
9.4.1
Logic
binEnc binEnc(boolean1, boolean2, ...)
This function, whose name stands for "binary encoder", takes a list of booleans, and treats them like the bits in a binary number. It returns an integer representing the decimal value of the number. The digits go from least significant to most significant. This can be a very handy tool to convert bits into an integer code to drive the Component Styles feature.
binEnc(0,0,1,0)
9.4.2
...returns 2
binEnum(0, false, 15, 0, 23)
9.4.3
706
...would return the value in the dataset if it isn't null, but 0 if it is null.
9.4.4
...would return 0
getBit(1,0)
...would return 1
getBit(8,3)
...would return 1
getBit(8,2)
...would return 0
9.4.5
9.4.6
isNull isNull(value)
Tests to see whether or not the argument value is null or not. Note that you can also check for null by simply comparing the value to the null keyword. isNull(x) is the same as x = null.
if(isNull({Root Container.MyProperty}), 0, 1)
9.4.7
707
noMatchValue is returned. Note: The type of the value returned will always be coerced to be the same type as the noMatchValue. If lookupColumn is not specified, it defaults to 0. If resultColumn is not specified, it defaults to 1. The examples are based of a table that has the following data in it: PRODUCT PRICE CATEGORY "Apples" 1.99 "Fruit" "Carrots" 3.50 "Vegetable" "Walnuts" 6.25 "Nut"
lookup({Root Container.Table.data}, "Carrots", -1.0)
9.4.8
...would return 46 because the value (15) matched case 3, so the third return (46) was returned.
switch( 35, // value 50, // case 1 52, // case 2 200, // return 1 100, // return 2 -1) // default
...would return -1 because the value (35) didn't match case 1 or 2, so the returnDefault was used.
switch( 2012 Inductive Automation
708
1, // value 0, 1, 2, // cases 1-3 "Off", // return 1 "Running", // return 2 "Fault", // return 3 forceQuality("!BAD STATE!",0)) // default
9.4.9
9.5
9.5.1
Math
abs abs(number)
Returns the absolute value of number.
abs(-4)
... returns 4
9.5.2
acos acos(number)
Returns the arc cosine of number, which must be a number between -1 and 1. The results will be an angle expressed in radians in the range of 0.0 through pi.
acos(.38)
9.5.3
asin asin(number)
Returns the arc sine of number, which must be a number between -1 and 1. The results will be an angle expressed in radians in the range of -pi/2 through pi/2
asin(.38)
9.5.4
atan atan(number)
Returns the arc tangent of number, which must be a number. The results will be an angle expressed
2012 Inductive Automation
709
9.5.5
ceil ceil(number)
Returns the smallest floating point value that is greater than or equal to the argument and is equal to a mathematical integer.
ceil(2.38)
9.5.6
cos cos(number)
Returns the trigonometric cosine of number, which is interpreted as an angle expressed in radians. The results will be a floating point value.
cos(1.89)
9.5.7
exp exp(number)
Returns Euler's number e raised to the power of the argument number, or enumber
exp(5)
9.5.8
floor floor(number)
Returns the largest floating point value that is less than or equal to the argument and is equal to a mathematical integer.
floor(2.72)
9.5.9
log log(number)
Returns the natural logarithm (base e) of a number.
log(28)
710
711
toRadians(180)
9.6
9.6.1
Strings
concat concat(string1, string2, ...)
Concatenates all of the strings passed in as arguments together. Rarely used, as the + operator does the same thing.
concat("The answer is: ", "42")
9.6.2
escapeSQL escapeSQL(string)
Returns the given string with special SQL characters escaped. This is a fairly simplistic function - it just replaces single quotes with two single quotes, and backslashes with two backslashes. See system.db.runPrepUpdate for a much safer way to sanitize user input.
"SELECT * FROM mytable WHERE option = '" + escapeSQL("Jim's Settings") + "'" ... returns SELECT * FROM mytable WHERE option='Jim''s Settings' "SELECT * FROM mytable WHERE option = '" + escapeSQL({Root Container.TextField.text}) + "'"
... returns a query with sanitized user input from a text field.
9.6.3
escapeXML escapeXML(string)
Returns the given string after being escaped to be valid for inclusion in XML. This means replacing XML special characters with their XML entity equivalents.
escapeXML("Use Navigate > PB to get to the Pork&Beans section.")
9.6.4
...returns 4
indexOf("Test", "")
...returns 0
indexOf("Disfunctional", "fun")
...returns 3
712
indexOf("Disfunctional", "marble")
...returns -1
indexOf("banana", "n")
...returns 2
9.6.5
...returns 4
indexOf("Test", "")
...returns 4
indexOf("Disfunctional", "fun")
...returns 3
indexOf("Disfunctional", "marble")
...returns -1
indexOf("banana", "n")
...returns 4
9.6.6
...returns "he"
left("hello", 0)
...returns ""
left("hello", 5)
...returns "hello"
9.6.7
len len(value)
Returns the length of the argument, which may be a string or a dataset. If the argument is a string, it returns the number of characters in the string. If the argument is a dataset, it returns the number of rows in the dataset. Will return zero if the argument is null.
len("Hello World")
... returns 11
713
len({Root Container.Table.data})
9.6.8
lower lower(string)
Takes a string and returns a lower-case version of it.
lower("Hello World")
9.6.9
This table shows some numbers, and the result of using various format strings to format them. Number 5 5 5 123 1024 1337 1337.42 87.32 -1234 -1234 4096 .348 34.8 Example:
numberFormat(34.8, "#0.00'%'")
Pattern 0 0.0 00.0 #,##0 #,##0 #,##0.# #.##0.# #,##0.0000 #,##0 #,##0;(#) 0.###E0 #.00% #0.00'%'
Result 5 5.0 05.0 123 1,024 1,337 1,337.4 87.3200 -1,234 (1,234) 4.096E3 34.80% 34.80%
714
...returns "hellohello"
repeat("hello", 0)
...returns ""
...returns "XandZ"
replace("bob and mary went to bob's house", "bob", "judith")
...returns "lo"
right("filename.pdf", 3)
...returns "pdf"
right("hello", 0)
...returns ""
715
"hello" "world"
split("boo:and:foo", ":")
716
trim(" Goodbye.")
9.7
9.7.1
Type Casting
toBoolean toBoolean(value, [failover])
Tries to convert value to a boolean, according to these rules: 1. If value is a number, 0 is false and anything else is true. 2. If value is a string, then the strings (case insensitive) "on", "true", "t", "yes", "y" are all true. The strings (case insensitive) "off", "false", "f", "no", "n" are considered false. If the string represents a number, the first rule applies. All other strings fail type casting. 3. All other types fail type casting. If type casting fails, an error is thrown, unless the failover argument is specified, in which case it will be used.
toBoolean(1) ... returns true . toBoolean("abc", false) ... returns false
9.7.2
button etched
etchedtitled
717
title; width; lineColor; fontJustification; fontPosition; fontColor; font color; topWidth, leftWidth; bottomWidth; rightWidth title; style; mainColor; bgColor, shadowSize, fontJustification; fontPosition; fontColor; font Styles: 0=Gradient / South-to-North 1=Gradient / West-to-East 2=Gradient / North-to-South 3=Gradient / East-to-West 4=Solid
Other Constants Font Justifications: 1= 2= 3= 4= 5= Left Center Right Leading Trailing Font Positions: 1= 2= 3= 4= 5= 6= Above Top Top Below Top Above Bottom Bottom Below Bottom
Examples:
toBorder("bevel;1010")
... returns
toBorder("matte;red;10;1;1;1")
... returns
toBorder("paneltitled;MyTitle")
... returns
toBorder("paneltitled;Options;1;lightgray;gray;0;;;(0,255,0)")
... returns
9.7.3
718
This function tries to convert value to a color. It assumes that value is a string. If you have integers representing Red, Green, and Blue values see the color expression. The string value is converted to a color according to these rules: 1. If value is a name of a color as defined in the table below, the corresponding color will be returned. Note that color names are case insensitive. 2. If value is a hex color string (with or without a leading "#", the color equivalent of that hex string will be used. Examples: "#FF0000", "556B2F" 3. If value is a list of 3 or 4 integers, a color will be created that uses the first three integers as red, green, and blue values, and the optional fourth integer as an alpha channel value. All values should be between 0 and 255. The list is free-form, any non-digit characters may be used as delimiters between the digits. Examples: "(0,0,0)", "23-99-203", "[255,255,33,127]" For example, all of these expressions return the color red:
toColor("red") toColor("#FF0000") toColor("255,0,0")
You can use the failover parameter to ensure that this expression returns something even if the input string may be bad:
toColor({UserOptions/CustomColor}, "black")
Named Colors AliceBlue AntiqueWhite Aqua Aquamarine Azure Beige Bisque Black BlanchedAlmond Blue BlueViolet Brown BurlyWood CadetBlue Chartreuse Chocolate Clear Coral CornflowerBlue Cornsilk Crimson Cyan DarkBlue DarkCyan DarkGoldenRod DarkGray DarkGreen DarkKhaki DarkMagenta #F0F8FF #FAEBD7 #00FFFF #7FFFD4 #F0FFFF #F5F5DC #FFE4C4 #000000 #FFEBCD #0000FF #8A2BE2 #A52A2A #DEB887 #5F9EA0 #7FFF00 #D2691E (transparent) #FF7F50 #6495ED #FFF8DC #DC143C #00FFFF #00008B #008B8B #B8860B #A9A9A9 #006400 #BDB76B #8B008B
2012 Inductive Automation
719
DarkOliveGreen Darkorange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DimGray DodgerBlue Feldspar FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold GoldenRod Gray Green GreenYellow HoneyDew HotPink IndianRed Indigo Ivory Khaki Lavender LavenderBlush LawnGreen LemonChiffon LightBlue LightCoral LightCyan LightGoldenRodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateBlue LightSlateGray LightSteelBlue LightYellow
2012 Inductive Automation
#556B2F #FF8C00 #9932CC #8B0000 #E9967A #8FBC8F #483D8B #2F4F4F #00CED1 #9400D3 #FF1493 #00BFFF #696969 #1E90FF #D19275 #B22222 #FFFAF0 #228B22 #FF00FF #DCDCDC #F8F8FF #FFD700 #DAA520 #808080 #008000 #ADFF2F #F0FFF0 #FF69B4 #CD5C5C #4B0082 #FFFFF0 #F0E68C #E6E6FA #FFF0F5 #7CFC00 #FFFACD #ADD8E6 #F08080 #E0FFFF #FAFAD2 #90EE90 #D3D3D3 #FFB6C1 #FFA07A #20B2AA #87CEFA #8470FF #778899 #B0C4DE #FFFFE0
720
Lime LimeGreen Linen Magenta Maroon MediumAquaMarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed MidnightBlue MintCream MistyRose Moccasin NavajoWhite Navy OldLace Olive OliveDrab Orange OrangeRed Orchid PaleGoldenRod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip PeachPuff Peru Pink Plum PowderBlue Purple Red RosyBrown RoyalBlue SaddleBrown Salmon SandyBrown SeaGreen SeaShell Sienna Silver SkyBlue SlateBlue SlateGray
#00FF00 #32CD32 #FAF0E6 #FF00FF #800000 #66CDAA #0000CD #BA55D3 #9370D8 #3CB371 #7B68EE #00FA9A #48D1CC #C71585 #191970 #F5FFFA #FFE4E1 #FFE4B5 #FFDEAD #000080 #FDF5E6 #808000 #6B8E23 #FFA500 #FF4500 #DA70D6 #EEE8AA #98FB98 #AFEEEE #D87093 #FFEFD5 #FFDAB9 #CD853F #FFC0CB #DDA0DD #B0E0E6 #800080 #FF0000 #BC8F8F #4169E1 #8B4513 #FA8072 #F4A460 #2E8B57 #FFF5EE #A0522D #C0C0C0 #87CEEB #6A5ACD #708090
2012 Inductive Automation
721
Snow SpringGreen SteelBlue Tan Teal Thistle Tomato Transparent Turquoise Violet VioletRed Wheat White WhiteSmoke Yellow YellowGreen
#FFFAFA #00FF7F #4682B4 #D2B48C #008080 #D8BFD8 #FF6347 #FFFFFF #40E0D0 #EE82EE #D02090 #F5DEB3 #FFFFFF #F5F5F5 #FFFF00 #9ACD32
9.7.4
... coerces the value returned by the a project scripting function into a dataset. See also: DataSets vs PyDataSets
9.7.5
9.7.6
722
... returns the value in the text box as a double, or 0.0 if the value doesn't represent an number.
9.7.7
... returns the value in the text box as a float, or 0.0 if the value doesn't represent an number.
9.7.8
9.7.9
723
toInt("38")
... returns 38
toInt("33.9")
... returns 34
toInt({Root Container.TextField.text}, -1)
... returns the value in the text box as an int, or -1 if the value doesn't represent an number.
... returns 38
toLong("33.9")
... returns 34
toLong({Root Container.TextField.text}, -1)
... returns the value in the text box as an long, or -1 if the value doesn't represent an number.
9.8
9.8.1
Advanced
forceQuality forceQuality(value, [qualityCode])
Returns the given value, but overwrites the quality of that value. If the quality argument is omitted, the
724
quality will be GOOD (192). This is a way to have expressions opt-out of the quality overlay system. You can also force a specific quality code here by including the quality argument.
forceQuality({Tanks/Tank15})
... returns the value of the Tank15 tag, but always with a good quality code.
forceQuality({Tanks/Tank15}, 410)
... returns the value of the Tank15 tag, but always with a TAG_DISABLED quality. See also: Quality Overlays
9.8.2
And then you could use this expression to bind a property value to the weather:
runScript("app.weather.getTempAt('95818')", 15000)
... This would bind a property to the temperature in sunny Sacramento, CA, and would refresh itself every 15 seconds. See also: About Python
725
9.8.3
... returns a Dataset sorted descending on the column named "Column 1".
9.8.4
tag tag(tagPath)
Returns the value of the tag at the path specified. Normally, you'd use the expression language's built-in bound-value syntax to use a tag value in an expression. What makes this function useful is that the path itself can be the result of an expression, meaning it can be dynamic.
tag("Tanks/Tank5")
... returns the value for the tank represented by the dynamic property TankNum on the Root Container. See also: Indirect Tag Binding
727
10
10.1
10.2
system.alert
10.2.1 system.alert.acknowledgeAlert
Description Acknowledges an alert, as specified by a system, path, and stateName. When run in a Client script, the currently logged-in user will be recorded as having acknowledged the alert. When run in a Gateway script, you must provide a username that will be recorded with the acknowledgement, since no user actually acknowledged the alert. Syntax
system.alert.acknowledgeAlert( system, path, stateName)
Parameters String system - The originating system for the alert being acknowledged. String path - The path to the alert being acknowledged. String stateName - The alert state name to acknowledge. Returns
nothing
Scope Client
system.alert.acknowledgeAlert( system, path, stateName, user)
Parameters String system - The originating system for the alert being acknowledged. String path - The path to the alert being acknowledged. String stateName - The alert state name to acknowledge. String user - A username to use for who acknowledged this alert. Only available in the Gateway-scoped version of this function. Returns
nothing
2012 Inductive Automation
728
Scope Gateway Examples This example shows the basic syntax for acknowledging an alert.
system.alert.acknowledgeAlert("SQLTags.default", "[default]Alm_ESTOP", "ALM_STOP")
This code snippet could be used as a mouseReleased event handler on a Table component whose data was the return value of the system.alert.queryAlertStatus function. It would present a right-click menu to acknowledge the currently selected alert.
row = event.source.selectedRow if row != -1: data = event.source.data alertSys = data.getValueAt(row,"System") alertPath = data.getValueAt(row,"Path") alertState = data.getValueAt(row,"State Name") def ack(event, aSys=alertSys, aPath=alertPath, aState=alertState): import system system.alert.acknowledgeAlert(aSys,aPath,aState) menu = system.gui.createPopupMenu({"Acknowledge":ack}) menu.show(event)
10.2.2 system.alert.queryAlertHistory
Description This function queries one of the configured Alert Storage profiles for alert history. The filter arguments help to narrow down the results to alerts that match various criteria, most commonly a range of dates. You can use * to match any number of characters and ? to match a single character in the filter string arguments. The results of this function are a dataset with the following columns: System - The system that issued the alert. Path - The path to the alert item Display Path - The custom display path (if any) for the alert. Will be the Path if no Display Path is configured. State Name - The state name for the alert. Severity - The severity, as a string. Severity Code - The severity as an integer. 0-4, low-high. Active - A boolean indicating whether this alert state is still active. Active Timestamp - The time at which this alert went active. Active Value - The value that triggered this alert to go active. Cleared - A boolean indicating whether this alert has cleared. Cleared Timestamp - The time at which this alert cleared. May be null. Cleared Value - The value that cleared the alert. Acked - A boolean indicating whether or not this alert was been acknowledged. Ack Timestamp - The time that the alert was acknowledged. May be null.
2012 Inductive Automation
729
Ack user - The user who acknowledged the alert. Notes - The notes field for the alert Flags - A bitmask representing the current alert state. 0x01= Active, 0x02=Cleared, 0x04=Acknowledged. So if the alert is active and acknowledged, but not cleared, this will be 0x01 | 0x04 = 5; This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.alert.queryAlertHistory( storageProfile, startDate, endDate, system, path, stateName,
Parameters String storageProfile - The name of the alert storage profile to query. Date startDate - Earliest alert to return. Defaults to 8 hours earlier than current time if omitted. Date endDate - Latest alert to return. Defaults to current time if omitted. String system - Filter string to restrict results based on the alert system. String path - Filter string to restrict results based on the alert path. String stateName - Filter string to restrict results based on the alert state name. Integer minSeverity - Minimum severity to return. Defaults to 0 (Low). Integer maxSeverity - Maximum severity to return. Defaults to 4 (High). Boolean activeAndUnacked - Whether or not to return alerts that are currently active and unacknowledged. Default is true. Boolean activeAndAcked - Whether or not to return alerts that are currently active and have been acknowledged. Default is true. Boolean clearAndUnacked - Whether or not to return alerts that are cleared and unacknowledged. Default is true. Boolean clearAndAcked - Whether or not to return alerts that are cleared and have been acknowledged. Default is true. String sortOrder - The sort order in which to return matching alerts. Either "asc" or "desc", referring to the alert's active timestamp. Default is "desc". String displayPath - Filter string to restrict results based on the alert's display path. Returns Dataset - A dataset containing the historical alert events from the given storage profile that matched the filter and date range arguments. Scope All Examples This code would query an alert storage profile called "DBHistory", looking for the number of unacknowledged alerts in the last 36 hours, displaying the number to the user in a popup message.
from java.util import Date from java.util import Calendar cal = Calendar.getInstance() end = cal.getTime() cal.add(Calendar.HOUR, -36) start = cal.getTime()
730
results = system.alert.queryAlertHistory("DBHistory", start, end, activeAndAcked=0, clearAndAck if results.rowCount > 0: system.gui.messageBox("There are %d un-acked alerts!" % results.rowCount)
10.2.3 system.alert.queryAlertStatus
Description Queries the alerting system for the current status of all alerts. By default, flatten mode is on, which means that you will get a single entry per alert path. If you turn flatten off, you'll get a row for each state of the alert. This can be important for alerts that have overlapping states. The results of this function are a dataset with the following columns: System - The system that issued the alert. Path - The path to the alert item Display Path - The custom display path (if any) for the alert. Will be the Path if no Display Path is configured. State Name - The state name for the alert. If flatten is true, this will be the highest severity active alert state. If no state is active, this will be the most recently cleared alert state. Severity - The severity, as a string. Severity Code - The severity as an integer. 0-4, low-high. Active - A boolean indicating whether this alert state is currently active. Active Timestamp - The time at which this alert went active. May be null. Active Value - The value that triggered this alert to go active. Cleared - A boolean indicating whether this alert is currently clear. Cleared Timestamp - The time at which this alert cleared. May be null. Cleared Value - The value that cleared the alert. Acked - A boolean indicating whether or not this alert has been acknowledged. Ack Timestamp - The time that the alert was acknowledged. May be null. Ack user - The user who acknowledged the alert. Notes - The notes field for the alert Flags - A bitmask representing the current alert state. 0x01= Active, 0x02=Cleared, 0x04=Acknowledged. So if the alert is active and acknowledged, but not cleared, this will be 0x01 | 0x04 = 5; This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.alert.queryAlertStatus( system, path, stateName, minSeverity, maxSeverity,
Parameters String system - Filter string to restrict results based on the alert system. String path - Filter string to restrict results based on the alert path. String stateName - Filter string to restrict results based on the alert state name. Integer minSeverity - Minimum severity to return. Defaults to 0 (Low). Integer maxSeverity - Maximum severity to return. Defaults to 4 (High). Boolean activeAndUnacked - Whether or not to return alerts that are currently active and unacknowledged. Default is true.
731
Boolean activeAndAcked - Whether or not to return alerts that are currently active and have been acknowledged. Default is false. Boolean clearAndUnacked - Whether or not to return alerts that are cleared and unacknowledged. Default is false. Boolean clearAndAcked - Whether or not to return alerts that are cleared and have been acknowledged. Default is false. Boolean flatten - If true, will flatten results so that there is only one entry per alert path, matching the highest active state. Default is true. String displayPath - Filter string to restrict results based on the alert's display path. Returns Dataset - A dataset containing the alerts in the system that match the filters. Scope All Examples This script will query the alert status for currently active alerts and push the results into a table.
results = system.alert.queryAlertStatus(flatten=1,activeAndUnacked=1, activeAndAcked=1) event.source.parent.getComponent("Table").data=results
This expression binding will return the count of currently active alerts with a severity of Medium or higher, checking once a second.
runScript( "system.alert.queryAlertStatus(activeAndAcked=1, minSeverity=2).rowCount", 1000 )
10.3
system.dataset
10.3.1 system.dataset.addRow
Description Takes a dataset and returns a new dataset with a new row added or inserted into it. Datasets are immutable, so it is important to realize that this function does not actually add a row to a dataset. You'll need to do something with the new dataset that this function creates to achieve something useful. If the rowIndex argument is omitted, the row will be appended to the end of the dataset. Syntax
system.dataset.addRow( dataset [, rowIndex], row )
Parameters Dataset dataset - The starting dataset. Please be aware that this dataset will not actually be modified (datasets are immutable), but rather will be the starting point for creating a new dataset. int rowIndex - The index (starting at 0) at which to insert the new row. Will throw an IndexError if less than zero or greater than the length of the dataset. If omitted, the new row will be appended to the end. [optional] PySequence row - A Python sequence representing the data for the new row. Its length must equal the number of columns in the dataset. Returns Dataset - A new dataset with the new row inserted or appended. Scope
2012 Inductive Automation
732
All Examples This example would add a new option to a Dropdown List by adding a row to its underlying dataset. Notice how the last line assigns the return value of the addRow function to the dropdown's data property.
dropdown = event.source.parent.getComponent("Dropdown") newRow = [5, "New Option"] dropdown.data = system.dataset.addRow(dropdown.data, newRow)
This snippet would add a new option into a Dropdown component just like above, but at the beginning:
dropdown = event.source.parent.getComponent("Dropdown") newRow = [5, "New Option"] dropdown.data = system.dataset.addRow(dropdown.data, 0, newRow)
10.3.2 system.dataset.dataSetToExcel
Description Formats the contents of one or more datasets as an excel spreadsheet, returning the results as a string. Each dataset specified will be added as a worksheet in the Excel workbook. This function uses an xml-format for Excel spreadsheets, not the native Excel file format. Syntax
system.dataset.dataSetToExcel( showHeaders, datasets )
Parameters boolean showHeaders - If true (1), the spreadsheet will include a header row. Object[] datasets - A sequence of datasets, one for each sheet in the resulting workbook. Returns String - An Excel-compatible XML-based workbook, with one worksheet per dataset. Scope All Examples This snippet would run a SQL query against a database, and turn the results into a string that is XML that Excel can open. It then writes the string to a file on the local hard drive.
results = system.db.runQuery("SELECT * FROM example1 LIMIT 100") results = system.dataset.toDataSet(results) spreadsheet = system.dataset.dataSetToExcel(1, [results]) filePath = "C:\\output\\results.xls" system.file.writeFile(filePath, spreadsheet)
10.3.3 system.dataset.dataSetToHTML
Description Formats the contents of a dataset as an HTML page, returning the results as a string. Uses the <table> element to create a data table page.
733
Syntax
system.dataset.dataSetToHTML( showHeaders, dataset, title)
Parameters boolean showHeaders - If true(1), the HTML table will include a header row. Dataset dataset - The dataset to export String title - The title for the HTML page. Returns String - The HTML page as a string. Scope All Examples This snippet would run a SQL query against a database, and turn the results into a string containing HTML. It then writes the string to a file on the local hard drive.
results = system.db.runQuery("SELECT * FROM example1 LIMIT 100") results = system.dataset.toDataSet(results) html = system.dataset.dataSetToHTML(1, results, "Production Report") filePath = "C:\\output\\results.html" system.file.writeFile(filePath, html)
10.3.4 system.dataset.deleteRow
Description Takes a dataset and returns a new dataset with a row removed. Datasets are immutable, so it is important to realize that this function does not actually remove the row from the argument dataset. You'll need to do something with the new dataset that this function creates to achieve something useful. Syntax
system.dataset.deleteRow( dataset, rowIndex)
Parameters Dataset dataset - The starting dataset. Please be aware that this dataset will not actually be modified (datasets are immutable), but rather will be the starting point for creating a new dataset. int rowIndex - The index (starting at 0) of the row to delete. Will throw an IndexError if less than zero or greater than len(dataset)-1. Returns Dataset - A new dataset with the specified row removed. Scope All Examples This example would remove the selected row from a List component, by re-assigning the List's data property to the new dataset returned by the deleteRow function.
2012 Inductive Automation
734
myList = event.source.parent.getComponent("List") row = myList.selectedIndex if row != -1: # make sure there is something selected myList.data = system.dataset.deleteRow(myList.data, row)
10.3.5 system.dataset.exportCSV
Description Exports the contents of a dataset as a CSV file, prompting the user to save the file to disk. Syntax
system.dataset.exportCSV( filename, showHeaders, dataset)
Parameters String filename - A suggested filename to save as. boolean showHeaders - If true (1), the CSV file will include a header row. Dataset dataset - The dataset to export. Returns String - The path to the saved file, or None if the action was canceled by the user. Scope Client Examples This snippet would prompt the user to save the data currently displayed in a Table component to a CSV file, and would open the file (in an external program, presumably Excel) after a successful save.
table = event.source.parent.getComponent("Table") filePath = system.dataset.exportCSV("data.csv", 1, table.data) if filePath != None: system.net.openURL("file://"+filePath)
10.3.6 system.dataset.exportExcel
Description Exports the contents of a dataset as an Excel spreadsheet, prompting the user to save the file to disk. Uses the same format as the dataSetToExcel function. Syntax
system.dataset.exportExcel( filename, showHeaders, dataset)
Parameters String filename - A suggested filename to save as. boolean showHeaders - If true (1), the spreadsheet will include a header row. Object[] dataset - A sequence of datasets, one for each sheet in the resulting workbook. Returns String - The path to the saved file, or None if the action was canceled by the user. Scope
2012 Inductive Automation
735
Client Examples This snippet would prompt the user to save the data currently displayed in a Table component to an Excel-compatible spreadsheet file, and would open the file after a successful save.
table = event.source.parent.getComponent("Table") filePath = system.dataset.exportExcel("data.xls", 1, table.data) if filePath != None: system.net.openURL("file://"+filePath)
10.3.7 system.dataset.exportHTML
Description Exports the contents of a dataset to an HTML page. Prompts the user to save the file to disk. Syntax
system.dataset.exportHTML( filename, showHeaders, dataset, title)
Parameters String filename - A suggested filename to save as. boolean showHeaders - If true (1), the HTML tabl will include a header row. Dataset dataset - The dataset to export. String title - The title for the HTML page. Returns String - The path to the saved file, or None if the action was canceled by the user. Scope Client Examples This snippet would prompt the user to save the data currently displayed in a Table component to an HTML file, and would open the file in the default web browser after a successful save.
table = event.source.parent.getComponent("Table") filePath = system.dataset.exportHTML("data.html", 1, table.data,"Production Report") if filePath != None: system.net.openURL("file://"+filePath)
10.3.8 system.dataset.fromCSV
Description Converts a dataset stored in a CSV formatted string to a dataset that can be immediately assignable to a dataset property in your project. Usually this is used in conjunction with system.file. readFileAsString when reading in a CSV file that was exported using system.dataset.exportCSV. The CSV string must be formatted in a specific way:
736
"#NAMES" "Col 1","Col 2","Col 3" "#TYPES" "I","str","D" "#ROWS","6" "44","Test Row 2","1.8713151369491254" "86","Test Row 3","97.4913421614675" "0","Test Row 8","20.39722542161364" "78","Test Row 9","34.57127071614745" "20","Test Row 10","76.41114659745085" "21","Test Row 13","13.880548366871926"
The first line must be "#NAMES" The second line must list the names of the columns of the datset, each in quotes and separated by commas The third line must be "#TYPES" The fourth line must list the type of each column of the dataset in order Integer = "I" String = "str" Double = "D" Date = "date" Long = "L" Short = "S" Float = "F" Boolean = "B" The fifth line must be "#ROWS" followed by a comma and then the number of rows of data in quotes (i.e. "#ROWS", "6") The following lines will be your data, each column value surrounded in quotes and separated by a comma; each row on a separate line. The number of rows must match what was specified on line 5
Syntax
system.dataset.fromCSV( csv)
Parameters String csv - A string holding a CSV dataset. Returns Dataset - A new dataset. Scope All Examples In this example it is assumed that the CSV file being read was a dataset that was previously exported using system.dataset.exportCSV:
#Specify file path file_path = "C:\\my_dataset.csv" #Read in the file as a string data_string = system.file.readFileAsString(file_path) #Convert the string to a dataset and store in a variable data = system.dataset.fromCSV(data_string) #Assign the dataset to a table event.source.parent.getComponent('Table').data = data
737
10.3.9 system.dataset.setValue
Description Takes a dataset and returns a new dataset with a one value altered. Datasets are immutable, so it is important to realize that this function does not actually set a value in the argument dataset. You'll need to do something with the new dataset that this function creates to achieve something useful. Syntax
system.dataset.setValue( dataset, rowIndex, columnIndex, value)
Parameters Dataset dataset - The starting dataset. Will not be modified (datasets are immutable), but acts as the basis for the returned dataset. int rowIndex - The index of the row to set the value at (starting at 0) int columnIndex - The index of the column to set the value at (starting at 0) PyObject value - The new value for the specified row/column. Returns Dataset - A new dataset, with the new value set at the given location. Scope All
system.dataset.setValue( dataset, rowIndex, columnName, value)
Parameters Dataset dataset - The starting dataset. Will not be modified (datasets are immutable), but acts as the basis for the returned dataset. int rowIndex - The index of the row to set the value at (starting at 0) String columnName - The name of the column to set the value at. Case insensitive. PyObject value - The new value for the specified row/column. Returns Dataset - A new dataset, with the new value set at the given location. Scope All Examples This snippet could be used for a Button's actionPerformed event to change the selected cell's value in a Table component to zero.
table = event.source.parent.getComponent("Table") selRow = table.getSelectedRow() selCol = table.getSelectedColumn() if selRow != -1 and selCol != -1: newData = system.dataset.setValue(table.data, selRow, selCol, 0.0) table.data = newData
10.3.10 system.dataset.sort
Syntax
system.dataset.sort( dataset, keyColumn [, ascending])
Parameters
2012 Inductive Automation
738
Dataset dataset - The dataset to sort. String keyColumn - The index or column name of the column to sort on. boolean ascending - True for ascending order, False for descending order. [optional] Returns Dataset - A new sorted dataset. Scope All
system.dataset.sort( dataset, keyColumn [, ascending])
Parameters Dataset dataset - The dataset to sort. int keyColumn - The index or column name of the column to sort on. boolean ascending - True for ascending order, False for descending order. [optional] Returns Dataset - A new sorted dataset. Scope All
10.3.11 system.dataset.toCSV
Syntax
system.dataset.toCSV( dataset, showHeaders, forExport)
Parameters Dataset dataset - The dataset to export to CSV. Boolean showHeaders - If set to true(1), a header row will be present in the CSV. Default is true(1). Boolean forExport - If set to true(1), extra header information will be present in the CSV data which is necessary for the CSV to be compatible with the fromCSV method. Overrides showHeaders. Default is false(0). Returns String - The CSV data as a string Scope All
10.3.12 system.dataset.toDataSet
Description This function is used to 1) convert PyDataSets to DataSets, and 2) create new datasets from raw Python lists. See also: Working with Datatypes / Datasets. Syntax
system.dataset.toDataSet( dataset)
Parameters PyDataSet dataset - A PyDataSet object to convert. Returns Dataset - The newly created dataset.
739
Scope All
system.dataset.toDataSet( headers, data)
Parameters PySequence headers - The column names for the dataset to create. PySequence data - A list of rows for the new dataset. Each row must have the same length as the headers list, and each value in a column must be the same type. Returns Dataset - The newly created dataset. Scope All Examples This first example shows how this function can be used to convert from a PyDataSet (which is what system.db.runQuery returns) to a normal DataSet, which is the datatype of a Table component's data property.
pyDataSet = system.db.runQuery("SELECT * FROM example1 LIMIT 100") table = event.source.parent.getComponent("Table") normalDataSet = system.dataset.toDataSet(pyDataSet) table.data = normalDataSet
This second example shows how to use this function to create a new dataset out of a python sequence that you have filled in. In this case, the sequence is created via a for loop appending rows to a list.
# Generate the Rows rows = [] for x in range(10): oneRow = ["Row %d" % x, x+15] rows.append(oneRow) # Generate the DataSet headers = ["RowID", "Value"] data = system.dataset.toDataSet(headers, rows) # Use our new dataset to fill in a Table table = event.source.parent.getComponent("Table") table.data = data
10.3.13 system.dataset.toPyDataSet
Description This function converts from a normal DataSet to a PyDataSet, which is a wrapper class which makes working with datasets more Python-esque. See also: Working with Datatypes / Datasets. Syntax
system.dataset.toPyDataSet( dataset)
740
Returns PyDataSet - The newly created PyDataSet. Scope All Examples This example script would be added to a button that is in the same container as the table you are working with. It grabs the data of the Table component, and adds up the values in the column named "Value", displaying the result to the user.
# Get a Table component's data table = event.source.parent.getComponent("Table") data = system.dataset.toPyDataSet(table.data) # Loop through the data, summing the Value column value = 0.0 for row in data: value += row["Value"] # Show the user the sum of the Value column system.gui.messageBox("The value is: %f" % value)
10.3.14 system.dataset.updateRow
Description Takes a dataset and returns a new dataset with a one row altered. Datasets are immutable, so it is important to realize that this function does not actually change the row in the argument dataset. You'll need to do something with the new dataset that this function creates to achieve something useful. To alter the row, this function takes a Python dictionary to represent the changes to make to the specified row. The keys in the dictionary are used to find the columns to alter. See also: Sequences and Dictionaries. Syntax
system.dataset.updateRow( dataset, rowIndex, changes )
Parameters Dataset dataset - The starting dataset. Will not be modified (datasets are immutable), but acts as the basis for the returned dataset. int rowIndex - The index of the row to update (starting at 0) PyDictionary changes - A Dictionary of changes to make. They keys in the dictionary should match column names in the dataset, and their values will be used to update the row. Returns Dataset - A new dataset with the values at the specified row updated according to the values in the dictionary. Scope All Examples This example could be used to dynamically change the data that an Easy Chart displays. In this simple example, we assume that the chart is always configured to display a single tank's level. This
2012 Inductive Automation
741
script would update the pen being displayed using a dynamic tank number.
# Generate new tag name and tag path tankNumber = 5 newName = "Tank%d Level" % tankNumber newPath = "Tanks/Tank%d/Level" % tankNumber # Consolidate changes into a dictionary updates = {"NAME": newName, "TAG_PATH":newPath} # Update the Easy Chart chart = event.source.parent.getComponent("Easy Chart") newPens = system.dataset.updateRow(chart.tagPens, 0, updates) chart.tagPens = newPens
10.4
system.db
10.4.1 system.db.beginTransaction
Description Begins a new database transaction. Database transactions are used to execute multiple queries in an atomic fashion. After executing queries, you must either commit the transaction to have your changes take effect, or rollback the transaction which will make all operations since the last commit not take place. The transaction is given a new unique string code, which is then returned. You can then use this code as the tx argument for other system.db.* function calls to execute various types of queries using this transaction. An open transaction consumes one database connection until it is closed. Because leaving connections open indefinitely would exhaust the connection pool, each transaction is given a timeout. Each time the transaction is used, the timeout timer is reset. For example, if you make a transaction with a timeout of one minute, you must use that transaction at least once a minute. If a transaction is detected to have timed out, it will be automatically closed and its transaction id will no longer be valid. Syntax
system.db.beginTransaction( database, isolationLevel, timeout)
Parameters String database - The name of the database connection to create a transaction in. Use "" for the project's default connection. Integer isolationLevel - The transaction isolation level to use. Use one of the four constants: system.db.READ_COMMITTED, system.db.READ_UNCOMMITTED, system.db. REPEATABLE_READ, or system.db.SERIALIZABLE Long timeout - The amount of time, in milliseconds, that this connection is allowed to remain open without being used. Timeout counter is reset any time a query or call is executed against the transaction, or when committed or rolled-back. Returns String - The new transaction ID. You'll use this ID as the "tx" argument for all other calls to have them execute against this transaction. Scope All Examples
2012 Inductive Automation
742
This example would start a transaction with a 5 second timeout against the project's default database, using the default isolation level. Then it executes a series of update calls, and commits and closes the transaction.
txId = system.db.beginTransaction(timeout=5000) status=2
for machineId in range(8): system.db.runPrepUpdate("UPDATE MachineStatus SET status=? WHERE ID=?", args=[status, machin system.db.commitTransaction(txId) system.db.closeTransaction(txId)
10.4.2 system.db.closeTransaction
Description Closes the transaction with the given ID. Note that you must commit or rollback the transaction before you close it. Closing the transaction will return it's database connection to the pool. The transaction ID will no longer be valid. Syntax
system.db.closeTransaction( tx)
Scope All
10.4.3 system.db.commitTransaction
Description Performs a commit for the given transaction. This will make all statements executed against the transaction since its beginning or since the last commit or rollback take effect in the database. Until you commit a transaction, any changes that the transaction makes will not be visible to other connections. Note that if you are done with the transaction, you must close it afterward you commit it. Syntax
system.db.commitTransaction( tx)
Scope All
743
10.4.4 system.db.createSProcCall
Description Creates an SProcCall object, which is a stored procedure call context. This is an object that is used to configure a call to a stored procedure. Once configured, you'd use system.db.execSProcCall to call the stored procedure. The call context object then holds any results from the stored procedure. The SProcCall object has the following functions used for registering parameters: SPRocCall.registerInParam(index OR name, typeCode, value) SPRocCall.registerOutParam(index OR name, typeCode) SPRocCall.registerReturnParam(typeCode) These functions are used to register any in/out parameters for the stored procedure. Parameters can be referenced by index (starting at 1, not 0), or by name. To register an in/out parameter, you simply register it twice - once as an input parameter with the value you'd like to pass to the stored procedure, and once as an output parameter. N.B. not all JDBC drivers support named procedure parameters. If your function returns a value, you must use registerReturnParam to specify the datatype of the returned value. Note that this is different from stored procedures that return a result set, which doesn't require any setup on the SProcCall object. Some database systems call stored procedures that return a value "functions" instead of "procedures". For all of these functions, you'll need to specify a type code. These are codes defined by the JDBC specification. For your convenience, the codes exist as constants in the system.db namespace. Each type code will be mapped to a database-specific type by the JDBC driver. Not all type codes will be recognized by all JDBC drivers. The following type code constants are available: BIT TINYINT SMALLINT INTEGER BIGINT FLOAT REAL DOUBLE NUMERIC DECIMAL CHAR VARCHAR LOGVARCHAR LONGVARBINA BLOB RY DATE NULL CLOB TIME OTHER REF TIMESTAMP BINARY VARBINARY DISTINCT STRUCT ARRAY DATALINK BOOLEAN ROWID NCHAR NVARCHAR LONGNVARCH AR NCLOB SQLXML ORACLE_CURS OR
Once the call context has been executed, you can retrieve the result set, return value, and output parameter values (if applicable) by calling the following functions: SProcCall.getResultSet() - returns a dataset that is the resulting data of the stored procedure, if any. SProcCall.getUpdateCount() - returns the number of rows modified by the stored procedure, or -1 if not applicable. SProcCall.getReturnValue() - returns the return value, if registerReturnParam had been called. SProcCall.getOutParamValue(index OR name) - returns the value of the previously registered out-parameter. Syntax
744
Parameters String procedureName - The named of the stored procedure to call. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the call will be executed in its own transaction. Returns SProcCall - A stored procedure call context, which can be configured and then used as the argument to system.db.execSProcCall. Scope All Examples This example would call a stored procedure named "start_batch" against the current project's default database connection that had no input or output parameters, and did not return any values or results:
call = system.db.createSProcCall("start_batch") system.db.execSProcCall(call)
This example would call a stored procedure "get_shift_workers" with no arguments, which returned a result set of employees for the current shift. It then pushes the resulting dataset into a Table component:
call = system.db.createSProcCall("get_shift_workers") system.db.execSProcCall(call) results = call.getResultSet() table = event.source.parent.getComponent("Table") table.data = results
This example would call a stored procedure that took two arguments, the first an integer and the second a string. It also is configured to return an integer value.
call = system.db.createSProcCall("perform_calculation") call.registerReturnParam(system.db.INTEGER) call.registerInParam(1, system.db.INTEGER, 42) call.registerInParam(2, system.db.VARCHAR, "DC-MODE") system.db.execSProcCall(call) #Print the result to the console print call.getReturnValue()
This example would do the same as the one above, except for a stored procedure that returned its value using an out-parameter. It also uses named argument names instead of indexed arguments.
call = system.db.createSProcCall("perform_calculation") call.registerInParam("arg_one", system.db.INTEGER, 42) call.registerInParam("arg_two", system.db.VARCHAR, "DC-MODE") call.registerOutParam("output_arg", system.db.INTEGER) system.db.execSProcCall(call) #Print the result to the console
745
print call.getOutParamValue("output_arg")
10.4.5 system.db.dateFormat
Description This function is used to format Dates nicely as strings. It uses a format string to guide its formatting behavior. Learn more about date formatting in Working with Datatypes / Dates Expert Tip: This function uses the Java class java.text.SimpleDateFormat internally, and will accept any valid format string for that class. Syntax
system.db.dateFormat( date, formatPattern)
Parameters Date date - The Date object that you'd like to format String formatPattern - A format pattern string to apply. Returns String - The date as a string formatted according to the format pattern. Scope All Examples This example will display a message box on a button press that displays the selected date (without the time) from a Calendar component, in a format like "Feb 3, 2009"
date = event.source.parent.getComponent("Calendar").latchedDate toDisplay = system.db.dateFormat(date, "MMM d, yyyy") system.gui.messageBox("The date you selected is: %s" % toDisplay)
This example would do the same as the one above, but also display the time, in a format like: "Feb 3, 2009 8:01pm"
date = event.source.parent.getComponent("Calendar").latchedDate toDisplay = system.db.dateFormat(date, "MMM d, yyyy") system.gui.messageBox("The date you selected is: %s" % toDisplay)
This example would take two dates from two Popup Calendar components, format them in a manner that the database understands, and then use them in a SQL query to limit the results to a certain date range.
startDate = event.source.parent.getComponent("StartDate").date endDate = event.source.parent.getComponent("EndDate").date startDate = system.db.dateFormat(startDate, "yyyy-MM-dd HH:mm:ss") endDate = system.db.dateFormat(endDate, "yyyy-MM-dd HH:mm:ss") query = "SELECT * FROM mytable WHERE t_stamp >= '%s' AND t_stamp <= '%s'" % (startDate, endDate results = system.db.runQuery(query) event.source.parent.getComponent("Table").data = results
10.4.6 system.db.execSProcCall
Description Executes a stored procedure call. The one parameter to this function is an SProcCall - a stored procedure call context. See the description of system.db.createSProcCall for more information and examples.
746
Syntax
system.db.execSProcCall( callContext)
Parameters SProcCall callContext - A stored procedure call context, with any input, output, and/or return value parameters correctly configured. Use system.db.createSProcCall to create a call context. Returns
nothing
Scope All
10.4.7 system.db.getConnectionInfo
Description Returns a dataset of information about a single database connection, as specified by the name argument. Syntax
system.db.getConnectionInfo( name)
Parameters String name - The name of the database connection to find information about. Returns Dataset - A dataset containing information about the named database connection, or an empty dataset if the connection wasn't found. Scope All
10.4.8 system.db.getConnections
Description Returns a dataset of information about each configured database connection. Each row represents a single connection. Syntax
system.db.getConnections()
Parameters
none
Returns Dataset - A dataset, where each row represents a database connection. Scope All
10.4.9 system.db.refresh
Description
2012 Inductive Automation
747
This function will programmatically cause a SQL Query or DB Browse property binding to execute immediately. This is most often used for bindings that are set to Polling - Off. In this way, you cause a binding to execute on demand, when you know that the results of it's query will return a new result. To use it, you simply specify the component and name of the property on whose binding you'd like to refresh. Syntax
system.db.refresh( component, propertyName)
Parameters JComponent component - The component whose property you want to refresh String propertyName - The name of the property that has a SQL Query binding that needs to be refreshed Returns boolean - True (1) if the property was found and refreshed successfully. Scope Client Examples This example could be placed in the actionPerformed event of a Button, to be used to refresh the data of a Table. Remember to use the scripting name of the property that you're trying to refresh, and that the property names are case-sensitive.
table = event.source.parent.getComponent("Table") system.db.refresh(table, "data")
10.4.10 system.db.rollbackTransaction
Description Performs a rollback on the given connection. This will make all statements executed against this transaction since its beginning or since the last commit or rollback undone. Note that if you are done with the transaction, you must also close it afterward you do a rollback on it. Syntax
system.db.rollbackTransaction( tx)
Scope All
10.4.11 system.db.runPrepQuery
Description Runs a prepared statement against the database, returning the results in a PyDataSet.. Prepared statements differ from regular queries in that they can use a special placeholder, the question-mark character (?) in the query where any dynamic arguments would go, and then use an array of values to provide real information for those arguments. Make sure that the length of your argument array
748
matches the number of question-mark placeholders in your query. This call should be used for SELECT queries. This is a useful alternative to system.db.runQuery because it allows values in the WHERE clause, JOIN clause, and other clauses to be specified without having to turn those values into strings. This is safer because it protects against a problem known as a SQL injection attack, where a user can input data that affects the query's semantics. Syntax
system.db.runPrepQuery( query, args, database, tx)
Parameters String query - A query (typically a SELECT) to run as a prepared statement, with placeholders (?) denoting where the arguments go. Object[] args - A list of arguments. Will be used in order to match each placeholder (?) found in the query. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the query will be executed in its own transaction. Returns PyDataSet - The results of the query as a PyDataSet Scope All Examples This example would search for all records in a LogEntry table where the message contained a userentered search term.
search = event.source.parent.getComponent("SearchFor").text # Wrap the term in % signs for LIKE-style matching search = '%' + search + '%' results= system.db.runPrepQuery("SELECT * FROM LogEntry WHERE EntryText LIKE ?", [search]) event.source.parent.getComponent("Table").data = results
10.4.12 system.db.runPrepUpdate
Description Runs a prepared statement against the database, returning the number of rows that were affected. Prepared statements differ from regular queries in that they can use a special placeholder, the question-mark character (?) in the query where any dynamic arguments would go, and then use an array of values to provide real information for those arguments. Make sure that the length of your argument array matches the number of question-mark placeholders in your query. This call should be used for UPDATE, INSERT, and DELETE queries. This is extremely useful for two purposes: 1. This method avoids the problematic technique of concatenating user input inside of a query, which can lead to syntax errors, or worse, a nasty security problem called a SQL injection attack. For example, if you have a user-supplied string that is used in a WHERE clause, you use singlequotes to enclose the string to make the query valid. What happens in the user has a single-quote in their text? Your query will fail. Prepared statements are immune to this problem.
2012 Inductive Automation
749
2. This is the only way to write an INSERT or UPDATE query that has binary or BLOB data. Using BLOBs can be very hand for storing images or reports in the database, where all clients have access to them. Syntax
system.db.runPrepUpdate( query, args, database, tx, getKey)
Parameters String query - A query (typically an UPDATE, INSERT, or DELETE) to run as a prepared statement, with placeholders (?) denoting where the arguments go. Object[] args - A list of arguments. Will be used in order to match each placeholder (?) found in the query. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the update will be executed in its own transaction. Boolean getKey - A flag indicating whether or not the result should be the number of rows returned (getKey=0) or the newly generated key value that was created as a result of the update (getKey=1). Not all databases support automatic retrieval of generated keys. Returns Integer - The number of rows affected by the query, or the key value that was generated, depending on the value of the getKey flag. Scope All Examples This example would gather some user entered text and insert it into the database.
userText = event.source.parent.getComponent("TextArea").text userName = system.security.getUsername() system.db.runPrepUpdate("INSERT INTO Comments (Name, UserComment) VALUES (?,?)", [userName, use
This example inserts a new user and gives it the 'admin' role. Demonstrates the ability to retrieve a newly created key value.
#get the username/password name = event.source.parent.getComponent('Name').text desc = event.source.parent.getComponent('Description').text building = event.source.parent.getComponent('Building').selectedValue #insert the value id = system.db.runPrepUpdate("INSERT INTO machines (machine_name, description) VALUES (?, ?)",
#add a row to the user role mapping table system.db.runPrepUpdate("INSERT INTO machine_building_mapping (machine_id, building) VALUES (?,
750
10.4.13 system.db.runQuery
Description Runs a SQL query, usually a SELECT query, against a database, returning the results as a dataset. If no database is specified, or the database is the empty-string "", then the current project's default database connection will be used. The results are returned as a PyDataSet, which is a wrapper around the standard dataset that is convenient for scripting. See also: Working with Datatypes / Datasets. Syntax
system.db.runQuery( query, database, tx)
Parameters String query - A SQL query, usually a SELECT query, to run. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the query will be executed in its own transaction. Returns PyDataSet - The results of the query as a PyDataSet. Scope All Examples Assuming the following dataset: I Va D lu e 0 3. 55 1 67 .2 2 9. 87 If you executed the following code:
table = system.db.runQuery("SELECT * FROM TEST") then table[2] would access the third row (rows are zero-indexed), and both table[2][0] and table[2]["ID"] would access the ID value of the third row. As further example of how to use the
results of runQuery, here are seven different ways to print out the table, and their results follow. Note that some of the later methods exercise some more advanced Jython concepts such as list comprehensions and string formatting, but their intent should be obvious. Generally speaking, the more concise Jython code becomes, the more readable it is.
table = system.db.runQuery("SELECT * FROM Test")
751
print "Printing TEST Method 1..." for row in table: for col in row: print col, print "" print "" print "Printing TEST Method 2..." for row in table: print row[0], row[1] print "" print "Printing TEST Method 3..." for row in table: print row["ID"], row["VALUE"] print "" print "Printing TEST Method 4..." for rowIdx in range(len(table)): print "Row ",str(rowIdx)+": ", table[rowIdx][0], table[rowIdx][1] print "" print "Printing TEST Method 5..." print [str(row[0])+", "+ str(row[1]) for row in table] print "" print "Printing TEST Method 6..." print ["%s, %s" % (row["ID"],row["VALUE"]) for row in table] print "" print "Printing TEST Method 7..." print [[col for col in row] for row in table] print ""
The results printed out would be: Printing TEST Method 1... 0 3.55 1 67.2 2 9.87 Printing TEST Method 2... 0 3.55 1 67.2 2 9.87 Printing TEST Method 3... 0 3.55 1 67.2 2 9.87 Printing Row 0: 0 Row 1: 1 Row 2: 2 TEST Method 4... 3.55 67.2 9.87
752
Printing TEST Method 5... ['0, 3.55', '1, 67.2', '2, 9.87'] Printing TEST Method 6... ['0, 3.55', '1, 67.2', '2, 9.87'] Printing TEST Method 7... [[0, 3.55], [1, 67.2], [2, 9.87]]
10.4.14 system.db.runScalarQuery
Description Runs a query against a database connection just like the runQuery function, but only returns the value from the first row and column. If no results are returned from the query, the special value None is returned. Syntax
system.db.runScalarQuery( query, database, tx)
Parameters String query - A SQL query that should be designed to return one row and one column. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the query will be executed in its own transaction. Returns Object - The value from the first row and first column of the results. Returns None if no rows were returned. Scope All Examples Example 1: # This code would count the number of active alarms, and acknowledge them all if there is at least one.
numAlarms = system.db.runScalarQuery("SELECT COUNT(*) FROM alarmstatus WHERE unacknowledged = 1 if numAlarms > 0: # There are alarms - acknowledge all of them system.db.runUpdateQuery("UPDATE alarmstatus SET unacknowledged = 0")
Example 2: This code would read a single value from a table and show it to the user an a popup box.
lakeLevel = system.db.runScalarQuery("SELECT Level FROM LakeInfo WHERE LakeId='Tahoe'") system.gui.messageBox("The lake level is: %d feet" % lakeLevel)
10.4.15 system.db.runUpdateQuery
Description
2012 Inductive Automation
753
Runs a query against a database connection, returning the number of rows affected. Typically this is an UPDATE, INSERT, or DELETE query. If no database is specified, or the database is the emptystring "", then the current project's default database connection will be used. Note that you may want to use the runPrepUpdate query if your query is constructed with user input (to avoid the user's input from breaking your syntax) or if you need to insert binary or BLOB data. Syntax
system.db.runUpdateQuery( query, database, tx, getKey)
Parameters String query - A SQL query, usually an INSERT, UPDATE, or DELETE query, to run. String database - The name of the database connection to execute against. If omitted or "", the project's default database connection will be used. String tx - A transaction identifier. If omitted, the update will be executed in its own transaction. Boolean getKey - A flag indicating whether or not the result should be the number of rows returned (getKey=0) or the newly generated key value that was created as a result of the update (getKey=1). Not all databases support automatic retrieval of generated keys. Returns Integer - The number of rows affected by the query, or the key value that was generated, depending on the value of the getKey flag. Scope All Examples This code would acknowledge all unacknowledged alarms # and show the user how many alarms were acknowledged.
rowsChanged = system.db.runUpdateQuery("UPDATE alarmstatus SET unacknowledged = 0") system.gui.messageBox("Acknowledged %d alarms" % rowsChanged)
This code would insert a new recipe step into a recipe table, after asking the user how many gallons of syrup should be added on this recipe step.
inputText = system.db.inputBox("How many gallons?", "12.3") # Make sure the user didn't hit cancel if inputText != None: # Make sure the input is a number gallons = float(inputText) # Detect the next step number by adding 1 to the last step number nextStepNum = system.db.runScalarQuery("SELECT MAX(StepNum) + 1 FROM RecipeSteps") # Insert recipe step system.db.runUpdateQuery("INSERT INTO RecipeSteps (StepNum, Gallons) VALUES (%d, %f)" % (nex
This example inserts a new user and gives it the 'admin' role. Demonstrates the ability to retrieve a newly created key value.
754
#insert the value id = system.db.runUpdateQuery("INSERT INTO machines (machine_name, description) VALUES ('%s', '
#add a row to the user role mapping table system.db.runUpdateQuery("INSERT INTO machine_building_mapping (machine_id, building) VALUES (%
10.5
system.file
10.5.1 system.file.fileExists
Description Checks to see if a file at a given path exists. Syntax
system.file.fileExists( filepath)
Parameters String filepath - The path of the file to check. Returns boolean - True (1) if the file exists, false (0) otherwise. Scope All Examples This basic example shows how the fileExists function is used in its simplest form:
if system.file.fileExists("C:\\temp_file.txt"): system.gui.messageBox("Yes, the file exists") else: system.gui.messageBox("No, it doesn't exist")
This code uses the fileExists function, along with other system.file.* functions, to prompt the user to confirm that they want to overwrite an existing file.
filename = system.file.saveFile(name) if filename != None: reallyWrite = 1 if system.file.fileExists(filename): reallyWrite = system.gui.confirm("File '%s' already exists. Overwrite?" % filename) if reallyWrite: system.file.writeFile(filename, "This will be the contents of my new file")
10.5.2 system.file.getTempFile
Description Creates a new temp file on the host machine with a certain extension, returning the path to the file. The file is marked to be removed when the Java VM exits. Syntax
755
system.file.getTempFile( extension)
Parameters String extension - An extension, like ".txt", to append to the end of the temporary file. Returns String - The path to the newly created temp file. Scope All Examples This code writes some data to a temorary file, and then opens that file. Assume that the data variable holds the contents of an excel (xls) file.
filename = system.file.getTempFile("xls") system.file.writeFile(filename, data) system.net.openURL("file://" + filename)
10.5.3 system.file.openFile
Description Shows an "Open File" dialog box, prompting the user to choose a file to open. Returns the path to the file that the user chose, or None if the user canceled the dialog box. An extension can optionally be passed in that sets the filetype filter to that extension. Syntax
system.file.openFile( [extension])
Parameters String extension - A file extension, like "pdf", to try to open. [optional] Returns String - The path to the selected file, or None if canceled. Scope Client Examples This code would prompt the user to open a file of type 'gif'. If None is returned, it means the user canceled the open dialog box.
path = system.db.openFile('gif') if path != None: # do something with the file
10.5.4 system.file.readFileAsBytes
Description Opens the file found at path filename, and reads the entire file. Returns the file as an array of bytes. Commonly this array of bytes is uploaded to a database table with a column of type BLOB (Binary Large OBject). This upload would be done through an INSERT or UPDATE SQL statement run through the system.db.runPrepUpdate function. You could also write the bytes to another file using the system.file.writeFile function, or send the bytes as an email attachment using
2012 Inductive Automation
756
system.net.sendEmail. Syntax
system.file.readFileAsBytes( filepath)
Parameters String filepath - The path of the file to read. Returns byte[] - The contents of the file as an array of bytes. Scope All Examples This code would prompt the user to choose a file. If the user chooses a file, it would then read that file and upload it to a database table called Files into a BLOB column called file_data.
path = system.file.openFile() if path != None: bytes = system.file.readFileAsBytes(filename) system.db.runPrepUpdate("INSERT INTO Files (file_data) VALUES (?)", (bytes))
10.5.5 system.file.readFileAsString
Description Opens the file found at path filename, and reads the entire file. Returns the file as a string. Common things to do with this string would be to load it into the text property of a component, upload it to a database table, or save it to another file using system.file.writeFile function. Syntax
system.file.readFileAsString( filepath)
Parameters String filepath - The path of the file to read. Returns String - The contents of the file as a string. Scope All Examples This code would prompt the user to choose a text file. If the user chooses a file, it would then set a text area on the screen to display the file.
path = system.file.openFile("txt") if path != None: contents = system.file.readFileAsString(path) event.source.parent.getComponent("Text Area").text = contents
757
10.5.6 system.file.saveFile
Description Prompts the user to save a new file named filename. The optional extension and typeDesc arguments will be used for a file type filter, if any. If the user accepts the save, the path to that file will be returned. If the user cancels the save, None will be returned. Syntax
system.file.saveFile( filename [, extension] [, typeDesc])
Parameters String filename - A file name to suggest to the user. String extension - The appropriate file extension, like "jpeg", for the file. [optional] String typeDesc - A description of the extension, ilke "JPEG Image" [optional] Returns String - The path to the file that the user decided to save to, or None if they canceled. Scope Client Examples This code would prompt the user to save the text in a text area to a file.
path = system.file.saveFile("myfile.txt") if path != None: system.file.writeFile(path, event.source.parent.getComponent("Text Area").text)
10.5.7 system.file.writeFile
Description Writes the given data to the file at file path filename. If the file exists, the append argument determines whether or not it is overwritten (the default) or appended to. The data argument can be either a string or an array of bytes (commonly retrieved from a BLOB in a database or read from another file using system.file.readFileAsBytes). Syntax
system.file.writeFile( filepath, charData [, append])
Parameters String filepath - The path of the file to write to. String charData - The character content to write to the file. boolean append - If true(1), the file will be appended to if it already exists. If false(0), the file will be overwritten if it exists. The default is false(0). [optional] Returns
nothing
Scope All
system.file.writeFile( filepath, data [, append])
758
Parameters String filepath - The path of the file to write to. byte[] data - The binary content to write to the file. boolean append - If true(1), the file will be appended to if it already exists. If false(0), the file will be overwritten if it exists. The default is false(0). [optional] Returns
nothing
Scope All Examples Example 1: This code would download a BLOB from a database and save it to a file.
resultset = system.db.runQuery("SELECT file_data FROM Files WHERE id=12") if len(rs) > 0: # if the query returned anything... data = rs[0][0] # grab the BLOB at the 0th row and 0th column filename = system.file.saveFile("MyDownloadedFile.xyz") if filename != None: system.file.writeFile(filename, data)
Example 2: This code would write the contents of a text area to a file.
data = event.source.parent.getComponent("Text Area").text filename = system.file.saveFile("MyDownloadedFile.txt") if filename != None: system.file.writeFile(filename, data)
10.6
system.gui
10.6.1 system.gui.chooseColor
Description Prompts the user to pick a color using the default color-chooser dialog box. Syntax
system.gui.chooseColor( initialColor [, dialogTitle])
Parameters Color initialColor - A color to use as a starting point in the color choosing popup. String dialogTitle - The title for the color choosing popup. Defaults to "Choose Color"
[optional]
Returns Color - The new color chosen by the user. Scope Client
759
Examples This code would be placed in the actionPerformed event of a button, and would change the background color of the container the button was placed in.
parent = event.source.parent newColor = system.gui.chooseColor(parent.background) parent.background = newColor
10.6.2 system.gui.color
Description Creates a new color object, either by parsing a string or by having the RGB[A] channels specified explicitly. Syntax
system.gui.color( color)
Parameters String color - A string that will be coerced into a color. Can accept many formats, such as "red" or "#FF0000" or "255,0,0" Returns Color - The newly created color. Scope Client
system.gui.color( red, green, blue [, alpha])
Parameters int red - The red component of the color, an integer 0-255. int green - The green component of the color, an integer 0-255. int blue - The blue component of the color, an integer 0-255. int alpha - The alpha component of the color, an integer 0-255. [optional] Returns Color - The newly created color. Scope Client Examples This example changes the background color of a component to red.
myComponent = event.source myComponent.background = fpmi.gui.color(255,0,0) # turn the component red
10.6.3 system.gui.confirm
Description Displays a confirmation dialog box to the user with "Yes" and "No" options, and a custom message. Syntax
760
Parameters String message - The message to show in the confirmation dialog. String title - The title for the confirmation dialog. [optional] Returns boolean - True (1) if the user selected "Yes", false (0) if the user selected "No" Scope Client Examples By using the confirm function in an if statement, we can let the user confirm an action. In this case, we shut down the plaint if the user confirms it, otherwise, we don't do anything.
if system.gui.confirm("Are you sure you want to shutdown the plant?", "Really Shutdown?"): system.db.runUpdateQuery("UPDATE ControlTable SET Shutdown=1")
10.6.4 system.gui.convertPointToScreen
Description Converts a pair of coordinates that are relative to the upper-left corner of some component to be relative to the upper-left corner of the entire screen. Syntax
system.gui.convertPointToScreen( x, y, event)
Parameters int x - The X-coordinate, relative to the component that fired the event. int y - The Y-coordinate, relative to the component that fired the event. EventObject event - An event object for a component event. Returns PyTuple - A tuple of (x,y) in screen coordinates. Scope Client Examples This example will get the coordinates where the mouse is (from the corner of the monitor) and display them in a label.
#get the screen coordinates of the pointer and write them to a label coords = system.gui.convertPointToScreen(event.x,event.y,event) event.source.parent.getComponent('Label').text = "x: %s y: %s" %(coords[0], coords[1])
10.6.5 system.gui.createPopupMenu
Description Creates a new popup menu, which can then be shown over a component on a mouse event. To use this function, first create a Python sequence whose entries are strings, and another sequence
2012 Inductive Automation
761
whose entries are function objects. The strings will be the items that are displayed in your popup menu, and when an item is clicked, its corresponding function will be run. Your functions must accept an event object as an argument. See also: Functions To show the popup menu, store the menu object that this function returns, and then call its show (event) function, where event is the event object for a mousePressed or mouseReleased event on the component you wish the popup menu to be shown on. Best Practices. It is best to have the menu object created only once via an application specific library function. Then, call the show(event) function on both the mousePressed and mouseReleased events on your component. The reason for this is that different operating systems (Windows, Linux, MacOS) differ in when they like to show the popup menu. The show(event) function detects when the right time is to show itself, either on mouse press or release. See the examples for more. Syntax
system.gui.createPopupMenu( itemsDict)
Parameters PyDictionary itemsDict - A dictionary of String:Function keys to create the popup menu. You can create sub-menus by using a nested dictionary of the same type as a dictionary value. Returns JPopupMenu - The javax.swing.JPopupMenu that was created. Scope Client
system.gui.createPopupMenu( itemNames, itemFunctions )
Parameters PySequence itemNames - A list of names to create popup menu items with. PySequence itemFunctions - A list of functions to match up with the names. Returns JPopupMenu - The javax.swing.JPopupMenu that was created. Scope Client Examples This first example is a very basic to demonstrate the fundamentals of making a popup menu. Put the following script in the mouseReleased event of a component. This will only work on Windows continue on for cross-platform instructions.
def sayHello(event): import system system.gui.messageBox("Hello World") menu = system.gui.createPopupMenu({"Click Me":sayHello}) menu.show(event)
Because of the different popup-trigger settings on different operating systems, the preceding code will probably fail on Linux or a Mac. The way around this is to do the same code in both the mousePressed and mouseReleased events. In order to avoid code duplication, you'll want to factor out the code into a project script module.
762
The following, more sophisticated example shows a popup menu being used to acknowledge alarms in an alarm table by right-clicking on the table, and choosing either to acknowledge the selected alarm or all alarms. You would put this script in a project script module called app.util:
def getAlarmPopup(): import system,app # This function will be the "Acknowledge" entry in the popup menu def ack(event): import system,app table = event.source selRow = table.selectedRow if selRow == -1: system.gui.warningBox("No alarm selected") elif table.model.getValueAt(selRow, 0) == 0: # In my table, the first column is the alarm's unacknowledged bit. system.gui.warningBox("Alarm already acknowledged") else: desc = table.model.getValueAt(selRow, 1) path = table.model.getValueAt(selRow, 2) message = "<html>Are you sure you want to acknowledge<br>%s?" % desc if system.gui.confirm(message,"Confirm"): app.auth.ackAlarm(desc,path) table.setSelectedRow(-1) # This function will be the "Acknowledge All" entry in the popup menu def ackAll(event): import system,app if system.gui.confirm("Are you sure you want to acknowledge all alarms?","Confirm"): app.auth.ackAllAlarms(event)
# Finally, create the actual popup menu and return it alarmPopup = system.gui.createPopupMenu(["Acknowledge Alarm", "Acknowledge All"],[ack, ackAl return alarmPopup
Now you could simply put this code in the Table's mousePressed and mouseReleased events:
menu = app.util.getAlarmPopup() menu.show(event)
10.6.6 system.gui.errorBox
Description Displays an error-style message box to the user. Syntax
system.gui.errorBox( message [, title])
Parameters String message - The message to display in an error box. String title - The title for the error box. [optional] Returns
nothing
Scope Client
763
Examples Turn on compressor #12, but only if the user has the right credentials.
if 'Supervisor' in system.security.getRoles(): system.db.runUpdateQuery("UPDATE CompressorControl SET running=1 WHERE compNum = 12") else: system.gui.errorBox("Unable to turn on Compressor 12. You don't have proper security privil
10.6.7 system.gui.findWindow
Description Finds and returns a list of windows with the given path. If the window is not open, an empty list will be returned. Useful for finding all instances of an open window that were opened with system.gui. openWindowInstance Syntax
system.gui.findWindow( path)
Parameters String path - The path of the window to search for Returns List - A list of window objects. May be empty if window is not open, or have more than one entry if multiple windows are open. Scope Client Examples This example finds all of the open instances of the window named "Popup" and closes them all.
allInstances = system.gui.findWindow("Popup") for window in allInstances: system.nav.closeWindow(window)
10.6.8 system.gui.getOpenedWindowNames
Description Finds all of the currently open windows, returning a tuple of their paths. Syntax
system.gui.getOpenedWindowNames()
Parameters
none
Returns PyTuple - A tuple of strings, representing the path of each window that is open. Scope
2012 Inductive Automation
764
Client Examples This example prints out into the console the full path for each opened window.
windows = system.gui.getOpenedWindowNames() print 'There are %d windows open' % len(windows) for path in windows: print path
10.6.9 system.gui.getOpenedWindows
Description Finds all of the currently open windows, returning a tuple of references to them. Syntax
system.gui.getOpenedWindows()
Parameters
none
Returns PyTuple - A tuple of the opened windows. Not their names, but the actual window objects themselves. Scope Client Examples This example prints out the path of each currently opened window to the console.
windows = system.gui.getOpenedWindows() print 'There are %d windows open' % len(windows) for window in windows: print window.getPath()
10.6.10 system.gui.getParentWindow
Description Finds the parent (enclosing) window for the component that fired an event, returning a reference to it. Syntax
system.gui.getParentWindow( event)
Parameters EventObject event - A component event object. Returns PyObject - The window that contains the component that fired the event. Scope Client Examples Use this in an event script to change the window's title.
765
10.6.11 system.gui.getSibling
Description Given a component event object, looks up a sibling component. Shortcut for event.source. parent.getComponent("siblingName"). If no such sibling is found, the special value None is returned. Syntax
system.gui.getSibling( event, name)
Parameters EventObject event - A component event object. String name - The name of the sibling component. Returns PyObject - The sibling component itself. Scope Client Examples This example will get it's sibling Text Field's text, and use it.
textField = system.gui.getSibling(event, 'TextField (1)') if textField is None: system.gui.errorBox("There is no text field!") else: system.gui.messageBox("You typed: %s" % textField.text)
10.6.12 system.gui.getWindow
Description Finds a reference to an open window with the given name. Throws a ValueError if the named window is not open or not found. Syntax
system.gui.getWindow( name)
Parameters String name - The path to the window to field. Returns PyObject - A reference to the window, if it was open. Scope Client Examples Example 1:
766
This example will get the window named 'Overview' and then close it.
try: window = system.gui.getWindow('Overview') system.gui.closeWindow(window) except ValueError: system.gui.warningBox("The Overview window isn't open")
Example 2: This example will set a value on a label component in the 'Header' window.
try: window = system.gui.getWindow('Header') window.getRootContainer().getComponent('Label').text = "Machine 1 Starting" except ValueError: system.gui.warningBox("The Header window isn't open")
10.6.13 system.gui.getWindowNames
Description Returns a list of the paths of all windows in the current project, sorted alphabetically. Syntax
system.gui.getWindowNames()
Parameters
none
Returns PyTuple - A tuple of strings, representing the path of each window defined in the current project. Scope Client Examples This example would open windows that begin with "Motor" and pass in the currently selected motor number.
motor = event.source.parent.number windows = system.gui.getWindowNames() for path in windows: if name[:5] == "Motor": system.gui.openWindow(path, {"motorNumber":motor})
10.6.14 system.gui.inputBox
Description Opens up a popup input dialog box. This dialog box will show a prompt message, and allow the user to type in a string. When the user is done, they can press "OK" or "Cancel". If OK is pressed, this function will return with the value that they typed in. If Cancel is pressed, this function will return the value None.
767
Syntax
system.gui.inputBox( message, defaultText)
Parameters String message - The message to display for the input box. String defaultText - The default text to initialize the input box with. Returns String - The string value that was entered in the input box. Scope Client Examples This could go in the mouseClicked event of a label to allow the user to change the label's text.
txt = system.gui.inputBox("Enter text:", event.source.text) if txt != None: event.source.text = txt
10.6.15 system.gui.isTouchscreenModeEnabled
Description Checks whether or not the running client's touchscreen mode is currently enabled. Syntax
system.gui.isTouchscreenModeEnabled()
Parameters
none
Returns boolean - True(1) if the client currently has touchscreen mode activated. Scope Client Examples This example should be used in the Client Startup Script to check if this client is being run on a touch screen computer (judged by an IP address) and set touchscreen mode.
ipAddress = system.net.getIpAddress() isTouchscreen = system.db.runScalarQuery("SELECT COUNT(*) FROM touchscreen_computer_ips WHERE i if isTouchscreen and not system.gui.isTouchscreenModeEnabled(): system.gui.setTouchscreenModeEnabled(1)
10.6.16 system.gui.messageBox
Description Displays an informational-style message popup box to the user.
2012 Inductive Automation
768
Syntax
system.gui.messageBox( message [, title])
Parameters String message - The message to display. String title - A title for the message box. [optional] Returns
nothing
Scope Client Examples This example will show how many hours a motor has been running when it is clicked.
# get the motor number motorNumber = event.source.getPropertyValue('MotorNumber') # retrieve the hours running from the database hours = system.db.runScalarQuery("SELECT HoursRunning FROM MotorStatus WHERE motor=%d" % motorN system.gui.messageBox("The motor has been running for %d hours" % motorNumber)
10.6.17 system.gui.moveComponent
Description Alter's a components position to a new pair of coordinates, (x,y), a point relative to the upper-left corner of the component's parent. Note that when using relative layout, these coordinates are evaluated as if the component's size was the same size as the last time the component was saved in the Designer. This effectively means that your argument coordinates will automatically scale with relative layout. Syntax
system.gui.moveComponent( component, x, y)
Parameters JComponent component - The component to move. int x - The x-coordinate to move to, relative to the upper-left corner of the component's parent container. int y - The y-coordinate to move to, relative to the upper-left corner of the component's parent container. Returns
nothing
Scope Client Examples This code would go in a Timer's propertyChange script for animation.
769
10.6.18 system.gui.passwordBox
Description Pops up a special input box that uses a password field, so the text isn't echoed back in clear-text to the user. Returns the text they entered, or None if they canceled the dialog box. Syntax
system.gui.passwordBox( message [, title] [, echoChar])
Parameters String message - The message for the password prompt. String title - A title for the password prompt. [optional] String echoChar - A custom echo character. Defaults to: * [optional] Returns String - The password that was entered, or None if the prompt was canceled. Scope Client Examples This example would prompt a user for a password before opening the 'Admin' Screen.
password = system.gui.passwordBox("Please enter the password.") if password == "open sesame": system.nav.openWindow("Admin")
10.6.19 system.gui.reshapeComponent
Description Sets a component's position and size at runtime. The coordinates work in the same way as the system.gui.moveComponent function. Syntax
system.gui.reshapeComponent( component, x, y, width, height)
Parameters JComponent component - The component to move and resize int x - The x-coordinate to move to, relative to the upper-left corner of the component's parent container. int y - The y-coordinate to move to, relative to the upper-left corner of the component's parent container.
770
int width - The new width for the component int height - The new height for the component Returns
nothing
Scope Client Examples This code would go in a Timer's propertyChange script for animation.
if event.propertyName == "value": newX = event.newValue; newWidth = int(event.newValue*1.5) rect = event.source.parent.getComponent("Rectangle") system.gui.reshapeComponent(rect, newX, 150, newWidth, 80)
10.6.20 system.gui.resizeComponent
Description Sets a component's size at runtime. The coordinates work in the same way as the system.gui. moveComponent function. Syntax
system.gui.resizeComponent( component, width, height)
Parameters JComponent component - The component to resize int width - The new width for the component int height - The new height for the component Returns
nothing
Scope Client Examples This code would go in a Timer's propertyChange script for animation \
if event.propertyName == "value": newWidth = event.newValue; rect = event.source.parent.getComponent("Rectangle") system.gui.resizeComponent(newWidth, 80)
771
10.6.21 system.gui.setTouchscreenModeEnabled
Description Alters a running client's touchscreen mode on the fly. Syntax
system.gui.setTouchscreenModeEnabled( enabled)
Parameters boolean enabled - The new value for touchscreen mode being enabled. Returns
nothing
Scope Client Examples This example could be used on an input heavy window's internalFrameActivated event to remove touch screen mode.
if system.gui.isTouchscreenModeEnabled(): system.gui.setTouchscreenModeEnabled(0)
10.6.22 system.gui.showNumericKeypad
Description Displays a modal on-screen numeric keypad, allowing for arbitrary numeric entry using the mouse, or a finger on a touchscreen monitor. Returns the number that the user entered. Syntax
system.gui.showNumericKeypad( initialValue [, fontSize])
Parameters Number initialValue - The value to start the on-screen keypad with. int fontSize - The font size to display in the keypad. [optional] Returns Number - The value that was entered in the keypad. Scope Client Examples This function is a holdover for backwards compatibility. Input components now know when the client is in touchscreen mode and respond accordingly. This script would go in the MouseClicked or MousePressed action of a Text Field or Numeric Text Field.
772
# For Integer Numeric Text Field: if system.gui.isTouchscreenModeEnabled(): event.source.intValue = system.gui.showNumericKeypad(event.source.intValue) # For Double Numeric Text Field: if system.gui.isTouchscreenModeEnabled(): event.source.doubleValue = system.gui.showNumericKeypad(event.source.doubleValue) # For Text Field: # notice the str() and int() functions used to convert the text to a number and vice versa # str() and int() are built-in Jython functions if system.gui.isTouchscreenModeEnabled(): event.source.text = str(system.gui.showNumericKeypad(int(event.source.text)))
10.6.23 system.gui.showTouchscreenKeyboard
Description Displays a modal on-screen keyboard, allowing for arbitrary text entry using the mouse, or a finger on a touchscreen monitor. Returns the text that the user "typed". Syntax
system.gui.showTouchscreenKeyboard( initialText [, fontSize] [, passwordMode])
Parameters String initialText - The text to start the on-screen keyboard with. int fontSize - The font size to display in the keyboard. [optional] boolean passwordMode - True (1) to activate passwordmode, where the text entered isn't echoed back clear-text. [optional] Returns String - The text that was "typed" in the on-screen keyboard. Scope Client Examples This function is a holdover for backwards compatibility. Input components now know when the client is in touchscreen mode and respond accordingly. This would go in the MouseClicked or MousePressed action of a Text Field or similar component.
if system.gui.isTouchscreenModeEnabled(): event.source.text = system.gui.showTouchscreenKeyboard(event.source.text)
10.6.24 system.gui.warningBox
Description Displays a message to the user in a warning style pop-up dialog. Syntax
system.gui.warningBox( message [, title])
773
String title - The title for the warning box. [optional] Returns
nothing
Scope Client Examples This code show a yellow popup box similar to the system.gui.messageBox function.
# Start the motor, or, warn the user if in wrong mode runMode = event.source.parent.getPropertyValue('RunMode') if runMode == 1: Cannot start the motor in mode #1 system.gui.warningBox("Cannot start the motor, current mode is <B>VIEW MODE</B>") else: system.db.runUpdateQuery("UPDATE MotorControl SET MotorRun=1")
10.7
system.nav
10.7.1 system.nav.centerWindow
Description Given a window path, or a reference to a window itself, it will center the window. The window should be floating an non-maximized. If the window can't be found, this function will do nothing. Syntax
system.nav.centerWindow( window )
Scope Client
system.nav.centerWindow( windowPath)
See also:
2012 Inductive Automation
774
system.nav.openWindow
10.7.2 system.nav.closeParentWindow
Description Closes the parent window given a component event object. Syntax
system.nav.closeParentWindow( event)
Parameters EventObject event - A component event object. The enclosing window for the component will be closed. Returns
nothing
#This code would be placed in the actionPerformed event of a button, and would close the window system.nav.closeParentWindow(event)
10.7.3 system.nav.closeWindow
Description Given a window path, or a reference to a window itself, it will close the window. If the window can't be found, this function will do nothing. Syntax
system.nav.closeWindow( windowPath)
Scope Client
system.nav.closeWindow( window )
Scope Client Examples Example 1: This example would get the window named 'Overview' and then close it.
2012 Inductive Automation
775
# If the window isn't open, show a warning try: window = system.gui.getWindow('Overview') system.nav.closeWindow(window) except ValueError: system.gui.warningBox("The Overview window isn't open")
Example 2: This example would close the window named 'Overview' in one step.
# If the window isn't open, the call to closeWindow will have no effect system.nav.closeWindow('Overview')
10.7.4 system.nav.getCurrentWindow
Description Returns the path of the current "main screen" window, which is defined as the maximized window. With the Typical Navigation Strategy, there is only ever one maximized window at a time. Syntax
system.nav.getCurrentWindow()
Parameters
none
Returns String - The path of the current "main screen" window - the maximized window. Scope Client Examples
# This code could run in a global timer script. # After a 5-minute timeout, navigate back to the home screen if system.util.getInactivitySeconds() > 300 and system.nav.getCurrentWindow() != "HomeScreen": system.nav.swapTo("HomeScreen")
10.7.5 system.nav.goBack
Description When using the Typical Navigation Strategy, this function will navigate back to the previous main screen window. Syntax
system.nav.goBack()
Parameters
none
776
Client Examples This code would go in a button to move to the previous screen.
system.nav.goBack()
10.7.6 system.nav.goForward
Description When using the Typical Navigation Strategy, this function will navigate "forward" to the last mainscreen window the user was on when they executed a system.nav.goBack(). Syntax
system.nav.goForward()
Parameters
none
Returns PyObject - The window that was returned to Scope Client Examples This code would go in a button to move to the last screen that used system.nav.goBack().
system.nav.goForward()
10.7.7 system.nav.goHome
Description When using the Typical Navigation Strategy, this function will navigate to the "home" window. This is automatically detected as the first main-screen window shown in a project. Syntax
system.nav.goHome()
Parameters
none
Returns PyObject - A reference to the home window that was navigated to. Scope Client Examples This code would go in a button to move to the Home screen.
system.nav.goHome()
777
10.7.8 system.nav.openWindow
Description Opens the window with the given path. If the window is already open, brings it to the front. The optional params dictionary contains key:value pairs which will be used to set the target window's root container's dynamic variables. For instance, if the window that you are opening is named "TankDisplay" has a dynamic variable in its root container named "TankNumber", then calling system.nav.openWindow ("TankDisplay", {"TankNumber" : 4}) will open the "TankDisplay" window and set Root Container.TankNumber to four. This is useful for making parameterized windows, that is, windows that are re-used to display information about like pieces of equipment. See also: Parameterized Windows. Syntax
system.nav.openWindow( path [, params])
Parameters String path - The path to the window to open. PyDictionary params - A dictionary of parameters to pass into the window. The keys in the dictionary must match dynamic property names on the target window's root container. The values for each key will be used to set those properties. [optional] Returns PyObject - A reference to the opened window. Scope Client Examples Example 1:
# This is the simplest form of openWindow system.nav.openWindow("SomeWindowName")
Example 2:
# A more complex example - a setpoint screen for multiple valves that opens centered titleText = "Third Valve Setpoints" tankNo = system.nav.openWindow("ValveSetPts", {"valveNum":3, "titleText":titleText}) system.nav.centerWindow("ValveSetPts")
10.7.9 system.nav.openWindowInstance
Description Operates exactly like system.nav.openWindow, except that if the named window is already open, then an additional instance of the window will be opened. There is no limit to the number of additional instances of a window that you can open. Syntax
system.nav.openWindowInstance( path [, params])
778
Parameters String path - The path to the window to open. PyDictionary params - A dictionary of parameters to pass into the window. The keys in the dictionary must match dynamic property names on the target window's root container. The values for each key will be used to set those properties. [optional] Returns PyObject - A reference to the opened window. Scope Client Examples This example would open three copies of a single HOA popup screen.
system.nav.openWindowInstance("HOA" {machineNum:3}) system.nav.openWindowInstance("HOA" {machineNum:4}) system.nav.openWindowInstance("HOA" {machineNum:5})
10.7.10 system.nav.swapTo
Description Performs a window swap from the current main screen window to the window specified. Swapping means that the opened window will take the place of the closing window - in this case it will be maximized. See also: Typical Navigation Strategy. Syntax
system.nav.swapTo( path [, params])
Parameters String path - The path of a window to swap to. PyDictionary params - A dictionary of parameters to pass into the window. The keys in the dictionary must match dynamic property names on the target window's root container. The values for each key will be used to set those properties. [optional] Returns PyObject - A reference to the swapped-to window. Scope Client Examples Example 1: This code would go in a button's ActionPerformed event to swap out of the current window and into a window named MyWindow
system.nav.swapTo("MyWindow")
Example 2: This code would go in a button's ActionPerformed event to swap out of the current window and into a window named MyWindow. It also looks at the selected value in a dropdown menu and passes that value into the new window.
779
# MyWindow's Root Container must have a dynamic property named "paramValue" dropdown = event.source.parent.getComponent("Dropdown") system.nav.swapTo("MyWindow", {"paramValue":dropdown.selectedValue)
10.7.11 system.nav.swapWindow
Description Performs a window swap. This means that one window is closed, and another is opened and takes its place - assuming its size, floating state, and maximization state. This gives a seamless transition - one window seems to simply turn into another. Syntax
system.nav.swapWindow( swapFromPath, swapToPath [, params])
Parameters String swapFromPath - The path of the window to swap from. Must be a currently open window, or this will act like an openWindow. String swapToPath - The name of the window to swap to. PyDictionary params - A dictionary of parameters to pass into the window. The keys in the dictionary must match dynamic property names on the target window's root container. The values for each key will be used to set those properties. [optional] Returns PyObject - A reference to the swapped-to window. Scope Client
system.nav.swapWindow( event, swapToPath [, params])
Parameters EventObject event - A component event whose enclosing window will be used as the "swapfrom" window. String swapToPath - The name of the window to swap to. PyDictionary params - A dictionary of parameters to pass into the window. The keys in the dictionary must match dynamic property names on the target window's root container. The values for each key will be used to set those properties. [optional] Returns PyObject - A reference to the swapped-to window. Scope Client Examples This function works like system.nav.swapTo except that you can specify the source and destination for the swap. Example 1:
# This code would go in a button's ActionPerformed event to swap out of the # window containing the button and into a window named MyWindow system.nav.swapWindow(event, "MyWindow")
780
Example 2:
# This code would swap from window named WindowA to a window named WindowB system.nav.swapWindow("WindowA", "WindowB")
Example 3:
# This code would swap from window named WindowA to a window named WindowB. # It also looks at the two calendar popup controls and passes the two selected dates to # WindowB. WindowB's Root Container must have dynamic properties named "startDate" and # "endDate" date1 = event.source.parent.getComponent("Start Date").date date2 = event.source.parent.getComponent("End Date").date system.nav.swapWindow("WindowA", "WindowB", {"startDate":date1, "endDate":date2})
10.8
system.net
10.8.1 system.net.getExternalIpAddress
Description Returns the client's IP address, as it is detected by the Gateway. This means that this call will communicate with the Gateway, and the Gateway will tell the clienth what IP address its incoming traffic is coming from. If you have a client behind a NAT router, then this address will be the WAN address of the router instead of the LAN address of the client, which is what you'd get with system. net.getIpAddress. Syntax
system.net.getExternalIpAddress()
Parameters
none
Returns String - A text representation of the client's IP address, as detected by the Gateway Scope Client Examples Put this script on a navigation button to restrict users from opening a specific page.
ip = sytem.net.getExternalIpAddress() #check if this matches the CEO's IP address if ip == "66.102.7.104": system.nav.swapTo("CEO Dashboard") else: system.nav.swapTo("Manager Dashboard")
781
10.8.2 system.net.getHostName
Description Returns the host name of the computer that the client is currently running on. On Windows, this is typically the "computer name". For example, might return EAST_WING_WORKSTATION or bobslaptop. Syntax
system.net.getHostName()
Parameters
none
Returns String - The hostname of the local machine. This is the computer that the script is being executed on - may be a Client or the Gateway depending on the script context. Scope All Examples Put this script on a navigation button to link dedicated machines to specific screens.
comp = sytem.net.getHostName() #check which line this client is tied to if comp == "Line1Computer": system.nav.swapTo("Line Detail", {"line":1}) elif comp == "Line2Computer": system.nav.swapTo("Line Detail", {"line":2}) else: system.nav.swapTo("Line Overview")
10.8.3 system.net.getIpAddress
Description Returns the IP address of the computer the client is running on, as it appears to the client. See also: system.net.getExternalIpAddress(). Syntax
system.net.getIpAddress()
Parameters
none
Returns String - Returns the IP address of the local machine, as it sees it. Scope All Examples
782
Put this script on a navigation button to link dedicated machines to specific screens.
ip = sytem.net.getIpAddress() #check which line this client is tied to if ip == "10.1.10.5": system.nav.swapTo("Line Detail", {"line":1}) elif ip == "10.1.10.6": system.nav.swapTo("Line Detail", {"line":2}) else: system.nav.swapTo("Line Overview")
10.8.4 system.net.httpGet
Description Retrieves the document at the given URL using the HTTP GET protocol. The document is returned as a string. For example, if you use the URL of a website, you'll get the same thing you'd get by going to that website in a browser and using the browser's "View Source" function. Syntax
system.net.httpGet( url, connectTimeout, readTimeout)
Parameters String url - The URL to retrieve. Integer connectTimeout - The timeout for connecting to the url. In millis. Default is 10,000. Integer readTimeout - The read timeout for the get operation. In millis. Default is 60,000. Returns String - The content found at the given URL. Scope All Examples Example 1:
# This code would return the source for Google's homepage source = system.net.httpGet("http://www.google.com") print source
Example 2:
# This code would query Yahoo Weather for the temperature in Sacramento, CA # and then find the current temperature using a regular expression response = system.net.httpGet("http://xml.weather.yahoo.com/forecastrss?p=95818") # import Python's regular expression library import re # NOTE - if you've never seen regular expressions before, don't worry, they look # confusing even to people who use them frequently. pattern = re.compile('.*?<yweather:condition (.*?)/>', re.DOTALL)
783
match = pattern.match(response) if match: subText = match.group(1) condition = re.compile('.*?text="(.*?)"').match(subText).group(1) temp = re.compile('.*?temp="(.*?)"').match(subText).group(1) print "Condition: ", condition print "Temperature (F): ", temp else: print 'Weather service format changed'
10.8.5 system.net.httpPost
Description Retrieves the document at the given URL using the HTTP POST protocol. If a parameter dictionary argument is specified, the entries in the dictionary will encoded in "application/x-www-formurlencoded" format, and then posted. You can post arbitrary data as well, but you'll need to specify the MIME type. The document is then returned as a string. Syntax
system.net.httpPost( url, postParams )
Parameters String url - The URL to post to. PyDictionary postParams - A dictionary of name: value key pairs to use as the post data. Returns String - The content returned for the POST operation. Scope All
system.net.httpPost( url, contentType, postData)
Parameters String url - The URL to post to. String contentType - The MIME type to use in the HTTP "Content-type" header. String postData - The raw data to post via HTTP. Returns String - The content returned for the POST operation. Scope All Examples Example 1:
# This code posts a name (first and last) to the post testing page at # "http://www.snee.com/xml/crud/posttest.cgi", and returns the resulting page as a string. page = system.net.httpPost("http://www.snee.com/xml/crud/posttest.cgi", {"fname":"Billy", "lnam print page
Example 2:
# This code sends an XML message to a hypothetical URL. message = "<MyMessage><MyElement>here is the element</MyElement></MyMessage>"
784
10.8.6 system.net.openURL
Description Opens the given URL outside of the currently running Client in whatever application the host operating system deems appropriate. For example, the URL: "http://www.google.com" ... will open in the default web browser, whereas this one: "file://C:\Report.pdf" ... will likely open in Adobe Acrobat. The Windows network-share style path like: "\\Fileserver\resources\machine_manual.pdf" ... will work as well (in Windows). Be careful not to use this function in a full-screen client, as launching an external program will break your full-screen exclusive mode. Syntax
system.net.openURL( url [, useApplet])
Parameters String url - The URL to open in a web browser. boolean useApplet - If set to true (1), and the client is running as an Applet, then the browser instance that launched the applet will be used to open the URL. [optional] Returns
nothing
Example 2:
# This code would open a PDF document from a Windows-based file server # Note the double backslashes are needed because backslash is the escape character for Jython system.net.openURL("\\\\MyServer\\MyDocs\\document.pdf")
10.8.7 system.net.sendEmail
Description Sends an email through the given SMTP server. Note that this email is relayed first through the Gateway - the client host machine doesn't need network access to the SMTP server. You can send text messages to cell phones and pagers using email. Contact your cell carrier for details. If you had a Verizon cell phone with phone number (123) 555-8383, for example, your text messaging email address would be: 1235558383@vtext.com. Try it out!
2012 Inductive Automation
785
This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.net.sendEmail( smtp, fromAddr, subject, body, html, to, attachmentNames, attachmentData,
Parameters String smtp - The address of an SMTP server to send the email through, like "mail.example. com" String fromAddr String subject - The subject line for the email String body - The body text of the email. Boolean html - A flag indicating whether or not to send the email as an HTML email. Will autodetect if omitted. String[] to - A list of email addresses to send to. String[] attachmentNames - A list of attachment names. byte[][] attachmentData - A list of attachment data, in binary format. Integer timeout - A timeout for the email, specified in milliseconds. Defaults to 5 minutes (60,000*5) String username - If specified, will be used to authenticate with the SMTP host. String password - If specified, will be used to authenticate with the SMTP host. Returns
nothing
# This code would send a simple plain-text email to a single recipient, with no attachments body = "Hello, this is an email." recipients = ["bobsmith@mycompany.com"] system.net.sendEmail("mail.mycompany.com", "myemail@mycompany.com", "Here is the email!", body,
Example 2:
# This code would send an HTML-formatted email to multiple recipients (including cellphones) wi body = "<HTML><BODY><H1>This is a big header</H1>And this text is <font color='red'>red</font>< recipients = ["bobsmith@mycompany.com", "1235558383@vtext.com", "sally@acme.org", "1235557272@v myuser = "mycompany" mypass = "1234" system.net.sendEmail(smtp="mail.mycompany.com", from="myemail@mycompany.com", subject="Here is
Example 3:
# This code ask the user for an attachment file and attach the file. filePath = fpmi.file.openFile() if filePath != None: fileName = filePath.split("\\")[-1] # This gets the filename without the C:\folder stuff fileData = fpmi.file.readFileAsBytes(filePath) smtp = "mail.mycompany.com" sender = "myemail@mycompany.com" subject = "Here is the file you requested"
786
body = "Hello, this is an email." recipients = ["bobsmith@mycompany.com"] system.net.sendEmail(smtp, sender, subject, body, 0, recipients, [fileName], [fileData])
10.9
system.opc
10.9.1 system.opc.getServerState
Description Retreives the current state of the given OPC server connection. If the given server is not found, the return value will be None. Otherwise, the return value will be one of these strings: UNKNOWN FAULTED CONNECTING CLOSED CONNECTED DISABLED Syntax
system.opc.getServerState( opcServer)
Parameters String opcServer - The name of an OPC server connection. Returns String - A string representing the current state of the connection, or None if the connection doesn't exist. Scope All
10.9.2 system.opc.readValue
Description Reads a single value directly from an OPC server connection. The address is specified as a string, for example, [MyDevice]N11/N11:0 The object returned from this function has three attributes: value, quality, and timestamp. The value attribute represents the current value for the address specified. The quality attribute is an OPC-UA status code. You can easily check a good quality vs a bad quality by calling the isGood() function on the quality object. The timestamp attribute is Date object that represents the time that the value was retrieved at. Syntax
system.opc.readValue( opcServer, itemPath)
Parameters String opcServer - The name of the OPC server connection in which the item resides. String itemPath - The item path, or address, to read from. Returns QualifiedValue - An object that contains the value, quality, and timestamp returned from the OPC server for the address specified. Scope All
787
10.9.3 system.opc.readValues
Description This function is equivalent to the system.opc.readValue function, except that it can operate in bulk. You can specify a list of multiple addresses to read from, and you will receive a list of the same length, where each entry is the qualified value object for the corresponding address. Syntax
system.opc.readValues( opcServer, itemPaths )
Parameters String opcServer - The name of the OPC server connection in which the items reside. String[] itemPaths - A list of strings, each representing an item path, or address to read from. Returns QualifiedValue[] - A sequence of objects, one for each address specified, in order. Each object will contains the value, quality, and timestamp returned from the OPC server for the corresponding address. Scope All
10.9.4 system.opc.writeValue
Description Writes a value directly through an OPC server connection. Will return an OPC-UA status code object. You can quickly check if the write succeeded by calling isGood() on the return value from this function. Syntax
system.opc.writeValue( opcServer, itemPath, value)
Parameters String opcServer - The name of the OPC server connection in which the item resides. String itemPath - The item path, or address, to write to. Object value - The value to write to the OPC item. Returns Quality - The status of the write. Use returnValue.getQuality.isGood() to check if the write succeeded. Scope All
10.9.5 system.opc.writeValues
Description This function is a bulk version of system.opc.writeValue. It takes a list of addresses and a list of objects, which must be the same length. It will write the corresponding object to the corresponding address in bulk. It will return a list of status codes representing the individual write success or failure for each corresponding address. Syntax
788
Parameters String opcServer - The name of the OPC server connection in which the items reside. String[] itemPaths - A list of item paths, or addresses, to write to. Object[] values - A list of values to write to each address specified. Returns Quality[] - An array of Quality objects, each entry corresponding in order to the addresses specified. Scope All
10.10 system.print
10.10.1 system.print.createImage
Description Advanced Function. Takes a snapshot of a component and creates a Java BufferedImage out of it. You can use javax.imageio.ImageIO to turn this into bytes that can be saved to a file or a BLOB field in a database. Syntax
system.print.createImage( component)
Parameters Component component - The component to render. Returns BufferedImage - A java.awt.image.BufferedImage representing the component. Scope Client
10.10.2 system.print.createPrintJob
Description Provides a general printing facility for printing the contents of a window or component to a printer. The general workflow for this function is that you create the print job, set the options you'd like on it, and then call print() on the job. For printing reports or tables, use those components' dedicated print() functions. The PrintJob object that this function returns has the following properties that can be set: showPrintDialog If true (1), then the print dialog window will be shown before printing. This allows users to specify printing options like orientation, printer, paper size, margins, etc. [default: 1] fitToPage If the component is too wide or tall to fit on a page, it will be proportionately zoomed out until it fits into the page. [default: 1] zoomFactor If greater than zero, this zoom factor will be used to zoom the printed image in or out. For example, if this is 0.5, the printed image will be half size. If used, this zoom factor overrides the fitToPage parameter.
789
[default: -1.0] Either system.print.PORTRAIT or system.print.LANDSCAPE [default: system.print.PORTRAIT] The width of the paper in inches. [default: 8.5] The height of the paper in inches. [default: 11] The margins, specified in inches. [default: 0.75]
You can set all of the margins at once with job.setMargins(number), and you initiate the printing with job.print(). Syntax
system.print.createPrintJob( component)
Parameters Component component - The component that you'd like to print. Returns JythonPrintJob - A print job that can then be customized and started. Scope Client Examples Put this code on a button to print out an image of the container the button is in
job = system.print.createPrintJob(event.source.parent) job.setMargins(0.5) job.zoomFactor = 0.75 job.showPageFormat = 0 job.print()
10.10.3 system.print.printToImage
Description This function prints the given component (such as a graph, container, entire window, etc) to an image file, and prompts the user to save the file to their hard drive. Syntax
system.print.printToImage( component [, filename])
Parameters Component component - The component to render. String filename - A filename to save the image as. [optional] Returns
nothing
Scope Client Examples This code would go on a button and save an image of the container that it is in.
system.print.printToImage(event.source.parent, "Screen.jpg")
790
10.11 system.security
10.11.1 system.security.getRoles
Description Finds the roles that the currently logged in user has, returns them as a Python tuple of strings. Syntax
system.security.getRoles()
Parameters
none
Returns PyTuple - A list of the roles (strings) that are assigned to the current user. Scope Client Examples This would run on a button to prevent certain users from opening a window
if "Supervisor" in system.security.getRoles(): system.nav.openWindow("ManagementOnly") else: system.gui.errorBox("You don't have sufficient privileges to continue")
10.11.2 system.security.getUserRoles
Description Fetches the roles for a user from the Gateway. This may not be the currently logged in user. Requires the password for that user. If the authentication profile name is omitted, then the current project's default authentication profile is used. Syntax
system.security.getUserRoles( username, password, authProfile, timeout)
Parameters String username - The username to fetch roles for String password - The password for the user String authProfile - The name of the authentication profile to run against. Optional. Leaving this out will use the project's default profile. Integer timeout - Timeout for client-to-gateway communication. (default: 60,000ms) Returns PyTuple - A list of the roles that this user has, if the user authenticates successfully. Otherwise, returns None. Scope Client Examples Fetch the roles for a given user, and check to see if the role "Admin" is in them.
791
reqRole = "Admin" username = "Billy" password= "Secret" roles = system.security.getUserRoles(username, password) if reqRole in roles: # do something requiring "Admin" role.
10.11.3 system.security.getUsername
Description Returns the currently logged-in username. Syntax
system.security.getUsername()
Parameters
none
Returns String - The current user. Scope Client Examples This code would run on a startup script and do special logic based upon who was logging in
name = system.security.getUsername() if name == 'Bob': system.nav.openWindow("BobsHomepage") else: system.nav.openWindow("NormalHomepage")
10.11.4 system.security.isScreenLocked
Description Returns whether or not the screen is currently locked. Syntax
system.security.isScreenLocked()
Parameters
none
Returns boolean - A flag indicating whether or not the screen is currently locked. Scope Client Examples This would run in a timer script to lock the screen after 15 seconds of inactivity, and then log the user out after 30 seconds of inactivity.
if system.util.getInactivitySeconds() > 15 and not system.security.isScreenLocked():
792
10.11.5 system.security.lockScreen
Description Used to put a running client in lock-screen mode. The screen can be unlocked by the user with the proper credentials, or by scripting via the system.security.unlockScreen() function. Syntax
system.security.lockScreen( [obscure])
Parameters boolean obscure - If true(1), the locked screen will be opaque, otherwise it will be partially visible. [optional] Returns
nothing
Scope Client Examples This would run in a timer script to lock the screen after 15 seconds of inactivity, and then log the user out after 30 seconds of inactivity.
if system.util.getInactivitySeconds() > 15 and not system.security.isScreenLocked(): system.security.lockScreen() elif system.util.getInactivitySeconds() > 30: system.security.logout()
10.11.6 system.security.logout
Description Shuts-down the currently running client and brings the client to the login screen. Syntax
system.security.logout()
Parameters
none
Returns
nothing
Scope Client Examples This would run in a timer script to log the user out after 30 seconds of inactivity.
if system.util.getInactivitySeconds() > 30: system.security.logout()
793
10.11.7 system.security.switchUser
Description Attempts to switch the current user on the fly. If the given username and password fail, this function will return false. If it succeeds, then all currently opened windows are closed, the user is switched, and windows are then re-opened in the states that they were in. If an event object is passed to this function, the parent window of the event object will not be reopened after a successful user switch. This is to support the common case of having a switch-user screen that you want to disappear after the switch takes place. Syntax
system.security.switchUser( username, password, event, hideError)
Parameters String username - The username to try and switch to. String password - The password to authenticate with. EventObject event - If specified, the enclosing window for this event's component will be closed in the switch user process. Boolean hideError - If true (1), no error will be shown if the switch user function fails. (default: 0) Returns boolean - false(0) if the switch user operation failed, true (1) otherwise. Scope Client Examples This script would go on a button in a popup window used to switch users without logging out of the client.
# Pull the username and password from the input components uname = event.source.parent.getComponent("Username").text pwd = event.source.parent.getComponent("Password").text # Call switchUser. The event object is passed to this # function so that if the username and password work, # this window will be closed before the switch occurs. success= system.security.switchUser(uname,pwd,event) # If the login didn't work, give input focus back to the # username component, so that the user can try again if not success: event.source.parent.getComponent("Username").requestFocusInWindow()
10.11.8 system.security.unlockScreen
Description Unlocks the client, if it is currently in lock-screen mode.
794
Syntax
system.security.unlockScreen()
Parameters
none
Returns
nothing
Scope Client Examples This code would go in a global script to automatically unlock the screen on a specific computer
comp = system.net.getHostName() if comp == 'Line 1': system.security.unlockScreen()
10.11.9 system.security.validateUser
Description Tests credentials (username and password) against an authentication profile. Returns a boolean based upon whether or not the authentication profile accepts the credentials. If the authentication profile name is omitted, then the current project's default authentication profile is used. Syntax
system.security.validateUser( username, password, authProfile, timeout)
Parameters String username - The username to validate String password - The password for the user String authProfile - The name of the authentication profile to run against. Optional. Leaving this out will use the project's default profile. Integer timeout - Timeout for client-to-gateway communication. (default: 60,000ms) Returns boolean - false(0) if the user failed to authenticate, true(1) if the username/password was a valid combination. Scope Client Examples This would require the current user to enter their password again before proceeding.
currentUser = system.security.getUsername() password = system.gui.passwordBox("Confirm Password") valid = system.security.validateUser(currentUser, password) if valid: # do something else: system.gui.errorBox("Incorrect password")
795
10.12 system.serial
10.12.1 system.serial.closeSerialPort
Syntax
system.serial.closeSerialPort( ??)
Scope All
10.12.2 system.serial.configureSerialPort
Description Configure a serial port for use in a later call. This only needs to be done once unless the configuration has changed after the initial call. All access to constants must be prefixed by "system.serial.". Syntax
system.serial.configureSerialPort( port, bitRate, dataBits, handshake, hardwareFlowControl,
parity, stopBits )
Parameters String port - The name of the serial port, e.g., "COM1" or "/dev/ttyS0". This parameter is required. Integer bitRate - Configure the bit rate.Valid values are defined by the following constants: BIT_RATE_110, BIT_RATE_150, BIT_RATE_300, BIT_RATE_600, BIT_RATE_1200, BIT_RATE_2400, BIT_RATE_4800, BIT_RATE_9600, BIT_RATE_19200, BIT_RATE_38400, BIT_RATE_57600, BIT_RATE_115200, BIT_RATE_230400, BIT_RATE_460800, BIT_RATE_921600. Integer dataBits - Configure the data bits.Valid values are defined by the following constants: DATA_BITS_5, DATA_BITS_6, DATA_BITS_7, DATA_BITS_8. Integer handshake - Configure the handshake.Valid values are defined by the following constants: HANDSHAKE_CTS_DTR, HANDSHAKE_CTS_RTS, HANDSHAKE_DSR_DTR, HANDSHAKE_HARD_IN, HANDSHAKE_HARD_OUT, HANDSHAKE_NONE, HANDSHAKE_SOFT_IN, HANDSHAKE_SOFT_OUT, HANDSHAKE_SPLIT_MASK, HANDSHAKE_XON_XOFF. Boolean hardwareFlowControl - Configure hardware flow control. On or off. Integer parity - Configure parity.Valid values are defined by the following constants: PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE, PARITY_NONE. Integer stopBits - Configure stop bits.Valid values are defined by the following constants: STOP_BITS_1, STOP_BITS_2. Returns SerialConfigurator Scope All
796
10.12.3 system.serial.openSerialPort
Syntax
system.serial.openSerialPort( ??)
Scope All
10.12.4 system.serial.readBytes
Description Read numberOfBytes bytes from a serial port. Syntax
system.serial.readBytes( port, numberOfBytes [, timeout])
Parameters String port - The previously configured serial port to use. int numberOfBytes - The number of bytes to read. int timeout - Maximum amount of time, in milliseconds, to block before returning. [optional] Returns byte[] - A byte[] containing bytes read from the serial port.
2012 Inductive Automation
797
Scope All
10.12.5 system.serial.readBytesAsString
Syntax
system.serial.readBytesAsString( port, numberOfBytes [, timeout])
Parameters String port - The previously configured serial port to use. int numberOfBytes - The number of bytes to read. int timeout - Maximum amount of time, in milliseconds, to block before returning. [optional] Returns String - A String created from the bytes read. Scope All
10.12.6 system.serial.readLine
Description Read one line from a serial port. Syntax
system.serial.readLine( port [, timeout] [, encoding])
Parameters String port - The previously configured serial port to use. int timeout - Maximum amount of time, in milliseconds, to block before returning. [optional] String encoding - The String encoding to use. [optional] Returns String - A line of text. A line is considered to be terminated by any one of a line feed (' '), a carriage return (' '), or a carriage return followed immediately by a line feed. Scope All
10.12.7 system.serial.readUntil
Description Read from a serial port until a delimiter character is encountered. Syntax
system.serial.readUntil( port, delimiter, includeDelimiter)
Parameters String port - The previously configured serial port to use. char delimiter - The delimiter to read until. boolean includeDelimiter - If true, the delimiter will be included in the return value. Returns
798
String - Returns a String containing all characters read until the delimiter was reached, and including the delimiter if the "includeDelimiter" parameter was true. Scope All
10.12.8 system.serial.write
Description Write a String to a serial port. Syntax
system.serial.write( port, toWrite)
Parameters String port - The previously configured serial port to use. String toWrite - The String to write. Returns
nothing
Scope All
10.12.9 system.serial.writeBytes
Description Write a byte[] to a serial port. Syntax
system.serial.writeBytes( port, toWrite)
Parameters String port - The previously configured serial port to use. byte[] toWrite - The byte[] to write. Returns
nothing
Scope All
10.13 system.tag
10.13.1 system.tag.exists
Description Checks whether or not a tag exists. You pass this function a tag path, and it will evaluate true if the tag exists, otherwise false. Syntax
system.tag.exists( tagPath)
Parameters
2012 Inductive Automation
799
String tagPath - The path of the tag to look up Returns boolean Scope All Examples This code would write a 1 to the tag "Compressors/C28/ClearFault" if that tag exists.
if system.tag.exists("Compressors/C28/ClearFault"): system.tag.write("Compressors/C28/ClearFault", 1)
10.13.2 system.tag.isOverlaysEnabled
Description Returns whether or not the current client's quality overlay system is currently enabled. Syntax
system.tag.isOverlaysEnabled()
Parameters
none
Returns boolean - True (1) if overlays are currently enabled. Scope Client
10.13.3 system.tag.queryTagDensity
Description Queries the tag history system for information about the density of data. In other words, how much data is available for a given time span. This function is called with a list of tag paths, and a start and end data. The result set is a two column dataset specifying the timestamp, and a relative weight. Each row is valid from the given time until the next row. The weight is normalized to a value of 1.0 for each tag with data during that time. Thus, for three tag paths passed in, if all tags were present during the span, the result would be 3.0. This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.tag.queryTagDensity( paths, startDate, endDate)
Parameters PySequence paths - An array of tag paths (strings) to query. Date startDate - The start of the range to query. Date endDate - The end of the range to query. Returns Dataset - A 2-column dataset consisting of a timestamp and a weight. Each row is valid until the
2012 Inductive Automation
800
next row. The weight is 1 point for each tag with data present. Scope All
10.13.4 system.tag.queryTagHistory
Description Issues a query to to the SQLTags Historian. Querying tag history involves specifying the tags and the date range, as well as a few optional parameters. The SQLTags historian will find the relevant history and then interpolate and aggregate it together into a coherent, tabular result set. This function takes a list of strings, where each string is a tag path, like "Tanks/Tank5" or "[OracleProvider]Sump/Out2". See also: Tag Paths. The return size determines how the underlying data is aggregated and/or interpolated. If a distinct return size is specified, that will be the number of rows in the resulting dataset. The special numbers 0 and -1 mean "Natural" and "On-Change", respectively. "Natural" calculates a return size based on the rate of the logging historical scan classes. For example, if you query 1 hour of data for a scan class logging every minute, the natural return size is 60. "On-Change means that you'll get an entry whenever any of the tags under consideration have changed. Instead of defining a fixed return size, the parameters intervalHours and intervalMinutes can be used. These parameters can be used independently or together to define a "window size". For example, if you defined a 1 hour range, with intervalMinutes=15, you would get 4 rows as a result. The span of the query can be specified using startDate and endDate. You can also use rangeHours and rangeMinutes in conjunction with either start or end date to specify the range in dynamic terms. For example, you could specify only "rangeHours=-8" to get the last 8 hours from the current time. Or you could use "startDate='2012-05-30 00:00:00', rangeHours=12" to get the first half of the day for May 30th, 2012. The aggregation mode is used when the data is denser than what you asked for. This happens when using fixed return sizes, as there will often be multiple raw values for the window interval defined. Another common operation is to set the return size to 1, in order to use these aggregate functions for calculation purposes. The available functions are: "MinMax" - will return two entries per time slice - the min and the max. "Average" - will return the time-weighted average value of all samples in that time slice. "LastValue" - returns the most recent actual value to the end of the window. "SimpleAverage" - returns the simple mathematical average of the values - ((V1+V2+...+Vn)/n) This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.tag.queryTagHistory( paths, startDate, endDate, returnSize, aggregationMode,
Parameters PySequence paths - An array of tag paths (strings) to query. Each tag path specified will be a column in the result dataset. Date startDate - The earliest value to retrieve. If omitted, 8 hours before current time is used. Date endDate - The latest value to retrieve. If omitted, current time is used.
2012 Inductive Automation
801
Integer returnSize - The number of samples to return. -1 will return values as they changed, and 0 will return the "natural" number of values based on the logging rates of the scan class (es) involved. -1 is the default. String aggregationMode - The mode to use when aggregating multiple samples into one time slice. Must be one of "Average" or "MinMax". String returnFormat - Use "Wide" to have a column per tag queried, or "Tall" to have a fixedcolumn format. Default is "Wide". PySequence columnNames - Aliases that will be used to override the column names in the result dataset. Must be 1-to-1 with the tag paths. If not specified, the tag paths themselves will be used as column titles. Integer intervalHours - Allows you to specify the window interval in terms of hours, as opposed to using a specific return size. Integer intervalMinutes - Same as intervalHours, but in minutes. Can be used on its own, or in conjunction with intervalHours. Integer rangeHours - Allows you to specify the query range in hours, instead of using start and end date. Can be positive or negative, and can be used in conjunction with startDate or endDate. Integer rangeMinutes - Same as rangeHours, but in minutes. Returns Dataset - A dataset representing the historian values for the specified tag paths. The first column will be the timestamp, and each column after that represents a tag. Scope All
10.13.5 system.tag.read
Description Reads the value of the tag at the given tag path. Returns a qualified value object. You can read the value, quality, and timestamp from this object. If the tag path does not specify a tag property, then the Value property is assumed. Syntax
system.tag.read( tagPath)
Parameters String tagPath - Reads from the given tag path. If no property is specified in the path, the Value property is assumed. Returns QualifiedValue - A qualified value. This object has three sub-members: value, quality, and timestamp. Scope All Examples This example would read a value and display it in a message box.
qv = system.tag.read("[]EastSection/ValveG/HOA_bit") system.gui.messageBox("The value is %d" % qv.value)
This example would check the quality of a tag value, and write it to the database if the quality is good
802
10.13.6 system.tag.readAll
Description Reads the values of each tag in the tag path list. Returns a sequence of qualified value objects. You can read the value, quality, and timestamp from each object in the return sequence. Reading in bulk like this is more efficient than calling read() many times. Syntax
system.tag.readAll( tagPaths )
Parameters String[] tagPaths - A sequence of tag paths to read from. Returns QualifiedValue[] - A sequence of qualified values corresponding to each tag path given. Each qualified value will have three sub-members: value, quality, and timestamp. Scope All Examples This example would read 5 tags at once and print each of their values
tags = ["Tags/T1", "Tags/T2", "Tags/T3", "Tags/T4", "Tags/T5"] values = system.tag.readAll(tags) for x in range(len(tags)): print "%s = %s" % (tags[x], values[x])
10.13.7 system.tag.setOverlaysEnabled
Description Enables or disables the component quality overlay system. Syntax
system.tag.setOverlaysEnabled( enabled)
Parameters boolean enabled - True (1) to turn on tag overlays, false (0) to turn them off. Returns
nothing
Scope Client
10.13.8 system.tag.write
Description Writes a value to a tag. Note that this function writes asynchronously. This means that the function does not wait for the write to occur before returning - the write occurs sometime later on a different
2012 Inductive Automation
803
thread. Syntax
system.tag.write( tagPath, value, suppressErrors )
Parameters String tagPath - The path of the tag to write to. Object value - The value to write. Boolean suppressErrors - A flag indicating whether or not to suppress errors. (optional, client-only). Returns int - 0 if the write failed immediately, 1 if it succeeded immediately, and 2 if it is pending. Scope All Examples This code would go on a property change event for a numeric text field to calculate and write a value to a tag.
if event.propertyName == intValue: calcValue = event.newValue * 2.5 system.tag.write("Tanks/tankHiSP",calcValue)
10.13.9 system.tag.writeAll
Description Performs a bulk write. Take two sequences that must have the same number of entries. The first is the list of tag paths to write to, and then second is a list of values to write. This function is dramatically more efficient than calling write multiple times. Syntax
system.tag.writeAll( tagPaths, values )
Parameters String[] tagPaths - The paths of the tags to write to. Object[] values - The values to write. Returns int[] - Array of ints with an element for each tag written to: 0 if the write failed immediately, 1 if it succeeded immediately, and 2 if it is pending. Scope All Examples This code write to 5 tags at once.
tags = ["Tags/T1", "Tags/T2", "Tags/T3", "Tags/T4", "Tags/T5"] values = [2, 4, 8, 16, 32] values = system.tag.writeAll(tags,values)
804
10.13.10 system.tag.writeSynchronous
Description Writes a value to a tag, synchronously. This means that you know at the end of this function whether or not the write succeeded or not. However, this function cannot be called from the event dispatch thread, which means that it cannot be called directly from a GUI event like a button press, without wrapping it in a system.util.invokeAsynchronous. You can call this from project event scripts like timer scripts. Syntax
system.tag.writeSynchronous( tagPath, value [, timeout])
Parameters String tagPath - The path of the tag to write to. Object value - The value to write. int timeout - How long to wait before timing out. [optional] Returns
nothing
Scope All Examples This code would write to a tag and wait before continuing on.
system.tag.writeSynchronous("Tags/T5", 38) # this line will not be reached until the tag is written
10.14 system.util
10.14.1 system.util.beep
Description Tells the computer to make a "beep" sound. Syntax
system.util.beep()
Parameters
none
Returns
nothing
Scope All
10.14.2 system.util.execute
Description Executes the given commands via the operating system, in a separate process The commands argument is an array of strings. The first string is the program to execute, with subsequent strings being the arguments to that command.
2012 Inductive Automation
805
Syntax
system.util.execute( commands )
Parameters String[] commands - A list containing the command (1st entry) and associated arguments (remaining entries) to execute. Returns
nothing
10.14.3 system.util.exit
Description Exits the running client, as long as the shutdown intercept script doesn't cancel the shutdown event. Set force to true to not give the shutdown intercept script a chance to cancel the exit. Note that this will quit the Client completely. you can use system.security.logout() to return to the login screen. Syntax
system.util.exit( [force])
Parameters boolean force - If true (1), the shutdown-intercept script will be skipped. Default is false (0).
[optional]
Returns
nothing
10.14.4 system.util.getClientId
Description Returns a hex-string that represents a number unique to the running client's session. You are guaranteed that this number is unique between all running clients. Syntax
system.util.getClientId()
806
Parameters
none
Returns String - A special code representing the client's session in a unique way. Scope Client Examples
# This code would print the current client's id to the debug console. id = system.util.getClientId() print id
10.14.5 system.util.getConnectTimeout
Description Returns the connect timeout in milliseconds for all client-to-gateway communication. This is the maximum amount of time that communication operations to the Gateway will be given to connect. The default is 10,000ms (10 seconds). Syntax
system.util.getConnectTimeout()
Parameters
none
Returns int - The current connect timeout, in milliseconds. Default is 10,000 (ten seconds) Scope Client Examples
# This code would print out the current connect timeout print system.util.getConnectTimeout()
10.14.6 system.util.getConnectionMode
Description Retrieves this client session's current connection mode. 3 is read/write, 2 is read-only, and 1 is disconnected. Syntax
system.util.getConnectionMode()
Parameters
none
Returns int - The current connection mode for the client. Scope Client
2012 Inductive Automation
807
10.14.7 system.util.getEdition
Description Returns the "edition" of the Vision client - "standard", "limited", or "panel". Syntax
system.util.getEdition()
Parameters
none
Returns String - The edition of the Vision module that is running the client. Scope Client
10.14.8 system.util.getGatewayAddress
Description Returns the address of the gateway that the client is currently communicating with. Syntax
system.util.getGatewayAddress()
Parameters
none
Returns String - the address of the Gateway that the client is communicating with. Scope Client Examples
# This code would open up the gateway config page. address = system.util.getGatewayAddress() system.net.openURL("%s/web/config/" % address)
10.14.9 system.util.getInactivitySeconds
Description Returns the number of seconds since any keyboard or mouse activity. Note - this function will always return zero in the Designer. Syntax
system.util.getInactivitySeconds()
Parameters
none
Returns long - The number of seconds the mouse and keyboard have been inactive for this client.
808
10.14.10 system.util.getProjectName
Description Returns the name of the project that is currently being run. Syntax
system.util.getProjectName()
Parameters
none
Returns String - The name of the currently running project. Scope Client Examples
# This code would display the name of the currently running project system.gui.messageBox("You are running project: %s" % system.util.getProjectName())
10.14.11 system.util.getProperty
Description Retrieves the value of a named system property. Some of the available properties are: file.separator. The system file separator character. (for example, "/" (unix) or "\" (windows)) line.separator. The system line separator string. (for example, "\r\n" (carriage return, newline)) os.arch. Operating system architecture. (for example, "x86") os.name. Operating system name. (for example, "Windows XP") os.version. Operating system version. (for example, "5.1") user.home. User's home directory. user.name. User's account name. Syntax
system.util.getProperty( propertyName)
Parameters String propertyName - The name of the system property to get. Returns String - The value for the named property. Scope All
2012 Inductive Automation
809
Examples This script would store the contents of the Text Area component in the users home directory.
homeDir = system.util.getProperty("user.home") sep = system.util.getProperty("file.separator") path = "%s%smyfile.txt" %(homeDir, sep) system.file.writeFile(path, event.source.parent.getComponent("Text Area").text)
10.14.12 system.util.getReadTimeout
Description Returns the read timeout in milliseconds for all client-to-gateway communication. This is the maximum amount of time allowed for a communication operation to complete. The default is 60,000ms (1 minute). Syntax
system.util.getReadTimeout()
Parameters
none
Returns int - The current read timeout, in milliseconds. Default is 60,000 (one minute) Scope Client
10.14.13 system.util.getSessionInfo
Description Returns a PyDataSet holding information about all of the sessions (logged-in users) on the Gateway. Optional regular-expression based filters can be provided to filter the username or the username and the project returned. The PyDataSet returned has these columns: username (String) project (String) address (String) isDesigner (Boolean) clientId (String) creationTime (Date) Note that this function will not return all sessions across a cluster - only the cluster node that is being communicated with by the client who makes the call. Syntax
system.util.getSessionInfo( [usernameFilter] [, projectFilter])
Parameters String usernameFilter - A filter string to restrict the list by username. * matches anything, ? matches one character. [optional]
2012 Inductive Automation
810
String projectFilter - A filter string to restrict the list by project. * matches anything, ? matches one character. [optional] Returns PyDataSet - A dataset representing the Gateway's current sessions. Scope Client Examples Example 1:
# This code would get the entire table of sessions and put it in an adjacent table table = event.source.parent.getComponent("Table") sessions = system.util.getSessionInfo() table.data = system.db.toDataSet(sessions)
Example 2:
# This code would count the number of times a user named "billy" is logged in sessions = system.util.getSessionInfo("billy") system.gui.messageBox("Billy has %d sessions" % len(sessions))
10.14.14 system.util.getSystemFlags
Description Returns an integer that represents a bit field containing information about the currently running system. Each bit corresponds to a public bitmask as defined below. See the examples for tips on how to extract the information in this bit field are in the examples. Note that the tag [System] Client/System/SystemFlags contains the same value. system.util.DESIGNER_FLAG. Set if running in the Designer. (1) system.util.PREVIEW_FLAG. Set if running in the Designer, and the Designer is in preview mode. (2) system.util.CLIENT_FLAG. Set if running as a Client. (4) system.util.WEBSTART_FLAG. Set if running as a Client in Web Start mode. (8) system.util.APPLET_FLAG. Set if running as a Client in Applet mode. (16) system.util.FULLSCREEN_FLAG. Set if running as a Client in full-screen mode. (32) system.util.SSL_FLAG. Set if communication to the Gateway is encrypted with SSL. (64) system.util.MOBILE_FLAG. Set if currently running a mobile-launched client. (128) system.util.STAGING_FLAG. Set if running a staging client. (256) Syntax
system.util.getSystemFlags()
Parameters
none
811
10.14.15 system.util.invokeAsynchronous
Description This is an advanced scripting function. Invokes (calls) the given Python function on a different thread. This means that calls to invokeAsynchronous will return immediately, and then the given function will start executing asynchronously on a different thread. This is useful for long-running data intensive functions, where running them synchronously (in the GUI thread) would make the GUI non-responsive for an unacceptable amount of time. WARNING: Under no circumstances should you ever do anything in the function that is invoked asynchronously that interacts with the GUI. This means things like window navigation, setting and getting component properties, showing error/message popups, etc. If you need to do something with the GUI in this function, this must be achieved through a call to system.util.invokeLater. Syntax
system.util.invokeAsynchronous( function)
Parameters PyObject function - A python function object that will get invoked with no arguments in a separate thread. Returns
nothing
def longProcess(rootContainer = event.source.parent): import system # Do something here with the database that takes a long time results = ...( something ) # Now we'll send our results back to the UI def sendBack(results = results, rootContainer = rootContainer): rootContainer.resultsProperty = results system.util.invokeLater(sendBack) system.util.invokeAsynchronous(longProcess)
10.14.16 system.util.invokeLater
Description This is an advanced scripting function. Invokes (calls) the given Python function object after all of the currently processing and pending events are done being processed, or after a specified delay. The function will be executed on the GUI, or event dispatch, thread. This is useful for events like propertyChange events, where the script is called before any bindings are evaluated. If you specify an optional time argument (number of milliseconds), the function will be invoked after all
2012 Inductive Automation
812
currently processing and pending events are processed plus the duration of that time. Syntax
system.util.invokeLater( function [, delay])
Parameters PyObject function - A Python function object that will be invoked later, on the GUI, or eventdispatch, thread with no arguments. int delay - A delay, in milliseconds, to wait before the function is invoked. The default is 0, which means it will be invoked after all currently pending events are processed. [optional] Returns
nothing
# The code in the update/refresh button uses the 'date' property on the two calendar components # which are bound to the current_timestamp property on their parent. We want to simulate a butt # press when the window opens, but only after the date properties' bindings have been evaluated if event.propertyName == 'current_timestamp': # Define a function to click the button def clickButton(button = event.source.parent.getComponent('Refresh')): import system button.doClick() system.gui.messageBox("Button has been clicked!") # Tell the system to invoke the function after # the current event has been processed system.util.invokeLater(clickButton)
10.14.17 system.util.playSoundClip
Description Plays a sound clip from a wav file to the system's default audio device. The wav file can be specified as a filepath, a URL, or directly as a raw byte[]. Syntax
system.util.playSoundClip( wavFile)
Parameters String wavFile - A filepath or URL that represents a wav file Returns
nothing
Scope All
system.util.playSoundClip( wavFile [, volume] [, wait])
813
double volume - The clip's volume, represented as a floating point number between 0.0 and 1.0
[optional]
boolean wait - A boolean flag indicating whether or not the call to playSoundClip should wait for the clip to finish before it returns [optional] Returns
nothing
Scope All
system.util.playSoundClip( wavBytes [, volume] [, wait])
Parameters byte[] wavBytes double volume - The clip's volume, represented as a floating point number between 0.0 and 1.0
[optional]
boolean wait - A boolean flag indicating whether or not the call to playSoundClip should wait for the clip to finish before it returns [optional] Returns
nothing
# This code would play a sound clip at full volume that was located on the current host's files # It will not return until the clip in finished playing system.util.playSoundClip("C:\\sounds\\siren.wav")
Example 2:
# This code would pull a sound clip out of a BLOB field from a database, playing it asynchronou soundData = system.db.runScalarQuery("SELECT wavBlob FROM sounds WHERE type='alert_high'") system.util.playSoundClip(soundData, 0.5, 0)
10.14.18 system.util.queryAuditLog
Description Queries an audit profile for audit history. Returns the results as a dataset. This function accepts k eyword-style invocation. See also: Functions / Keyword Invocation Syntax
system.util.queryAuditLog( auditProfileName, startDate, endDate, actorFilter, actionFilter,
Parameters String auditProfileName - The name of the audit profile to pull the history from. Date startDate - The earliest audit event to return. If omitted, the current time - 8 hours will be used.
2012 Inductive Automation
814
Date endDate - The latest audit evnet to return. If omitted, the current time will be used. String actorFilter - A filter string used to restrict the results by actor. String actionFilter - A filter string used to restrict the results by action. String targetFilter - A filter string used to restrict the results by target. String valueFilter - A filter string used to restrict the results by value. String systemFilter - A filter string used to restrict the results by system. Integer contextFilter - A bitmask used to restrict the results by context. 0x01 = Gateway, 0x02 = Designer, 0x04 = Client. Returns Dataset - A dataset with the audit events from the specified profile that match the filter arguments. Scope Client
10.14.19 system.util.retarget
Description This function allows you to programmatically 'retarget' the Client to a different project and/or different Gateway. You can have it switch to another project on the same Gateway, or another gateway entirely, even across a WAN. This feature makes the vision of a seamless, enterprise-wide SCADA application a reality. The retarget feature will attempt to transfer the current user credentials over to the new project / Gateway. If the credentials fail on that project, the user will be prompted for a valid username and password, with an option to cancel the retargeting and return to the original project. One valid authentication has been achieved, the currently running project is shut down, and the new project is loaded. You can pass any information to the other project through the parameters dictionary. All entries in this dictionary will be set in the global scripting namespace in the other project. Even if you don't specify any parameters, the system will set the variable _RETARGET_FROM_PROJECT to the name of the current project and _RETARGET_FROM_GATEWAY to the address of the current Gateway. Syntax
system.util.retarget( projectName [, gatewayAddress] [, params] [, startupWindows])
Parameters String projectName - The name of the project to retarget to. String gatewayAddress - The address of the Gateway that the project resides on. If omitted, the current Gateway will be used. Format is: "host:httpPort:sslPort/contextName" [optional] PyDictionary params - A dictionary of parameters that will be passed to the new project. They will be set as global variables in the new project's Python scripting environment. [optional] String[] startupWindows - A list of window names to use as the startup windows. If omitted, the project's normal startup windows will be opened. If specified, the project's normal startup windows will be ignored, and this list will be used instead. [optional] Returns
nothing
Scope Client
815
Examples Example 1:
# This code would switch to a project named 'TankControl' on the same Gateway # as the currently running project system.util.retarget("TankControl")
Example 2:
# This code would switch to a project named 'TankControl' on a # Gateway located at a different IP address running on port 8080, and # would open the window named "Graph", and set a global jython variable in the new # project named "retargetOccured" to the value 1 (one). system.util.retarget("TankControl", "10.30.2.33:8088/main", {"retargetOccured":1}, ["Graph"])
Example 3:
# This code would be put in a button in the target that was retargetted to, # and act as a 'back' button, that would retarget back to the original project. global _RETARGET_FROM_PROJECT global _RETARGET_FROM_GATEWAY # _RETARGET_FROM_GATEWAY is formatted like 'http://10.1.10.1:8088/main', so you have to remove system.util.retarget(_RETARGET_FROM_PROJECT, _RETARGET_FROM_GATEWAY[7:])
10.14.20 system.util.setConnectTimeout
Description Sets the connect timeout for client-to-gateway communication. Specified in milliseconds. Syntax
system.util.setConnectTimeout( connectTimeout)
Parameters int connectTimeout - The new connect timeout, specified in milliseconds. Returns
nothing
10.14.21 system.util.setConnectionMode
Description Sets the connection mode for the client session. Normally a client runs in mode 3, which is readwrite. You may wish to change this to mode 2, which is read-only, which will only allow reading and
2012 Inductive Automation
816
subscribing to tags, and running SELECT queries. Tag writes and INSERT / UPDATE / DELETE queries will not function. You can also set the connection mode to mode 1, which is disconnected, all tag and query features will not work. Syntax
system.util.setConnectionMode( mode)
Parameters int mode - The new connection mode. 1 = Disconnected, 2 = Read-only, 3 = Read/Write. Returns
nothing
Scope Client Examples This example, which could go in a project's startup script, would check the current username and set the connection mode to read-only if it is the "guest" user.
username = system.security.getUsername() if "guest" == username.lower(): # Set "guest" user to read-only mode system.util.setConnectionMode(2) else: system.util.setConnectionMode(3)
10.14.22 system.util.setReadTimeout
Description Sets the read timeout for client-to-gateway communication. Specified in milliseconds. Syntax
system.util.setReadTimeout( readTimeout)
Parameters int readTimeout - The new read timeout, specified in milliseconds. Returns
nothing
Scope Client
Index
817
Index
-22-State Button 503
-AAggregation Mode 231 Allen Bradley 106, 107, 108, 109 Anchored Layout 220 Animation, using Timers 682 app.* 180 Applet Size 178 Attributes Panel 356, 383 Audio Playback 681 Auto-Login 179 Auto-Refresh 157 average function - Aggregate Substitution Keys
376
-BBar Chart 626 Barcode component 559 Base Rate 179 Basic Drawing Tools 311 Bzier curve 213 Bidirectional Bindings 229 BLOB images 398 Blue Property 210 Bold Property 210 Box and Whisker Chart 641 Builtin Functions - Substitution Keys Button Component 499
376
Circle 204 Classic Chart Component 617 Client Memory 178 Client Menubar Appearance 179 Client Poll Rate 176 Collapsible Palette 203 Column Selector 300 Column Selector Component 690 Comm Off 154 Comm Read/Write 154 Comm Read-Only 154 Comments Panel Component 602 Compass Component 566 Components Copying 207 Creating 203 Customizers 217 Dynamic Properties 217 Introduction 203 Layout 220 Moving 207 Overlays 218 Properties 210 Resizing 207 Rotating 207 Security 244 Shapes 204 Styles 218 connection path 109 Container Component 670 Control Chart 607 count function - Aggregate Substitution Keys Crosstab 314 CSV Export of Table 578, 589 Custom Palettes 206 Custom Properties 217 Customizers 217 Cylindrical Tank Component 550
376
-CCaching Windows 198 Calculated Pens 607 Calendar Component 649 Cap Style 211 Centered Components 220 Chart Component 617 Checkbox Component 521
2012 Inductive Automation
-DData Types Color 216 Dataset 216 Date 216 Double 216 Float 216 int 216
818
Data Types Integer 216 Long 216 String 216 Database Pens 607 Databinding 228 Dataset Definition 216 Scripting 420 Dataset Key 333, 395 Datatypes 216 Date Formatting Paterns 359, 386 Date Picker Component 652 Date Range Component 655 Date Spinner 481 Debugging scripts 155 Default Color Mapping 177 Default Component Layout 177 Default Database Connection 176 Default Launch Mode 178 Default SQLTags Provider 176 Designer Shortcuts 209 Diagnostics 155 Digital Display Component 539 Dockable Panels 154 Document Viewer Component 572 Drawing a line 204 Drop Target 226 Dropdown Component 491 Dynamic Properties 217, 373
focusLost 236 internalFrameActivated 236 internalFrameClosed 236 internalFrameClosing 236 internalFrameDeactivated 236 internalFrameOpened 236 itemStateChanged 236 keyPressed 236 keyReleased 236 keyTyped 236 mouseClicked 236 mouseDragged 236 mouseEntered 236 mouseExited 236 mouseMoved 236 mousePressed 236 mouseReleased 236 propertyChange 236 repaint 236 event.source 235 Expert Properties 210 Expression Binding 232
-FFailure Handshake 185 Fallback Delay 229 Fallback Value 233 Features 248 File Chooser 692 Fill Paint 211 Formatted Text Field 483 Freehand lines 204
-EEasy Chart 607 Editable Table 453, 578, 589 Ellipse 204 Event Handlers Action Qualifiers 242 Navigation 242 Overview 234 Set Property 242 Set Tag Value 242 SQL Update 242 event Object 235 Event Types actionPerformed 236 cellEdited 236 focusGained 236
-GGantt Chart 647 Gateway Comm Mode 154 Gauge Component 561 getComponent 235 Getting Started 255 Go Back 242 Go Forward 242 Gradient Paint Cycle Mode 211 Linear 211 Radial 211
2012 Inductive Automation
Index
819
670 154
-HHandshakes 185 Hiding a Project 178 Hiding the Exit Button 178 Hiding the Menubar 179 HOA Control 507 How it works 249 HTML Export of Table 578, 589 HTML Viewer Component 572
Launch Icon 178 Layout 220 LED Display Component 539 Level Indicator Component 553 Line-Wrap 489 List Component 586 Log Viewer 155 Login Screen Settings 179
-Mmax function - Aggregate Substitution Keys Memory 450 Menu 352 Meter Component 561 min function - Aggregate Substitution Keys Minimum Size 179 Miter Length 211 MJPEG Video 574 Modules 64 Momentary Button 514 Multi-Line Text Editor 489 Multi-State Button 507 Multi-State Indicator 536 376
-IImage Component 545 Image Manager 156 Image Placeholders 323, 381, 402 Images 156, 322, 380, 401 Indirect Bindings 230 Initial Gateway Comm Mode 177 Inspector Panel 361 Installation and trial mode 252 Introduction 244 IPCamera Component 574
376
-NNavigation 201 Netcam Component 574 Nudge Distances 177 Number Spinner 481 Numeric Label Component Numeric Text Editor 477
-JJava Heap 450 Java Web Start Homepage 178 Java Web Start Vendor 178 Java2D 673 Join Style 211
532
-OObject Layout 348 One-Shot (Latched) Button Output Console 155 Overlays 218 510
-LLabel Component 529 Label Swich Versions, Graph Labels 325 Latched Button 510
2012 Inductive Automation
-P318, 391 Paginate 365 Paint 211 Paintable Canvas Palettes 203 673
820
Passing Parameters (Windows) 202 Password Field Component 487 Paths 213 Pattern Paint 211 PDF File Viewer 694 PDF Report Component 685 PDF Reports 323, 382, 403 PDF, Saving Reports 380 Pens 607 Performance 155 Perspectives 154 Pie Chart 637 Playing Audio 681 Polling Base Rate 179 Polling Options 229 Polygon 204 Popup Calendar Component 652 Preview Mode 195 print keyword (Python) 155 Progress Bar 548 Projects Auditing 176 Authentication 176 Creating 78, 153 Deleting 78 Opening 153 Securing 243 Property Binding 228 Property Binding Types DB Browse 233 Expression 232 Indirect Tag 231 Property 232 SQL Query 233 SQLTags Historian 231 Tag 230 Property Expressions 404 Publish Mode 177 Pushbutton Component 499
-RRadio Button Component 523 Rectangle 204 Red Property 210 Relative Layout 220 Relative Rate 229 Report Designer 351 Report Viewer 303 Required Roles 176 Reset panels 154 Roles 243 Row Selector 296 Row Selector Component 687 RTF Viewer Component 572
-SSaving Reports 380 Script Modules 180 Selection and Alignment 346 Selection Tool 204 Shape Menu Difference 213 Division 213 Exclusion 213 Intersection 213 To Path 213 Union 213 Signal Generator 684 Simple Table 328 Slider Component 496 Sound Playback 681 SPC Chart 607 Spinner Component 481 SQLTags 57 SQLTags Historian 57 SQLTags Historian Pens 607 SQLTags Security 243 Square 204 SSL Certificate 471 Stale Overlay 218 Standard Properties 210 Status Chart 633 Stored Procedures Stored Procedure Group 194
2012 Inductive Automation
-QQuality Overlays 218 Query Base Rate 179 Query Browser 157
Index
821
Stroke Paint 211 Stroke Style 211 Styles Customizer 218 Substitution Keys 375 Substitution Keys: expressions, operators, and functions 378 Success Handshake 185 SUDS 428, 434, 436 Swich Versions, Graph 318, 391
-TTabbed Palette 203 Table Component 578, 589 Tables Basics 330, 392 Grouping 342 Overview 329 Row Versioning 340 Sorting and Filtering 338 Table Groups 345 Table Rows 336 Tabstrip Component 526 Tank Component 550 Template Instance 225 Template Master 225 Template Parameter 226 Templates About 225 Creating 226 Parameters 226 Using 226 Text Area Component 489 Text Editing 350 Text Field Component 474 Thermometer Component 569 Thread Viewer 155 Timer Component 682 Timezone Behavior 177 Toggle Button 503 Toolbar 355 total function - Aggregate Substitution Keys Touch Screen Mode 177 Touch Screen Support 219 Touchscreen Support 219 Transaction Groups Block 192 Historical 194
2012 Inductive Automation
Standard 191 Stored Procedure Group 194 Treeview Component 598 Trial Timeout Overlay 218 Triangle 204 Triggers 185 Tutorials Background 268, 281, 293 Basic Layout 270, 283 Creating the report 294 Getting Started 269, 282 Graphs 288 More changes 286 Overview 266, 280, 292 Row Versioning 276 Substitution Keys and Tables 272 Tutorial #1 - Table Example 266 Tutorial #2 - Adding Graphs 280 Tutorial #3 - PDF Example 292
-WWAV file 681 web service 428, 434, 436 Window Committing 177 Window Workspace 195 Windows About Window 198 Border Display Policy 198 Caching 198 Dock Position 198 Docking 198 Exporting 196 Importing 196 Layer 198 Multiple Instances 201 Notes 196 Open on Startup 198 Opening 201
376
822
Windows Organizing 196 Passing Parameters 202 Security 201 Swapping 201 Titlebar Display Policy 198 Workspace 153, 154
823
Back Cover