Expression Language and Syntax
Expression Language​
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. In most cases, expressions only 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 Temperature tag 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 * {My Temperature Tag} + 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 °F to the end of the label so that the user knew the units of the temperature. You could simply use some string concatenation in your expression, like this:
(1.8 * {Some Folder/Some Tag} + 32) + " °F"
For more information see Expression Bindings in Vision or Expression Bindings in Perspective.
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, and 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 any one of the following:
- Number
- Boolean
- String
- Bound Tag
- Bound property
- Function call
- Dataset access
- 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.456
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"
In addition, the following escape characters are available:
Character | Description |
---|---|
\n | New line |
\t | Tab |
\r | Carriage return |
// The words "Hello" and "User" will be placed on separate lines
"Hello\nUser"
// Each "\t" will inject a tab
"Lots\tOf\tSpace"
Boolean values are represented with True and False (without quotation marks). Note that boolean values are case insensitive, so true is the same as True. For simplicity, we recommend writing True and False, since Python uses similar casing for boolean values.
// Multiple ways to specify a true boolean value.
True
true
tRuE
TRUE
Another value you can specify is a null literal, using one of the following:
null
None
none
You can also use scientific notation to specify numeric constants, such as 1.3e5
.
Operators​
You can use these arithmetic, logical, and bit-shifting operators to combine expressions.
Operator | Name | Description |
---|---|---|
// | Comments | Allows for comments following this operator. |
- | Unary Minus or Subtraction | If both preceded by a number, then returns a value by subtracting the operand right from the operand on the left of the operator:If preceded by anything else (or nothing, such as the start of the expression) and is followed by a number, this operator will negate the number.
|
! | Not | Logical opposite of a boolean. |
^ | Power | Raises a number to the power of another number. |
% | Modulus | Modulus or remainder of two numbers. a%b is the remainder of a÷b. |
* | Multiply | Multiplies the number on the left of the operator by the number on the right of the operator. |
/ | Divide | Divides the number on the left of the operator by the number on the right of the operator. |
+ | Add or Concatenation | If both operands are numbers, this will add them together. Otherwise treats arguments as strings and performs concatenation.
|
- | Subtraction | Subtracts the number on the right of the operator from the number on the left of the operator. |
~ | Bitwise NOT | Examines the bits of an operand, and performs performs logical negation: bits with a value of 0 become 1, and vice versa. |
& | Bitwise AND | Examines the bits of two operands, and performs a logical AND to each set, comparing the bits in each position from both sets. Returns true for any position where the bits being compared are true.
|
| | Bitwise OR | Examines the bits of two operands, and performs a logical OR to each set, comparing the bits in each position from both sets. Returns true for any position where either bit being compared is true.Â
|
xor | Bitwise XOR | Examines the bits of two operands, and performs a logical exclusive OR to each set, comparing the bits in each position from both sets. Returns true for any position where only one of the bits are true.
|
<< | 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 | Logical less-than test between two numbers. Returns a boolean. |
>= | Greater Than or Equal To | Tests if the operand on the left is greater or equal to the operand on the right. Returns a boolean. |
<= | Less Than or Equal To | Tests if the operand on the left is less than or equal to the operand on the right. Returns a boolean. |
= | 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 Matching | Compares the left-hand value with the pattern on the right side. The pattern may 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 in Vision, 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 icon and Insert Tag icon 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 ["Column_Name"] //Returns the value from the first row at the given column name.
Dataset_Expression [Column_Index] //Returns the value from the given column at the first row.
Dataset_Expression [Row_Index, "Column_Name"] //Returns the value from the given row at the given column name.
Dataset_Expression [Row_Index, Column_Index] //Returns the value from the given row at the given 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"]
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"])
Collection and Mapping access​
// Returns the third elements in the array
{An Array}[2]
Keys in maps (dictionaries and JSON objects) can be access with square brackets and string name of the desired key:
// Returns the value of "myKey"
{A Map}["myKey"]
Expression 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, ...)
Whitespace and Comments​
Whitespace, such as spaces, tabs and newlines, are largely ignored in the expression language. It is often helpful to break your expression up onto multiple lines for clarity. Comments are delimited by two forward slashes. This will make the rest of that line be ignored. This example shows an if function spread over four lines with comments annotating the arguments.
if( {Root Container.UseTagValueOption.selected},
{MyTags/SomeValue}, // Use the Tag value.
"Not Selected" // Use default value if the user doesn't check the box.
)
Tag Paths​
While referencing a tag path in expressions, you may see some special notation, such as "~" and "[.]". More information on this notation can be found on the Tag Paths page.
Additional Examples​
The following headings demonstrate many simple examples that better demonstrate the expression language's syntax.
String Concatenation​
Expression Binding – Concat Strings
Watch the videoYou can use an expression binding to concatenate strings resulting in a new string that reflects the concatenation of different strings.
The function starts with CONCAT() and inside the function is a list of strings. They can be manually typed like "42" or they can come from Tags or properties.
Example 1
concat("The answer is: ", "42") //returns "The answer is: 42"
Example 2
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'
Celsius to Fahrenheit​
Use an expression binding to convert a temperature from Celsius to Fahrenheit. This is an example of how an expression binding can handle calculations.
{celsiusTemp} * 9/5 + 32
The reference to the Celsius temperature can come from a property or a Tag. As the property or the Tag changes, so does the expression binding.
Format Date​
Expression Binding – Format Date
Watch the videoYou can format a date in an expression binding by using the dateFormat
and now
functions.
To make a label that updates to show the current time:
Drag a Label component onto the window.
Select the label's Text property binding icon and select Expression binding.
Enter the following code into the expression, and click OK.
dateFormat(now(1000), "MMM d, yyyy hh:mm:s a")
The
dateFormat
function takes two arguments. The first argument is any date type variable. This can include another function (like now) that returns a date type. The second argument refers to the date format that you want returned. The now function returns the current time and in this case it will update every second. For more information on the date formatting expression, see the dateFormat Expression Functions page.
Date Manipulations​
Expression Binding – Date Manipulations
Watch the videoYou can manipulate dates in expression bindings such as a date addition/subtraction with the dateArithmetic
function. This is important when you want to use the expression bindings to select a date that is offset by a certain amount.
The following example will return the time 15 minutes ago by using the dateArithmetic expression function:
dateArithmetic(now(), -15, "minute")
Bit Functions​
Expression Binding – Bit Functions
Watch the videoYou can use various bit functions in expression bindings like getBit
to return individual bits of a word.
Example 1
Assuming a Tag path 'Folder/BitTag', the following would return the binary representation of the Tag's value at the 0 position
getBit({Folder/BitTag}, 0)
For more details on the getBit function, please see the getBit page in the Appendix.
Example 2
You have 3 bits in a PLC, only one of which will be on at a time. You want to turn these 3 bits into a single integer (0,1,2) to drive a component's Styles. Bind a custom integer property to:
binEnum({MyTags/Bit1}, {MyTags/Bit2}, {MyTags/Bit3})
Switch​
Expression Binding – Switch
Watch the videoYou can use the switch function in expression bindings to evaluate conditional statements. This function acts like the switch statement in C-like programming languages. It takes the value argument and compares it to each of the case1 through caseN expressions.
The following example returns the string Running
when it is given the value of 1. Its options are 0,1, and 2. And when comparing the value to the options the switch statement returns one of the corresponding results. If a result cannot be found, a fail-over option is returned.
switch(
1,
0, 1, 2,
"Off","Running","Fault",
forceQuality("!BAD STATE!",0))
Checking Conditions​
Expression Binding – Checking Conditions
Watch the videoYou can use expression bindings to return true or false based on different conditions.
Example 1
Consider the following expression that references the Tag with a path of 'Folder/Machine State':
{Folder/Machine State} = 0
The above expression simply tests the value of the Machine State Tag. If the value of the Machine State Tag is ever equal to 0 then the above expression would return true. In every case where Machine State is not equal to 0, then the expression would return false.
Example 2
It is possible to check for multiple conditions in the same expression. If you have two boolean Tags and you only want the expression to return true if both Tags are true then the binding would look like:
{boolTag1}=True && {boolTag2}=True
Tag History​
You can use expression tags to display tag history data that is stored in a database. The example below demonstrates how to pull a single tag’s average history on an expression tag using a Project Library script and the runScript function. The expression used here can be altered to incorporate multiple tag values if desired. The tag history used for this example is from the Sine0 tag in the Quick Start configuration. This was enabled in our project by accessing the default Tag Provider in Tag Browser dropdown, selecting Browse Devices to import the Sine0 tag, and selecting History > History Enabled > true and a Storage Provider in the Sine0 Tag Editor.
Since this method uses both project library scripting and requires access to tag data, make sure your project name is defined in the Gateway Scripting Project property on your Gateway Webpage.
In your Project Browser, expand the Scripting dropdown.
Right-click Project Library and select New Script.
In the name field, enter TagHistory.
Select Create Script.
Paste the following script:
def tagHistory(tagpath):
results = system.tag.queryTagCalculations(paths=[tagpath], calculations=['Average'], noInterpolation=False)
return results.getValueAt(0,1)noteSee the system.tag.queryTagCalculations page for more information on the function.
Save your project.
Navigate to the Tag Browser and select the Add Tag icon.
Select New Standard Tag > Expression Tag.
Click the Expression Edit icon and paste the following expression into the pop-up field:
runScript("TagHistory.tagHistory('[default]/sine0')", 0)
noteSee the runScript page for more information on the function.
Click Apply.
Change the Execution Mode to Fixed Rate.
Click OK.