Xtext + Xbase + Quartz + Joda Time = Perfect Rule Engine

Posted by Kai Kreuzer on May 29, 2012
Half a year ago I sketched my ideas for a new rule engine for the open Home Automation Bus (openHAB). I had presented an initial version at EclipseCon Europe 2011 and it is by now used by most openHAB users - I think Xtext/Xbase has been a great choice for this implementation and I would like to share some information of how this solution looks like.

1. Xtext for the Rule Skeleton

Xtext allows us to freely define the syntax for our rule definitions. An openHAB rule consists out of two sections, the trigger definition and the script to execute. openHAB specific concepts such as items and events can be nicely integrated into the grammar. An example rule would look like this:
rule "Turn light on"
when
Item
Door changed to OPEN
then
Light.postUpdate(ON)
end

2. Xbase for the Execution Code Block

The "then" part of a rule could simply be designed to be a sequence of pre-defined commands to execute. Reality shows that most users quickly require much more than this - they ask for complex calculation possibilities and execution flow constructs. Xbase comes in very handy as a powerful and customizable scripting language that is an integral part of Xtext. The functional programming oriented constructs make it easy to express logic in a few lines, where "classical" object-oriented languages would require much more procedural code:
rule "Initialize light states with random values"
when
System started
then
Lights?.members.forEach(light|
light.postUpdate(if(Math::random > 0.7) ON else OFF)
)
end

3. Quartz as a Scheduler

Many home automation use cases require to execute actions regularly at certain times. openHAB makes use of the Quartz library, which is helpful for scheduling jobs for execution in Java. As the cron syntax is very expressive, openHAB allows to directly use cron strings for time trigger definitions. Alternatively - for very common values - some pre-defined strings such as "noon" and "midnight" can be used:
rule "Time trigger"
when
Time is midnight or
Time cron "0 15 * * * ?"
then
callScript("doSomething")
end

4. Joda Time for Date and Time Calculations

In many cases you might want to refer to a relative point in time, e.g. "one hour ago", or "on the 1st of this month". Joda Time has a wonderful simple and yet very powerful fluent API to do exactly such kind of things. In openHAB, you can use this to access historic information as well as for scheduling code for future execution - in the latter case, the code will be run as a scheduled Quartz job.

rule "Automatically turn off Staircase Lights"
when
Item Light_Staircase received command ON
then
createTimer(now.plusMinutes(10)) [|
Light_Staircase.sendCommand(OFF)
]
end
rule "Turn on irrigation system after two days without rain"
when
Time is midnight
then
if(Rain==OFF && !Rain.changedSince(now.minusDays(2))) {
Irrigation.sendCommand(ON)
}
end

Summary

For most openHAB users this new rule engine is a better choice than the previous Drools-based engine. Although it does not offer as many rule features as Drools does (e.g. conditional triggers, rule grouping, dynamic deactivation, execution order inference etc.), it proves to be strong on other important points:
  • It has a syntax that is easy to read and write and which integrates well with openHAB concepts such as items and events.
  • It has full IDE support in the openHAB Designer such as syntax validation and highlighting, content assist etc.
  • It is much leaner at runtime as the code is interpreted and does not need to be compiled to Java byte code (which in turn requires a Java compiler to be part of the runtime)
  • It has very limited memory requirements at runtime as the code is very compact and it does not require any dedicated rule engine context where item state information would be duplicated.
For these reasons, the new rule engine has been made the default, which is shipped with the core openHAB runtime distribution. For users who require the full power of Drools, a separate Drools-package is still available as an optional download.