openHAB: faster loading of rules files

Posted by ads' corner on Saturday, 2020-10-24
Posted in [Ansible][Linux][Openhab]

openHAB rules files are lazy loaded. When a rule is used the first time, the entire rule file is loaded and compiled, which apparently is single-threaded and takes a couple seconds. Even on a reasonable powerful Rasperry Pi 4. This happens both after restarting openHAB and after changing the rules file. It also means that whatever the rule in question is supposed to do has to wait a couple seconds when requested for the first time. Imagine you have a light switch, enter a room, press the switch, and it takes 5-10 seconds until the light comes on.

To work around this problem, I add a piece of code in all rules files which triggers an immediate action right after loading the file. This way the rules file is already pre-loaded (which again takes a couple seconds, but likely at a time when the rule is not needed right now).

The code which I insert into every rules file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var rules_last_updated_<name> = null

rule "Init <name> Rules"
when
    System started
then
    rules_last_updated_<name> = now
end

rule "Update <name> Rules"
when
    Time cron "15 */30 * ? * *"
then
    rules_last_updated_<name> = now
end

The “System started” trigger in openHAB is misleading: it’s not only fired when the entire system starts, it is also fired when the rules file is loaded. That’s useful in my case, because it allows me to set a variable. And that’s enough to trigger the entire compilation of the file.

There is a second trigger which fires every 30 minutes, and which refreshes the rules file compilation.

<name> is a unique name I use for every rules file. Since the variable rules_last_updated_<name> is local to evey rules file this should not matter. However it allows me to expand this rule and log into the openHAB log when the rules file is compiled.

Now I don’t really add the entire code to every rules file, because I’m even more lazy. My installation is deployed using Ansible and templates, and in every rules file I just include another template with above code. Here is the template, in my case the name is performance.j2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{# this needs to go after the last variable declaration and before the first code #}

// variable which is used in this rule file
// to keep track of the last usage
// this more or less ensures that the rule is compiled and stays in memory
var rules_last_updated_{{ performance_name }} = null

rule "Init {{ performance_name }} Rules"
when
    System started
then
    rules_last_updated_{{ performance_name }} = now
end

rule "Update {{ performance_name }} Rules"
when
    Time cron "15 */30 * ? * *"
then
    rules_last_updated_{{ performance_name }} = now
end

And in every rules file I insert the following small code fragment:

1
2
3
4
5
6
... variables

{% set performance_name = 'chromecast' %}
{% include 'performance.j2' %}

... rules

When this is deployed, Ansible inserts the template from performance.j2 into every rules file, and when openHAB loads the file it instantly triggers the compilation.


Categories: [Ansible] [Linux] [Openhab]