Expression syntax reference

This reference documents the complete syntax of the Navixy IoT Logic Expression Language, including literals, operators, functions, and data types. For conceptual information about how expressions work within IoT Logic, see the Expression language overview.

Basic syntax elements

The expression language uses JEXL (Java Expression Language) as its foundation, with IoT-specific enhancements for device data processing.

Literals

Literal Type
Syntax
Example

Integer

Digits 0-9

42

Float

Digits with decimal point, optional f or F suffix

3.14, 42.0f

Long

Digits with l or L suffix

42L

Double

Digits with decimal point and d or D suffix

42.0d

Hexadecimal

0x or 0X prefix, then hex digits

0xFF, 0x1A2B

Octal

0 prefix, then octal digits

010

Scientific notation

Standard scientific notation with e or E

1.5e-10

String (double quotes)

Text enclosed in double quotes

"Hello world"

String (single quotes)

Text enclosed in single quotes

'Hello world'

String escape sequences

Backslash escape character

"Line 1\nLine 2", "Quote: \"text\""

Boolean

Keywords true or false

true, false

Null

Keyword null

null

Identifiers and attribute names

Attribute names must exactly match names from device telemetry. To make sure you use correct names, you can:

Attribute access

Short syntax (current values)

Direct attribute references provide the simplest way to access current device data in expressions. This syntax omits the value() function, using implicit default parameters for clean, readable formulas.

Use for: Simple calculations with current data

Syntax: attribute_name

How it works: Short syntax is a convenient shorthand that automatically uses value() function with default parameters:

  • temperature is equivalent to value('temperature', 0, 'all')

  • Default index: 0 (current value)

  • Default validation: 'all' (includes null values)

Examples:

Expression
Purpose

temperature * 1.8 + 32

Unit conversion

speed > 80

Threshold check

fuel_level + reserve_tank

Combine attributes

Full syntax (historical and advanced)

The explicit value() function unlocks historical data access and precise control over null handling. This syntax is essential for trend analysis, change detection, and any calculation requiring data from previous readings.

Use for: Historical data access, trend analysis, null handling control

Function: value(attribute_name, index, validation)

How it works: Full syntax explicitly defines all parameters of the value() function, enabling access to historical data and control over null handling.

Parameter
Values
Description

attribute_name

String

Attribute name from device

index

0-12

0=current, 1=previous, 12=oldest

validation

'all' | 'valid'

'all'=include nulls, 'valid'=skip nulls

Parameter behavior explained:

Given history: [25.5, null, 24.8, null, 23.2] (index 0 to 4)

Expression
Index
Validation
Result
Explanation

value('temp', 1, 'all')

1

Include nulls

null

Returns value at exact index 1, which is null

value('temp', 1, 'valid')

1

Skip nulls

24.8

Skips null at index 1, returns first valid value

value('temp', 2, 'all')

2

Include nulls

24.8

Returns value at exact index 2

value('temp', 2, 'valid')

2

Skip nulls

23.2

Skips nulls at indices 1 and 3, returns second valid value

When to use each validation mode:

  • 'all' - For time-based analysis where null indicates missing data at specific time.

  • 'valid' - For trend analysis where you need actual values regardless of gaps. Important: Returns the last non-null value, which can belong to another (earlier) reading. Consider it carefully when building expressions.

Formula examples:

Note that the examples in the table below showcase also a mix of short and full syntaxes used in the same formulas.

Use case
Formula
Calculation

Detect temperature change

temperature - value('temperature', 1, 'all')

Difference between current and previous reading, null if previous missing

Calculate acceleration

speed - value('speed', 1, 'valid')

Difference between current and last valid reading, ignoring gaps

Detect gradual trends

(temp - value('temp', 2, 'valid')) / 2

Average change per reading over last 2 valid readings

Sustained speeding alert

speed > 80 && value('speed', 1, 'valid') > 80

True if current AND previous valid reading both exceed 80

Smooth sensor fluctuations

(value('pressure', 0, 'valid') + value('pressure', 1, 'valid') + value('pressure', 2, 'valid')) / 3

Average of 3 most recent valid pressure readings

Operators

Arithmetic operators

Operator
Operation
Example

+

Addition

temperature + 10

-

Subtraction

fuel_level - 5

*

Multiplication

temperature * 1.8

/

Division

distance / time

%

Modulus (remainder)

value % 100

Comparison operators

Operator
Comparison
Example

==

Equal

speed == 80

!=

Not equal

status != 0

<

Less than

temperature < 0

<=

Less than or equal

fuel_level <= 10

>

Greater than

speed > 80

>=

Greater than or equal

voltage >= 12.0

Logical operators

Operator
Alternative
Operation
Example

&&

and

Logical AND

speed > 80 && engine_on

||

or

Logical OR

temp < 0 || pressure_low

!

not

Logical NOT

!door_closed

Pattern matching operators

Operator
Description

=~

Checks if the value of the left operand is in the set of the right operand. For strings, checks for regex pattern match

!~

Checks if the value of the left operand is not in the set of the right operand. For strings, checks for regex pattern mismatch

=^

Checks that the left string operand starts with the right string operand

