Skip to content
© 2026 The ThingsBoard Authors
Try for free

ThingsBoard Cloud

Choose your data region

Your data stays in the region you choose, for residency and compliance. No credit card required.

Rather run it yourself? Install on your own servers

TBEL Language Guide

This guide covers the TBEL syntax, data types, collections, and control-flow constructs. For the full list of built-in utility functions, see the Helper Functions reference.

TBEL is based on MVEL. A few syntax rules differ from JavaScript:

  • Use foreach instead of for...of / for...in. Traditional for loops are also supported.
  • Ternary expressions must be wrapped in parentheses when used outside an explicit if statement.
  • Multiple statements require semicolons; the semicolon after the final statement is optional.

Access properties from context objects directly:

msg.temperature
return (msg.temperature > 10 && msg.temperature < 20) ||
(msg.humidity > 10 && msg.humidity < 60);

Standard operator precedence applies. Use parentheses to control execution order.

Statements are separated by semicolons. The value of the last statement is the script’s return value:

var a = 2;
var b = 3;
a + b; // returns 5

TBEL automatically converts compatible types:

"123" == 123; // true

Maps are created inline and use a custom implementation with built-in memory tracking.

var map = {"temperature": 42, "nested": "508"};
map.temperature // dot notation
map.get("temperature") // method call
map["temperature"] // bracket notation

Safe-navigation prevents NullPointerException on missing keys:

if (map.?nonExistingKey.smth > 10) { }

Explicit entrySet():

foreach (element : map.entrySet()) {
element.getKey(); // or element.key
element.getValue(); // or element.value
}

Implicit (iterates over values):

foreach (value : map) {
// process each value
}
map.temperature = 0; // set value
map.put("humidity", 73); // add entry
map.putIfAbsent("temperature1", 73); // add if missing
map.replace("temperature", 56); // replace value
map.replace("temperature", 56, 42); // conditional replace
map.remove("temperature"); // remove entry
var keys = map.keys(); // get all keys
var values = map.values(); // get all values
var size = map.size(); // entry count
var memorySize = map.memorySize(); // memory in bytes
map.sortByKey(); // sort by key in-place
var sorted = map.sortByValue(); // sort by value in-place
map.putAll({"test": 12, "input": {"http": 130}}); // merge another map
isMap(map); // type check → true
var original = {};
original.humidity = 73;
var unmodifiable = original.toUnmodifiable();
unmodifiable.put("temperature1", 96); // throws error: Map is unmodifiable

Lists use a custom implementation with memory tracking. Only inline creation is permitted.

var list = ["A", "B", "C"];
list[0]; // "A"
list.size(); // 3
foreach (item : list) {
var smth = item;
}
for (var i = 0; i < list.size; i++) {
var smth = list[i];
}
list.add(3, "thingsboard"); // insert at index
list.push("thingsboard"); // append to end
list.unshift("r"); // prepend to start
list.addAll(["thingsboard", 4, 67]); // append all elements
list.addAll(2, ["x", "y"]); // insert all at index
var removed = list.remove(2); // remove by index
list.remove("C"); // remove by value
var first = list.shift(); // remove and return first
var last = list.pop(); // remove and return last
var spliced = list.splice(3); // remove from index to end
list.splice(2, 2); // remove 2 elements at index 2
list.splice(1, 4, "start", 5, "end"); // remove 4, insert replacements
list.set(3, "65"); // replace at index
list[1] = "98"; // bracket assignment
list.sort(); // ascending sort (default)
list.sort(true); // ascending
list.sort(false); // descending
list.reverse(); // reverse in-place
list.fill(67); // fill entire list
list.fill(4, 1); // fill from index 1
list.fill(2, 1, 4); // fill range [1, 4)

These return a new list without modifying the original:

var sorted = list.toSorted(); // new sorted list (ascending)
var sortedDesc = list.toSorted(false); // new sorted list (descending)
var reversed = list.toReversed(); // new reversed list
var sliced = list.slice(0, 2); // new sublist [0, 2)
var replaced = list.with(1, 69); // new list with index 1 replaced
var merged = list.concat(otherList); // new concatenated list
var str = list.join(); // join elements into string
var spliced = list.toSpliced(1, 0, "Feb"); // new list with splice applied
var length = list.length();
var memorySize = list.memorySize();
var idx = list.indexOf("B", 1); // first index of "B" starting from 1
list.validateClazzInArrayIsOnlyNumber(); // validate numeric content
isList(list); // type check → true
var original = [];
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: List is unmodifiable

