Skip to main content
Version: 1.0.8

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"]

abs, min and max keep whole numbers whole: given two integer tags they compute exactly and return an integer. Mixing an integer with a decimal, or calling sqrt or clamp, works in decimals.

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. A shift count outside 0..63 is likewise an error rather than a silent wrap.

Time and duration​

There is no separate time type. An instant is a whole number of nanoseconds since 1970 (UTC) — the same as now — and a duration is a whole number of nanoseconds, so the two combine with ordinary arithmetic.

FunctionSignatureReturns
seconds · minutes · hours · daysminutes(n)A duration of n whole units
secondsBetween · minutesBetween · hoursBetween · daysBetweenhoursBetween(a, b)The time from instant a to b, as a decimal count of units
floorToSecond · floorToMinute · floorToHour · floorToDayfloorToHour(t)t rounded down to the start of its second, minute, hour or day (UTC)
yearOf · monthOf · dayOfmonthOf(t)The calendar field of instant t, in UTC
hourOf · minuteOf · secondOfhourOf(t)The clock field of instant t, in UTC
weekdayOfweekdayOf(t)The day of the week, 0 = Sunday, in UTC
now - tag["Pump1/LastRun"] > minutes(5) idle for more than five minutes?
hourOf(now) >= 6 && hourOf(now) < 14 inside the morning shift (UTC hours)

Every calendar function works in UTC, not the plant's time zone: hourOf(now) on a site at UTC+7 reads 7 hours behind the wall clock.

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