Expression Language
The HiveMQ Data Intelligence expression language is a compact, domain-specific language for real-time calculations on your data. You define an expression once in your namespace, and the connected brokers evaluate the expression as data arrives.
You enter an expression in the Expression data source of a computed tag. For the step-by-step workflow, from the creation of the tag to the mapping of each variable, see Computations.
This page covers the syntax of the language itself: literals, variables, operators, and precedence. For the complete catalog of functions that you can call from an expression, with signatures and return types, see Functions.
Expression Structure
An expression produces exactly one value. The language has no statements, no assignments, and no semicolons. Each computed tag holds a single expression, and the result of that expression becomes the value of the tag.
To build a larger result, split the logic across several computed tags. A computed tag can reference another computed tag, so you can layer calculations rather than pack all logic into a single expression.
The language has no comment syntax. A // sequence in an expression causes a parse error.
|
Syntax
Literals
The language defines three kinds of literal values:
| Type | Syntax | Examples |
|---|---|---|
Integer |
One or more digits |
|
Decimal |
Digits with a decimal point |
|
Boolean |
The keyword |
|
| The language has no string literal. Text in quotation marks, such as HOT or NORMAL, is not valid syntax. To classify a value, return a number, for example a severity code, and interpret the code downstream. |
Integers and decimals both have arbitrary precision. For the data types that a variable or a function result can have, see Data Types.
Variables
A variable references live data, such as a tag, a payload field, or another computed tag.
A variable name starts with a letter or an underscore.
After the first character, a name can contain letters, digits, and underscores.
Variable names are case-sensitive, so motor_temp and Motor_Temp are two different variables.
Valid variable names include the following:
-
temperature_sensor_1 -
motor_speed -
production_count -
quality_index
The platform parses your expression and lists every name that it finds under Detected Variables. Map each detected variable to a tag before you save the computation. For the steps, see Map Each Variable to a Tag. The data type of a variable comes from the tag that you map to it. For the available types, see Data Types.
To use a tag’s stored history instead of its latest value, enable the Windowed option for the variable. A windowed variable supplies a series of values, which the aggregation functions consume.
Arithmetic Operators
| Operator | Operation | Example |
|---|---|---|
|
Addition |
|
|
Subtraction |
|
|
Multiplication |
|
|
Division |
|
|
Remainder |
|
|
Negation of a single operand |
|
Comparison Operators
A comparison operator takes two numeric operands and returns a boolean result.
| Operator | Operation | Example |
|---|---|---|
|
Greater than |
|
|
Greater than or equal to |
|
|
Less than |
|
|
Less than or equal to |
|
|
Equal to |
|
|
Not equal to |
|
Logical Operators
The language provides three logical operators for boolean operands:
-
&&(AND) returnstruewhen both operands aretrue. -
||(OR) returnstruewhen at least one operand istrue. -
!(NOT) inverts a single boolean operand.
Each line below is a separate expression:
temperature > 80 && humidity < 60
motor_active || backup_motor_active
!system_fault
(temperature > critical_temp || pressure > max_pressure) && !emergency_stop
Conditional Operator
The conditional operator selects one of two values based on a boolean condition.
The syntax is condition ? value_if_true : value_if_false.
error_count > 0 ? alert_level * 2 : normal_level
The operator is right-associative, so you can chain conditions to grade a value into more than two bands.
The expression below returns 2 above the critical threshold, 1 above the warning threshold, and 0 otherwise.
temperature > critical_threshold ? 2 : temperature > warning_threshold ? 1 : 0
| Because the language has no string literal, a conditional expression returns a number, not a text label. Map each number to a meaning in your namespace documentation, and keep the mapping consistent across tags. |
Function Calls
A function call consists of a function name and a pair of parentheses that hold zero or more comma-separated arguments. Each argument is itself an expression, so you can nest a call inside another call. Each line below is a separate expression:
SMA(temperature_readings)
MAX(temp_1, temp_2, temp_3)
ABS(current_temp - SMA(temp_history))
Function names are case-insensitive.
For example, SMA, sma, and Sma all refer to the same function.
Some functions take no arguments at all, such as INGESTION_TIME, and you write an empty pair of parentheses for them.
For every available function, with its arguments, constraints, and return type, see Functions.
Operator Precedence
The table below lists the precedence levels of the language, from the highest to the lowest. An operator with a higher precedence binds its operands before an operator with a lower precedence.
| Precedence | Operators | Description |
|---|---|---|
8 (highest) |
|
Primary expressions |
7 |
|
Logical NOT and negation, right-associative |
6 |
|
Multiplication, division, and remainder |
5 |
|
Addition and subtraction |
4 |
|
Relational comparison |
3 |
|
Equality comparison |
2 |
|
Logical AND |
1 |
|
Logical OR |
0 (lowest) |
|
Conditional operator, right-associative |
Two precedence rules deserve attention:
-
Relational operators bind tighter than the equality operators. The expression
a > 1 == b > 2compares the two boolean results. -
&&binds tighter than||. The expressiona || b && cevaluates asa || (b && c).
Use parentheses whenever the intended order is not obvious to a reader.
Variable Naming Conventions
Descriptive variable names keep an expression readable long after you write it. For industrial data, name each variable after the signal that it carries, and include the unit.
| Category | Example Names |
|---|---|
Sensor readings |
|
Production metrics |
|
Quality measurements |
|
Process parameters |
|
Best Practices
-
Use descriptive names.
motor_temperaturetells a reader more thantemp1. -
Include the unit in the name, for example
pressure_psiorflow_rate_gpm. -
Group related variables with a common prefix, for example
zone_1_tempandzone_2_temp. -
Use
snake_casefor multi-word names, and keep the convention across your namespace. -
Validate ranges. Check that a sensor value falls inside the expected range before you calculate with it.
-
Cover edge cases such as startup and shutdown with the conditional operator.
-
Keep thresholds explicit. Map each alarm level and warning level to its own variable. You can then adjust a limit without a rewrite of the expression.
-
Keep each expression small, and build a larger result from several computed tags.
Examples
The examples below show typical expressions for smart manufacturing. Each block holds one complete expression, which supplies the value of one computed tag.
Temperature Checks
Convert a Fahrenheit reading to Celsius:
(fahrenheit_sensor - 32) * 5 / 9
Check that a Celsius reading stays inside a target band:
celsius_temp >= 18 && celsius_temp <= 24
Detect a stable temperature, where the current reading stays close to its moving average. The expression below uses ABS and SMA:
ABS(current_temp - SMA(temp_history)) < 2.0
Grade the temperature into three severity codes, where 2 is critical, 1 is a warning, and 0 is normal:
temperature > critical_threshold ? 2 : temperature > warning_threshold ? 1 : 0
Production Line Metrics
Calculate Overall Equipment Effectiveness (OEE) from availability, performance, and quality rate:
(actual_runtime / planned_runtime) * (actual_output / target_output) * (good_parts / total_parts)
Present the same result as a percentage to two decimal places, with ROUND:
ROUND(oee * 100, 2)
Derive the current production rate from the number of events in a window, with COUNT:
COUNT(production_events) / time_window_hours
Check that the production rate stays consistent, with STDDEV:
STDDEV(hourly_production_rates) < acceptable_variance
LAST(efficiency_window) > FIRST(efficiency_window)
Quality Control
Calculate the upper control limit of a statistical process control (SPC) chart, three standard deviations above the mean:
SMA(quality_measurements) + (3 * STDDEV(quality_measurements))
Detect a measurement outside the control limits:
measurement > upper_control_limit || measurement < lower_control_limit
Measure the quality trend across a window:
LAST(quality_scores) - FIRST(quality_scores)
Predictive Maintenance
Compare the peak vibration in a window against the average vibration, with MAX_WINDOW:
MAX_WINDOW(vibration_data) / SMA(vibration_readings)
Combine several symptoms into a single maintenance indicator:
vibration_ratio > 3.0 || temperature > normal_temp + 10 || efficiency < normal_efficiency * 0.8
Energy Management
Calculate the energy efficiency of production, as output per unit of average power:
production_output / SMA(power_consumption)
Calculate the energy cost of the current consumption:
power_consumption * electricity_rate
Detect a demand level that approaches the contracted peak:
power_consumption > peak_threshold * 0.9
Process Control
Calculate a proportional control output from the deviation between the setpoint and the actual value:
proportional_gain * (target_value - actual_value)
Detect a flow rate that deviates from the target by more than the tolerance:
ABS(actual_flow - target_flow) > tolerance
Measure the pressure trend across a window:
LAST(pressure_window) - FIRST(pressure_window)
Detect a pressure condition that needs an intervention:
pressure > max_safe_pressure || (pressure_rising && pressure > warning_level)
Expression Results in the Namespace
An expression fits into the data flow of the platform as follows:
-
You map every variable in the expression to a tag or a field that supplies its values.
-
The connected broker evaluates the expression close to the data, as each new value arrives.
-
The result becomes the value of the computed tag. The platform stores the value and publishes it into the namespace like any other tag.
-
Downstream consumers read a computed tag exactly the way they read a raw tag. You can inspect the value in the Data Output and Charts tabs, and reference the tag from a further expression.
-
A windowed variable draws on a tag’s stored history, so an expression can compute over a time series instead of a single latest value.
For a worked example of higher-level metrics, such as Mean Time Between Failures (MTBF), see Beyond a Single Value: Complex Expressions.