Introduction
This post provides an overview of two features that have been added to openHAB recently to make it easier to write rules that work with groups of items. These features only apply to rules defined in .rules files (also know as DSL Rules), and not any other types of rules/scripts such as those for the Experimental Rule Engine or JSR223 Scripting.
The following sections will provide examples of the usage of each feature. These examples will be based on the items shown here.
Group AllLights
Group SwitchLights (AllLights)
Group DimmerLights (AllLights)
Switch SwitchLight01 (SwitchLights)
Switch SwitchLight02 (SwitchLights)
Dimmer DimmerLight01 (DimmerLights)
Dimmer DimmerLight02 (DimmerLights)
Feature: triggeringItem Implicit Variable
âtriggeringItemâ is an implicit variable that is available within rules that are triggered by item based events. Item based events use one or more of the following trigger formats.
Item <item> received command [<command>]
Item <item> received update [<state>]
Item <item> changed [from <state>] [to <state>]
The âtriggeringItemâ implicit variable by itself does not directly add group support, but it is a first step that allows a rule to easily determine which item caused the rule to execute.
This feature replaces the need to use a persistence based workaround to identify the item. (I believe this workaround was a creative solution to the problem that has served the community for a long time. Thank you, @rlkoshak)
Availability
âtriggeringItemâ is available in the openHAB 2.2.0 Release Build.
Examples
rule "OrCommandExample"
when
Item SwitchLight01 received command or
Item SwitchLight02 received command
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " received command " + receivedCommand)
end
rule "OrChangedExample"
when
Item SwitchLight01 changed or
Item SwitchLight02 changed or
Item DimmerLight01 changed or
Item DimmerLight02 changed
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " changed state from " + previousState + " to " + triggeringItem.state)
end
In these examples the âtriggeringItemâ implicit variable will be the item that actually triggered the rule (SwitchLight01, SwitchLight02, DimmerLight01, or DimmerLight02).
Limitations
As mentioned above, âtriggeringItemâ does not add group support on its own. In the rule below the âtriggeringItemâ implicit variable will always be the group SwitchLights.
rule "TriggeringItemLimitation"
when
Item SwitchLights changed
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " changed state from " + previousState + " to " + triggeringItem.state)
end
Feature: âMember ofâ Rule Triggers
New rule trigger options have been added that allow rules to operate on items that are members of groups. Group member based events use one or more of the following trigger formats.
Member of <group> received command [<command>]
Member of <group> received update [<state>]
Member of <group> changed [from <state>] [to <state>]
When you combine the âtriggeringItemâ implicit variable with âMember ofâ triggers you have true group support for rules.
Availability
âMember ofâ is an openHAB 2.3 feature. It is not available in any current release build. It is available in snapshot builds starting with openHAB 2.3.0 Build #1212.
Snapshot builds should not be considered as reliable/stable as release builds. Please do not switch to a snapshot just to get this feature unless you understand the risks and are willing to deal with them.
Examples
rule "MemberOfCommandExample"
when
Member of SwitchLights received command
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " received command " + receivedCommand)
end
rule "MemberOfChangedExample"
when
Member of SwitchLights changed or
Member of DimmerLights changed
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " changed state from " + previousState + " to " + triggeringItem.state)
end
In these examples the âtriggeringItemâ implicit variable will be the item that actually triggered the rule (SwitchLight01, SwitchLight02, DimmerLight01, or DimmerLight02).
Advantages
If you compare the âMember ofâ examples with the âtriggeringItemâ examples you will notice that only the âwhenâ sections have changed. The two sets of rule examples are functionally equivalent. The advantages provided by âMember ofâ are:
- For large groups it is easier to write
Member of <group> [condition]
thanItem <item1> [condition] or Item <item2> [condition] or Item <item3> [condition] or ...
- You can add items to and/or remove items from the group without modifying the rule
Limitations
âMember ofâ only works on items that are direct members of a group. It does not traverse nested groups. In the rule below the âtriggeringItemâ implicit variable will be one of the groups that are nested within AllLights (SwitchLights or DimmerLights) and not the base items (SwitchLight01, SwitchLight02, DimmerLight01, or DimmerLight02).
rule "MemberOfLimitation"
when
Member of AllLights changed
then
logInfo("RuleExamples", "The item " + triggeringItem.name + " changed state from " + previousState + " to " + triggeringItem.state)
end
Side Note
There is a topic that has come up several times in discussions around âtriggeringItemâ that I thought would be worth mentioning here. It is not an issue with âtriggeringItemâ, but the use of âtriggeringItemâ appears to have made it more common for people to run into the situation.
If you have a rule that is triggered based on an item receiving a command (Item <item> received command [<command>]
or Member of <group> received command [<command>]
), you should not use the state of that item within the rule. It does not matter how you access the state (triggeringItem.state
, ActualItemName.state
, or SomeGroup.members.<filter>.state
), it should be considered non-deterministic at this point. There is a GitHub issue that goes into some detail about why this is.
You can use the implicit variable âreceivedCommandâ within the rule to determine what command was issued to the item.