changed
Execute the rule when an item
, group
, member of group
, or thing
changed state.
Syntax:
changed entity [from:] [to:] [for:]
Options | Description | Examples |
---|---|---|
entity | One or more item, group, member of group, or thing to monitor for changes | changed SwitchItem1 changed Switches.members |
from: | Optional: Only execute rule if previous state matches from state(s) | from: OFF or from: 4..9 |
to: | Optional: Only execute rule if new state matches to state(s) | to: ON or to: ->t { t.even? } |
for: | Optional: Only execute rule if value stays changed for duration | for: 10.seconds |
The from
and to
options are enhanced compared to the rules DSL:
from
andto
accept arrays to match multiple states.- If the changed element being used as a trigger is a thing, the
to
andfrom
values will accept symbols and strings, where the symbol matches the supported status - Support for ranges
- Support for procs/lambdas for complex state matches
Changed Duration
The for
parameter provides a method of only executing the rule if the value is changed for a specific duration. This provides a built-in method of only executing a rule if a condition is true for a period of time without the need to create dummy objects with the expire binding or make or manage your own timers.
For example, the code in this design pattern becomes (with no need to create the dummy object):
rule "Execute rule when item is changed for specified duration" do
changed Alarm_Mode, for: 20.seconds
run { logger.info("Alarm Mode Updated")}
end
Examples
Multiple items can be separated with a comma:
rule 'Execute rule when either sensor changed' do
changed FrontMotion_Sensor, RearMotion_Sensor
run { |event| logger.info("Motion detected by #{event.item.name}") }
end
Or in an array:
SENSORS = [FrontMotion_Sensor, RearMotion_Sensor]
rule 'Execute rule when either sensor changed' do
changed SENSORS
run { |event| logger.info("Motion detected by #{event.item.name}") }
end
Group member trigger:
rule 'Execute rule when member changed' do
changed Sensors.members
run { |event| logger.info("Motion detected by #{event.item.name}") }
end
for
parameter can be an item too:
Alarm_Delay << 20
rule "Execute rule when item is changed for specified duration" do
changed Alarm_Mode, for: Alarm_Delay
run { logger.info("Alarm Mode Updated")}
end
You can optionally provide from and to states to restrict the cases in which the rule executes:
rule 'Execute rule when item is changed to specific number, from specific number, for specified duration' do
changed Alarm_Mode, from: 8, to: [14,12], for: 12.seconds
run { logger.info("Alarm Mode Updated")}
end
Works with ranges:
rule 'Execute rule when item is changed to a range of numbers, from a specific range of numbers, for specified duration' do
changed Alarm_Mode, from: 8..10, to: 12..14, for: 12.seconds
run { logger.info("Alarm Mode Updated")}
end
Works with endless ranges:
rule 'Execute rule when item is changed to any number greater than 12'
changed Alarm_Mode, to: (12..) # Parenthesis required for endless ranges
run { logger.info("Alarm Mode Updated")}
end
Works with procs:
rule 'Execute rule when item state is changed from an odd number, to an even number, for specified duration' do
changed Alarm_Mode, from: proc { |from| from.odd? }, to: proc {|to| to.even? }, for: 12.seconds
run { logger.info("Alarm Mode Updated")}
end
Works with lambda procs:
rule 'Execute rule when item state is changed from an odd number, to an even number, for specified duration' do
changed Alarm_Mode, from: ->from { from.odd? }, to: ->to { to.even? }, for: 12.seconds
run { logger.info("Alarm Mode Updated")}
end
Works with things as well:
rule 'Execute rule when thing is changed' do
changed things['astro:sun:home'], :from => :online, :to => :uninitialized
run { |event| logger.info("Thing #{event.uid} status <trigger> to #{event.status}") }
end
Real world example:
rule 'Log (or notify) when an exterior door is left open for more than 5 minutes' do
changed ExteriorDoors.members, to: OPEN, for: 5.minutes
triggered {|door| logger.info("#{door.id} has been left open!")}
end