Improved JavaScript-Rule Features in openHAB 3.2

Johannes Schildgen
(Smart)²Home
Published in
6 min readDec 31, 2021

In December 2021, the new release openHAB 3.2 was published. Similar to other releases, it contains bug fixes, new addons and bindings, and a lot of improvements. As the 3.2 release drastically improves the way of how to create rules using JavaScript / ECMAScript, this article will present these changes, compared to older openHAB releases (≤3.1).

Upgrade to openHAB 3.2

A sudo apt update && sudo apt upgrade will not upgrade your openHAB from 3.1.1 to 3.2. But you can use the openhabian-config tool to start the upgrade:

sudo openhabian-config
Update dialogue in openhabian-config

In the next step of the update process, you can choose between “openHAB 3" (that’s the current stable version), “main” (very latest version), and “stable” (that’s the old openHAB 2). The recommendation is to choose “openHAB 3”. It will update your system to openHAB 3.2

When running openHAB on a Raspberry Pi using openHABian, a hint is shown that you can (but you do not have to) upgrade to the newest openHABian release based on Raspberry Pi OS Bullseye. To do so, use a search engine to find out how to upgrade from Debian Buster to Bullseye.

To complete the upgrade to openHAB 3.2, choose “openHAB Related” in the menu of the openhabian-config tool, and then “openHAB Release”. Now, after the update is installed and openHAB is restarted, your system runs on openHAB 3.2. You can inspect your version number in the openHAB UI under “Help & About”.

Install JSScripting Language

The new language features presented in this article cannot be used within rules that use the old ECMA-262 Edition 5.1 which was the default for openHAB 3.1 and before. To install the new scripting engine, click on:
“Settings” -> “Addons” -> “Automation” -> “JSScripting” -> “Install”

A detailed documentation of all commands within this library can be found on https://github.com/openhab/openhab-js/

How to do stuff in JSScripting?

The following table shows the new commands in JSScripting compared to how it was done before openHAB 3.2:

╔══════════╦═══════════════════════════════╦══════════════════════╗
║ ║ old wayJSScripting
╠══════════╬═══════════════════════════════╬══════════════════════╣
Logging ║ var logger = ... ║ console.info("Hello")║
║ ║ logger.info("Hello") ║ ║
╠══════════╬═══════════════════════════════╬══════════════════════╣
Get Item ║ itemRegistry.getItem("A") ║ items.getItem("A") ║
State ║ .getState() ║ .state ║
╠══════════╬═══════════════════════════════╬══════════════════════╣
Command ║ events.sendCommand("A", "ON") ║ .sendCommand("ON") ║
╠══════════╬═══════════════════════════════╬══════════════════════╣
History ║ PersistenceExtensions... ║ .history ║
H. State ║ .historicState(itm, t) ║ .historicState(t) ║
Average ║ .averageSince(itm, t) ║ .averageSince(t) ║
╠══════════╬═══════════════════════════════╬══════════════════════╣
Notify ║ NotificationAction. ║ actions ║
║ ║ sendBroadcastNotification(m) ║ .NotificationAction ║
║ ║ ║ .sendBroadcast ║
║ ║ ║ Notification(m) ║
╚══════════╩═══════════════════════════════╩══════════════════════╝

In the old scripting engine, classes like PersistenceExtensions or NotificationAction needed to be imported first. This is not necessary anymore.

Timeouts and Intervals

setTimeout executes a given piece of code in x milliseconds. setInterval does the same, but it executes it again and again every x milliseconds.

console.log("Hello");
setTimeout(() => { console.log("1 Second later"); }, 1000);

Example Script

The following code shows examples of how to use the new commands. First, it makes a console output with the washing machine’s consumption 30 minutes ago. Then it sends a push notification to your mobile phone if the washing machine currently consumes less than 5W and has an average consumption of more than 5W within the last 30 minutes. Furthermore, in that case, the kitchen lights are turned on, and one second later, turned off again.

var current_state = items.getItem("Washingmachine_Power").state;var old_state = items.getItem("Washingmachine_Power").history.historicState(
new Date(new Date().getTime() - (30 * 60 * 1000)));
console.info("Old state: "+old_state);var avg_30 = items.getItem("Washingmachine_Power").history.maximumSince(
new Date(new Date().getTime() - (30 * 60 * 1000)));
if(current_state < 5 && avg_30 >= 5) {
actions.NotificationAction.sendBroadcastNotification(
"The washing machine is finished!");
var lights = items.getItem("Lights_Kitchen");
lights.sendCommand("ON");
setTimeout(() => { lights.sendCommand("OFF"); }, 1000);
}

Migrate from ECMA-262 Edition 5.1 to Edition 11

To migrate an existing script, first of all, the language of the script has to be adjusted. This can be either done by creating a new action within the rule with language ECMAScript 262 Edition 11, then copy and paste the code from the old script in the new one, and finally deleting the old script. Or, open the Code view within the rule and change type: application/javascript to type: application/javascript;version=ECMAScript-2021 Furthermore, you need to replace all openHAB commands with the new ones, as shown in the table above.

Blockly Scripts

Rule actions can also be developed with Blockly. This is a nice drag-and-drop language that now has much more blocks available for many openHAB related commands.

Creating openHAB Scripts with Blockly

Nearly all necessary commands are there in Blockly, for working with item states, persistence, logging, notifications, and much more. Blockly also supports copy and paste to duplicate a whole block. And by pressing the blue script button on the bottom right, the full JavaScript code of the script is shown. But, unfortunately, this still uses the old commands, not the new ECMA-262 Edition 11.

Rule Templates

Another nice new new feature in openHAB 3.2 is the marketplace where you can install rule templates. You can find it under “Settings” -> “Addons” -> “Automation”.

Marketplace for openHAB Rule Templates

After adding a rule template, create a new rule and choose the template. The only thing you need to do is providing a configuration. E.g., for the “Alert when Washing Machine Finished” template, you have to provide the item that holds the washing machine’s power, the theshold in Watts, an item (e.g. a light bulp), and the state for the new item.

Creating an openHAB 3 Rule by Using a Template

After the rule is created, it is converted into a regular When-Then rule with a script action as the Then part. Now, it is possible, to further edit the script for extending or customizing it.

Alexa

The way of how to add Alexa metadata is basically the same as before, but there are some new configuration options now:

Adding Item Metadata for Amazon Alexa in openHAB 3.2

Summary

The new way of writing JavaScript-based rules in openHAB 3.2 is much more conveniant than before. The commands are shorter, more user-friendly and there is no need anymore to import Java libraries first.

For existing scripts, there is no need to completely rewrite them, as openHAB 3.2 also supports the old scripting engine. But, new and old commands cannot be mixed within the same scripts. Thus, it makes sense to migrate existing scripts when you plan to extend them. And for creating new rules, it absolutely makes sense to only use the new engine for this.

Another nice feature is Blockly. There, you do not need any programming skills, and you do not need to know all the commands. Blockly is not a new feature in openHAB 3.2, but it was very limited. Now, nearly everything that you need is available as a block.

And when you have an existing Alexa connection, take a look in the items’ metadata. Maybe you find some new helpful configuration options there.

--

--