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
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)