!^

Checks that the left string operand doesn't start with the right string operand

=$

Checks that the left string operand ends with the right string operand

!$

Checks that the left string operand doesn't end with the right string operand

Ternary conditional

Syntax: condition ? value_if_true : value_if_false

Example: speed > 80 ? "Speeding" : "Normal"

Operator precedence

Operators are evaluated in order from highest to lowest precedence:

Precedence
Operators
Description

1 (highest)

( )

Parentheses

2

!, not, - (unary), + (unary)

Unary operators

3

*, /, %

Multiplication, division, modulus

4

+, -

Addition, subtraction

5

<, <=, >, >=

Comparison

6

==, !=

Equality

7

&&, and

Logical AND

8

||, or

Logical OR

9 (lowest)

? :

Ternary conditional

Use parentheses to override precedence or clarify complex expressions.

Core functions

Time and data access functions

Function
Parameters
Description

value(attribute_name, index, validation)

attribute_name (String)

index (Integer, 0-12)

validation (String: 'all' or 'valid')

Attribute value at specified historical position

genTime(attribute_name, index, validation)

attribute_name (String

index (Integer, 0-12)

validation (String: 'all' or 'valid')

Device-side generation timestamp (milliseconds) for attribute value. Default: now()

srvTime(attribute_name, index, validation)

attribute_name (String

index (Integer, 0-12

validation (String: 'all' or 'valid')

Server-side reception timestamp (milliseconds) for attribute value. Default: now()

Usage examples:

Use case
Expression

Default timestamp (current time)

"server_time": "now()" or "generation_time": "now()"

Data age

now() - genTime('temperature', 0, 'all')

Transmission delay

srvTime('temperature', 0, 'all') - genTime('temperature', 0, 'all')

Time offset

genTime('temperature', 0, 'valid') + 120000

For calculated attributes in IoT Logic flows, if genTime and srvTime are not explicitly specified, both default to now() (current timestamp).

Bit-level operations

The util: namespace provides specialized functions for binary data processing, data format conversions, and string operations.

Bit-level functions

Function
Parameters
Result type
Description

util:signed(n, bytesAmount)

n (Number): unsigned number

bytesAmount (int): bytes (1, 2, 4, 8)

Long

Converts an unsigned integer of bytesAmount bytes to a signed two's-complement value.

Note: It does not convert signed to unsigned.

util:checkBit(n, bitIndex)

n (Number): number to check

bitIndex (int): bit position (0=LSB)

Boolean

Check if bit is set (true) or not (false)

util:bit(n, bitIndex)

n (Number): number to check

bitIndex (int): bit position (0=LSB)

Integer

Get bit value (1 or 0)

util:bits(n, firstBitIndex, lastBitIndexInclusive)

n (Number): source number

firstBitIndex (int): start position

lastBitIndexInclusive (int): end position

Long

Extract bit range; reverse if lastBitIndexInclusive < firstBitIndex. Returns null if indexes are out of bounds.

util:bytes(n, firstByteIndex, lastByteIndexInclusive)

n (Number): source number

firstByteIndex (int): start position

lastByteIndexInclusive (int): end position

Long

Extract byte range; byte swap if lastByteIndexInclusive < firstByteIndex. Returns null if indexes are out of bounds.

Examples:

Expression
Result
Use case

util:signed(65535, 2)

-1

Convert 0xFFFF to signed 16-bit

util:checkBit(4, 2)

true

Check status flag bit

util:bits(1321678, 0, 3)

14

Extract 4-bit sensor value

util:bytes(11189196, 1, 0)

52411

Little-endian byte swap

HEX string operations

Binary data is processed as HEX strings (uppercase) for readability and protocol compatibility.

Function
Parameters
Result type
Description

util:hex(n)

n (Number): value to convert

String

Convert to HEX string; 16 chars for negative/float, variable for positive int; null if invalid

util:hex(n, bytesAmount)

n (Number): value to convertbytesAmount (int): byte length

String

Convert to fixed-length HEX (bytesAmount * 2 chars); pad/truncate as needed; null if invalid

util:hexToLong(s)

s (String): HEX string

Long

Convert HEX string to Long; null if invalid

util:hexToLong(s, firstByteIndex, lastByteIndexInclusive)

  • s (String): HEX string

  • firstByteIndex (int): start byte (0=left). Byte 0 is the leftmost (most-significant) byte of the HEX string.

  • lastByteIndexInclusive (int): end byte

Long

Extract bytes from HEX string to Long; reverse if lastByteIndexInclusive < firstByteIndex; null if invalid

Examples:

Expression
Result
Use case

util:hex(127)

"7F"

Variable length conversion

util:hex(127, 6)

"00000000007F"

Fixed-width formatting

util:hexToLong("FF")

255

Parse HEX value

util:hexToLong("AABBCC", 1, 0)

48042

Little-endian parsing

Data format conversions

Function
Parameters
Result type
Description

util:fromBcd(o)

o (Object): BCD number

Long

Convert BCD to decimal; null if invalid BCD

util:toBcd(o)

o (Object): decimal (0 to 9999999999999999)

Long

Convert decimal to BCD; null if out of range

util:toFloat(o)

o (Object): Long (IEEE 754 bits) or Double

Float

Convert to Float; interpret Long as IEEE 754 bits; null if invalid

util:toDouble(o)

o (Object): Long (IEEE 754 bits) or Double

Double

Convert to Double; interpret Long as IEEE 754 bits; null if invalid

Examples:

Expression
Result
Use case

util:fromBcd(0x1234)

1234

Decode BCD device ID

util:toBcd(1234)

0x1234 (4660)

Encode for BCD protocol

util:toFloat(1065353216)

1.0

Decode IEEE 754 float

String padding functions

Function
Parameters
Result type
Description

util:leftPad(o, length)

o (Object): value

length (int): target length

String

Pad left with "0" to length; null if input null

util:leftPad(o, length, padStr)

o (Object): value

length (int): target length

padStr (String): padding

String

Pad left with custom string; null if input null

util:rightPad(o, length)

o (Object): value

length (int): target length

String

Pad right with "0" to length; null if input null

util:rightPad(o, length, padStr)

o (Object): value

length (int): target length

padStr (String): padding

String

Pad right with custom string; null if input null

Examples:

Expression
Result

util:leftPad(123, 5)

"00123"

util:leftPad(7, 3, "*")

"**7"

util:rightPad(123, 5)

"12300"

Data types and type handling

Supported data types

Data Type
Description
Examples

Integer

Whole numbers

42, -100, 0xFF

Long

Large integers with L suffix

42L, 9999999999L

Float

Floating-point with optional f suffix

3.14, 42.0f

Double

Double-precision floating-point

3.14, 42.0d

String

Text enclosed in quotes

"text", 'text'

Boolean

True or false values

true, false

HEX String

Uppercase hexadecimal representation

"FF", "1A2B"

Null

Absence of value

null

Null propagation

Rule: Null values propagate through expressions without errors. When any operand is null, the expression typically evaluates to null.

Expression
Result
Notes

null + 5

null

Arithmetic with null

temperature + 10

null

If temperature is null

null == null

true

Null equality

null != 5

true

Null comparison

null > 0

false

Null in comparison

In Logic nodes expressions evaluating to null are treated as false and route through ELSE path.

Error conditions resulting in null

Condition
Expression example
Result

Invalid function input

util:hexToLong("invalid")

null

Invalid BCD

util:fromBcd(0x99A0)

null

Missing historical data

value('temperature', 5, 'valid')

null (if < 5 valid readings)

Type mismatch

"text" + 123

null

Expression patterns

Pattern type
Expression
Use case

Unit conversion

temperature * 1.8 + 32

Celsius to Fahrenheit

distance / 1.609

Kilometers to miles

volume * 0.264172

Liters to gallons

Change detection

temperature - value('temperature', 1, 'all')

Temperature change

value('fuel_level', 1, 'valid') - fuel_level

Fuel consumption

speed - value('speed', 1, 'valid')

Speed change

Binary parsing

util:signed(util:hexToLong(hex_data, 0, 1), 2) / 10.0

Signed temp from HEX

util:checkBit(status_flags, 0)

Check status flag

util:bits(status_word, 4, 7)

Extract sensor value

Time calculations

now() - genTime('temperature', 0, 'all')

Data age

srvTime('temp', 0, 'all') - genTime('temp', 0, 'all')

Transmission delay

genTime('temperature', 0, 'valid') + 120000

Time offset (2 min)

Quick reference tables

Core functions summary

Function
Result type
Primary use

value(attr, idx, val)

Any

Historical attribute value

genTime(attr, idx, val)

Long

Device generation time (default: now())

srvTime(attr, idx, val)

Long

Server reception time (default: now())

Bit operations summary

Function
Result type
Primary use

util:signed(n, bytes)

Long

Convert unsigned to signed

util:checkBit(n, bit)

Boolean

Check if bit is set

util:bit(n, bit)

Integer

Get bit value (0/1)

util:bits(n, firstBitIndex, lastBitIndexInclusive)

Long

Extract bit range

util:bytes(n, firstByteIndex, lastByteIndexInclusive)

Long

Extract byte range

HEX operations summary

Function
Result type
Primary use

util:hex(n)

String

Number to variable-length HEX

util:hex(n, bytes)

String

Number to fixed-length HEX

util:hexToLong(s)

Long

HEX string to number

util:hexToLong(s, firstByteIndex, lastByteIndexInclusive)

Long

Extract bytes from HEX string

Data conversion summary

Function
Result type
Primary use

util:fromBcd(o)

Long

BCD to decimal

util:toBcd(o)

Long

Decimal to BCD

util:toFloat(o)

Float

IEEE 754 bits to float

util:toDouble(o)

Double

IEEE 754 bits to double

String operations summary

Function
Result type
Primary use

util:leftPad(o, len)

String

Pad left with "0"

util:leftPad(o, len, pad)

String

Pad left with custom string

util:rightPad(o, len)

String

Pad right with "0"

util:rightPad(o, len, pad)

String

Pad right with custom string

Last updated

Was this helpful?