Sets are ordered collections that prevent duplicates.

var set1 = toSet(["B", "A", "C", "A"]); // from list (3 elements — "A" deduplicated)
var set2 = createSet(); // empty set
var set3 = createSet(["A", "B", "C"]); // from list
var set4 = newSet(); // empty set
foreach (item : set) {
// process item
}
var arr = set.toArray();
for (var i = 0; i < set.size; i++) {
var item = arr[i];
}
set.add(35); // add single element (returns true if new)
set.addAll(otherSet); // merge another set
set.remove(4); // remove element
set.clear(); // remove all elements
set.contains("A"); // membership check → true/false
set.size(); // element count
set.toArray(); // convert to array
set.toList(); // convert to list
set.clone(); // shallow copy
isSet(set); // type check → true
set.sort(); // ascending in-place
set.sort(true); // ascending in-place
set.sort(false); // descending in-place
var sorted = set.toSorted(); // new sorted set (ascending)
var sortedDesc = set.toSorted(false); // new sorted set (descending)
var original = createSet();
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: Set is unmodifiable

TBEL supports arrays only for primitive types. String indexing returns characters, and string arrays are automatically converted to lists.

var array = new int[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
var str = "My String";
var ch = str[0]; // 'M'
isArray(array); // true

Custom function example:

function sum(list) {
var result = 0;
for (var i = 0; i < list.length; i++) {
result += list[i];
}
return result;
}
var total = sum(array); // 6

Single or double quotes:

"This is a string literal"
'This is also string literal'

Escape sequences: \\, \n, \r, \u#### (Unicode), \### (octal).

125 // decimal integer
0353 // octal
0xAFF0 // hexadecimal
10.503 // double
94.92d // explicit double
14.5f // float
104.39484B // BigDecimal
8.4I // BigInteger
true
false
null
nil // alias for null

TBEL allows limited use of Java classes from java.util and java.lang:

var foo = Math.sqrt(4); // 2.0

Convert numbers to hex, octal, or binary using Integer.toString():

var b16 = Integer.toString(0x1A, 16); // "1a"
var b10 = Integer.toString(0x1A, 10); // "26"
var b8 = Integer.toString(0x1A, 8); // "32"
var b2 = Integer.toString(0x1A, 2); // "11010"

Negative numbers:

var i16 = Integer.toString(-255, 16); // "-ff"
var i10 = Integer.toString(-255, 10); // "-255"
var i8 = Integer.toString(-255, 8); // "-377"
var i2 = Integer.toString(-255, 2); // "-11111111"

Float and double hex strings:

var f0 = 7823764.8374;
var f16 = Float.toHexString(f0); // "0x1.dd8654p22"
var dd0 = 99993219.156013e-002;
var dd16 = Double.toHexString(dd0); // "0x1.e83f862142b5bp19"

Long conversion:

var l16 = Long.toString(9223372036854775807, 16); // "7fffffffffffffff"
var l10 = Long.toString(9223372036854775807, 10); // "9223372036854775807"
var l8 = Long.toString(9223372036854775807, 8); // "777777777777777777777"
var l2 = Long.toString(9223372036854775807, 2); // "111...111" (63 ones)

Creating new instances of Java classes is not allowed:

java.util.Collections.reverse(list); // allowed — static method call
list = new java.util.ArrayList(); // NOT allowed — constructor call
var metadataStr = JSON.stringify(metadata);
var metadata = JSON.parse(metadataStr);
if (temperature > 0) {
return "Greater than zero!";
} else if (temperature == -1) {
return "Minus one!";
} else {
return "Something else!";
}
temperature > 0 ? "Yes" : "No";
var numbers = [1, 2, 3];
var sum = 0;
foreach (n : numbers) {
sum += n;
}

Strings are iterable character-by-character:

foreach (c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
// process each character
}
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += i;
}
while (isTrue()) {
doSomething();
}
until (isFalse()) {
doSomething();
}
do {
x = something();
} while (x != null);
do {
x = something();
} until (x == null);