Design Pattern: Rule Disable

Edit: Updated for OH 4

Please see Design Pattern: What is a Design Pattern and How Do I Use Them for an explanation of what a DP is and how to use them.

Problem Statement

Often one has a set of Rules that need to run under a given set of conditions and not run when those conditions are not present. For example, one may have certain Rules that only run when everyone is away, only during a holiday season, or when the family is on vacation.

This DP covers various techniques that one can use to enable and disable Rules based on Item states.

Conditions

Rule conditions are a core part of all managed rules and supported by some text based rules (e.g. see JavaScript Scripting - Automation | openHAB) which will only run the rule action if all of the conditions are true. See Rules | openHAB for details.

A condition can be time based, Item state based, based on Ephemeris or based on a script which can be written in any of the supported rules languages.

When using a script, the last line executed must evaluate to a boolean.

In MainUI the conditions can be found near the bottom of the rule’s page.

See the reference for your preferred rules language to see if conditions are supported and how to define them. If not supported, an if statement at the top of the rule to exit when the condition is not set can be used.

Blockly

image

Notice that the block stands on it’s own and doesn’t plug into a standard block.

JS Scripting

item.MyItem.quantityState.greaterThan(Quantity("50 %")) && time.toZDT().isAfter(time.toZDT(items.Dusk))

Jython

(items["MyItem1"] == ON and items["MyItem2"] == OFF)

Disable/Enable Rules

OH 2.x with the Next Generation Rules Engine and all versions of OH 3 and later support the ability to enable and disable Rules. Many of the rules languages have support in their helper libraries to do this from a rule’s action and there is a set of rule actions available through the UI.

With rule conditions the rule is still triggered and the condition still executes. A disabled rule is rendered inert and nothing happens when the triggering events occur.

Note that both managed and file based rules can be enabled and disabled in this way.

Manually

On the rules page and from the developer sidebar there is a pause button (circle with an 11 in the middle next to the triangular play button). Clicking this causes the rule to be disabled.


and from the developer sidebar

UI Rule Action

When adding an action to a rule the “Scenes, Scripts & Rules” option has as a choice enabling or disabling a rule.

Any number of rules can be disabled in one action.

Blockly

Not directly supported. But the JS Scripting example below can be used in an inline script block. Or you can use one of the UI actions above.

JS Scripting

rules.setEnabled('ruleuid', false); // disable 
rules.setEnabled('ruleuid', true); // enable

Jython

Jython doesn’t have direct support for this in the helper library. It requires a two step process. The UID for the Rule is defined when the Rules is loaded and it is not guaranteed to be the same every time OH restarts. So you must first search for the UID based on the Rule’s name. Then you can enable/disable the Rule using the discovered UID.

Here is an example that enables a couple of Rules based on the state of a Switch Item.

from core.rules import rule
from core.triggers import when
from core import osgi

@rule("Christmas Mode",
      description="Enable/disable rules based on the state of vChristmas",
      tags=["christmas"])
@when("Item vChristmas changed")
@when("System started")
def xmas_enable(event):
    """
    Because smart plugs are reused for Christmas lights, disable the rules that
    normally use those plugs when Christmas mode is enabled and enable the
    Christmas lights Rule.
    """
    import time
    time.sleep(40) # Wait until all Rules are loaded

    xmas_enable.log.info("Turning {} Christmas mode"
                         .format(items["vChristmas"]))

    lightRuleId = [rule for rule in rules.getAll()
                   if rule.name == "Christmas lights"][0].UID
    humidifierRuleId = [rule for rule in rules.getAll()
                        if rule.name == "MBR Humidifier"][0].UID

    ruleEngine = (osgi.get_service("org.openhab.core.automation.RuleManager") or
               osgi.get_service("org.eclipse.smarthome.automation.RuleManager"))
    ruleEngine.setEnabled(lightRuleId, items["vChristmas"] == ON)
    ruleEngine.setEnabled(humidifierRuleId, items["vChristmas"] != ON)

3 Likes

Nope… items is in the default script scope.

1 Like

I wasn’t sure if the default script scope applied to the “but only if…” clauses. Good to know. :slight_smile:

When you use Scripted Conditions and Actions, you are actually using scripted automation. With the Jython bundle (not required, but nice), we can put out rule templates with Scripted Conditions and Actions that utilized community libraries!

@rlkoshak is there a way to do the same in java scripting automation addon (openhab-js)?

Yes. See rules - Documentation where you’ll find a isEnabled and setEnabled pair of functions.