# Advanced Rules
Blockly is super powerful and relatively easy to use but at some point there will be some nuance or use case that cannot be achieved through Blockly. Or perhaps the graphical representation is too limiting. For what ever reason, openHAB has you covered with text based Script Actions and Script Conditions.
# Languages
openHAB supports a growing list of programming languages in which rules can be written. openHAB comes with the following languages to choose from:
Language | Details | Intended Audience |
---|---|---|
Blockly | See the previous page | Non-developers |
Rules DSL | A programming language developed specifically for openHAB based on Xtend (opens new window). | Long time openHAB users |
In addition to these default choices, one can install a number of different languages as an Automation add-on. Such diverse languages as JavaScript, Ruby, Python, Groovy, Java, and more are available with more to come. See the add-on docs for the reference guide and specific information for how to use each individual add-on. Take note, not all automation add-ons support writing rules in the UI.
For the rest of this tutorial we will show how to use the JavaScript Scripting add-on which implements ECMAScript 2021, and JRuby Scripting add-on for Script Actions and Script Conditions in UI rules. See the add-on's reference for how to write rules in text files which is outside the scope of this tutorial.
# Installation
To install a new rules language navigate to Settings -> Automation and install the add-on desired. The next time you create a Script Action or Script Condition, if it's supported, the new language will be selectable.
# Helper Libraries
All of the rules languages will run inside the Java Virtual Machine.
This gives all these languages access to all of the Java standard library of classes.
Furthermore, all direct interactions with openHAB itself is done through Java Objects and Classes.
What does this mean?
It means that sometimes an int
isn't just an int
.
If you are going to write rules to directly interact with openHAB, you will have to be very conscious of where the data comes from and what its type is.
In order to make that process easier, most of the automation add-ons offer a Helper Library. These libraries come in various forms and are installed in different ways but they all endeavor to do the following:
- make writing rules in text files easier, less verbose, and more natural to the native language
- provide utility functions and ways to interact with openHAB using language native Classes, Objects and types
- abstract some of the sometimes verbose series of steps requires to do something (e.g. access an Item's metadata) into a single function call.
See the automation add-on's reference for how to access and install the Helper Library for your language of choice.
Again, see the add-on's reference for details.
# Creating a Rule
See the previous pages of this tutorial for details on creating a rule. The steps are the same no matter what language is to be used. Consequently this tutorial won't talk about the rule triggers at all.
One can combine and use multiple languages in the same rule, for example using a simple UI Condition and a Blockly Script Condition along with a Script Action written in Rules DSL and second one written in ECMAScript 2021.
For consistency and the ability to compare approaches, this part of the tutorial will use the same set of requirements as was used in the Blockly tutorial. As a reminder, we want to turn on a light when motion is detected and keep that light on for 30 minutes after the last motion was detected. But it should only do this between sunset and 23:00.
# When: Triggers
See the previous pages. Triggers are set up the same way for all UI rules. We will use the same trigger from the Blockly tutorial.
# Then: Actions
Just like in Blockly, we will create a new Action but instead of choosing Blockly, we will choose ECMAScript
or Ruby
.
This will open a blank text field where you can start typing your code. This text field provides text highlighting and some code completion which helps with coding.
As with the Blockly example, we want to start the rule using a log statement we can see in openhab.log when the rule runs.
Save and test the rule by running it manually and verify you see this statement in the logs.
Next we want to send a command to the light to turn it on.
Save and test and verify you see the log statement and the Item receive an ON command.
Now we want to create a Timer to go off in 30 minutes.
Save and test that you see the log statement and the Item receive the ON
command and 30 minutes later the second log statement and the OFF
command.
(hint, change the time passed to the timer to something smaller to make testing easier then change it back once things are working).
Now all we are lacking is the ability to reschedule that timer if motion is seen again in the 30 minute period.
Save and test that the rule sends the on and off commands as described.
# But only if: Conditions
Now we want the rule to only execute between sunset and 23:00.
Create a new Condition and choose ECMAScript
or Ruby
as the language.
This doesn't have to be the same language as the one chosen for the Script Action above.
Just like with the Script Action, the Helper Library is available by default.
As discussed in the Blockly tutorial, the last line of a condition must evaluate to true
or false
.
When true
the rule will run, otherwise it's skipped.
Sunset is available in an Item called Sunset
and we need to test to see if now
is between then and 23:00
.
# Advanced Topics
# Libraries
Most of the languages support installation and importing of third party libraries. Many of the languages will have special tools to download and install these libraries and there might be extra requirements to use them in openHAB. See the add-on's docs and the forum for details on the automation add-on chosen.
# Debugging
All the same advice from Blockly applies here too. Gradually build up your rule, testing at each step. Use logging liberally. Break up your code into functions you can test independently. Simplify complicated lines by breaking them up. Watch the logs for errors.
# Tips and Tricks
If you find yourself duplicating rules or code, consider ways to extract that into a function or library.
When posting to the forum, post the contents of the "Code" tab instead of screen shots.
Rules can call other rules which can be another way to break out common code.
Use the
cache
to hold things that need to survive the running of a script or be shared with other scripts. Thecache
will be cleared out during a restart.