Skip to main content
Version: 1.0.4

Expression Functions

Expressions are evaluated wherever a value is computed from tags — expression tags in the namespace, expression bindings on a property, transforms on a binding, and map-transform rows.

Expressions are quality-aware: every operand carries a quality, and a result carries the worst quality of its inputs. A computed value can never appear healthier than the data behind it.

A tag is referenced as tag["<path>"], with the full namespace path in quotes — tag["Line1/Tank1/Level"]. A bare path such as Tank1/Level is not a tag reference; it parses as a division.

Numeric functions​

FunctionSignatureReturns
absabs(x)Absolute value
minmin(a, b)The smaller of two values
maxmax(a, b)The larger of two values
sqrtsqrt(x)Square root
clampclamp(x, lo, hi)x bounded to [lo, hi]
clamp(tag["Tank1/Level"], 0, 100)
max(tag["Motor1/Current"], tag["Motor2/Current"])
sqrt(abs(tag["FT101/DeltaP"])) * tag["FT101/KFactor"]

clamp takes the worst quality of all three operands — a bad limit makes the result bad, which is the correct behaviour when a limit comes from a tag.

Bit manipulation​

Industrial data packs many booleans into one integer — status words, alarm words, fault registers. These functions unpack them without a script.

FunctionSignatureReturns
bitAndbitAnd(a, b)Bitwise AND
bitOrbitOr(a, b)Bitwise OR
bitXorbitXor(a, b)Bitwise XOR
bitNotbitNot(a)Bitwise NOT
shiftLeftshiftLeft(a, n)a << n
shiftRightshiftRight(a, n)a >> n
getBitgetBit(value, pos)Bit pos as a boolean
setBitsetBit(value, pos, on)value with bit pos set or cleared

Bit positions are 0-based and valid for 0..63. An out-of-range position produces a bad-quality result rather than a silently wrong one.

getBit(tag["PLC1/StatusWord"], 3) is fault bit 3 set?
bitAnd(tag["PLC1/AlarmWord"], 0x00FF) != 0 any alarm in the low byte?
setBit(tag["PLC1/CommandWord"], 5, true) build a command word

Integer operations are performed at 64-bit width, so a status word wider than 32 bits behaves correctly.

Arithmetic and comparison​

Standard operators are available: + - * / %, == != < <= > >=, && || !, and parentheses.

(tag["Motor1/Current"] / tag["Motor1/RatedCurrent"]) * 100
tag["Tank1/Level"] > 80 && tag["Pump1/Running"]

Quality propagation​

SituationResult quality
All inputs GoodGood
Any input UncertainUncertain
Any input Bad or NotFoundBad
Non-numeric input to a numeric functionBad
Bit position out of 0..63Bad

This is why a widget bound to an expression can be relied upon to show bad quality: the expression layer does not launder it.

Where expressions appear​

PlaceNotes
Expression tagA tag whose value is an expression — computed once, then usable anywhere a tag is
Expression binding on a propertyComputes the property's value from one or more tags
Expression transform on a bindingReshapes a value the binding already fetched
Map transform — expression inputThe row matches when the expression is truthy
Map transform — expression outputComputes the mapped output
Threshold transformBand boundaries

The three differ by where the value lives, which is the decision worth getting right. An expression tag is computed once in the namespace and can be trended, alarmed and reused anywhere. An expression binding computes a property's value on one screen. An expression transform reshapes a value some other binding already fetched.

If the same expression appears on a second screen, it wanted to be a tag.

→ Expression tags · Property bindings

When to reach for a script instead​

Expressions are the right tool for arithmetic, bit unpacking and simple conditionals. Use a script transform or a Gateway script when you need:

  • Iteration or data structures
  • Database or historian access
  • Multi-step logic with intermediate state
  • Anything you would want to unit-test

An expression that needs a comment explaining it has usually outgrown being an expression.

Next​

→ Environment variables