How Do I…?
- Items
- Get an Item
- Get the Item’s Name as a String
- Get the Item’s Label
- Get a Related Item
- Send a Command to an Item
- Send a Command to an Item Only When Its State is Different
- Send a Timed Command
- Send an Update to an Item
- Get State of an Item
- Check if an Item’s state is NULL of UNDEF
- Compare Item’s State
- Get the Thing Linked to an Item
- Get All Linked Things
- Groups
- Get the Members or All Members of a Group
- Intersection of Two Groups
- Iterate Over Members of a Group
- Filter Members of a Group
- Get the First Item in a Filtered List of Group Members
- Get first 5 Items from a filtered list of Group members
- Get a sorted list of Group members matching a condition
- Get a List of Values Mapped from the Members of a Group
- Perform Arithmetic on Values from Members of a Group
- Rules
- Create a Rule
- Create a Rule with One Line of Code
- Create a Rule in the Main UI
- Get the Triggering Item
- Get the Triggering Item’s Name
- Get the Triggering Item’s Label
- Get the Triggering Item’s State
- Get the Triggering Item’s Previous State
- Compare Triggering Item’s State Against Previous State
- Get the Received Command
- Create a Member-of-Group Trigger
- Run a Rule on Start Up
- Use Multiple Triggers
- Use Multiple Conditions
- Create a Simple Cron Rule
- Create a Complex Cron Rule
- Use Rule Guards
- Restrict Rule Executions to Certain Time of Day
- Stop a Rule if the Triggering Item’s State is NULL or UNDEF
- Suppress Item State Flapping
- Add a Pause / Sleep / Delay
- Things
- Timers
- Use Metadata
- Use Persistence
- Use Semantic Model
- Use Logging
- Use Actions
- Date/Time
- Ruby
- Miscellaneous
Items
Get an Item
Items and Groups are referred to by their name:
My_Item
gWindowBlinds
Items can be retrieved dynamically:
the_item = items['My_Item'] # This returns an item object, not just its state
# For all intents and purposes, the_item variable is the same as My_Item in the previous example
Get the Item’s Name as a String
My_Item.name
Get the Item’s Label
My_Item.label
Get a Related Item
my_light_item = items[My_Switch.name.sub('_Switch', '_Light')]
Send a Command to an Item
These three variants do the same thing:
My_Item.on
My_Item.command ON
My_Item << ON
Note: all possible commands are supported on the corresponding item types, e.g. on
, off
, up
, down
, play
, pause
, stop
, etc. For more details, see the individual item type sub-sections under Items
Send a Command to an Item Only When Its State is Different
My_Item.ensure.on
My_Item.ensure.command ON
My_Item.ensure << ON
Send a Timed Command
A Timed command is similar to the OpenHAB Item’s expire parameter but it offers more flexibility. It removes the need to manually create a timer.
My_Switch.on for: 5.minutes
Send an Update to an Item
My_Switch.update ON
Get State of an Item
Item’s state is inferred in the item object. Most operations can be done directly using the item itself. Explicitly, My_Item.state
can also be used to refer to the item’s state.
if My_Item == ON
# do something
end
# This syntax is equivalent and preferred:
if My_Item.on?
# do something
end
# Items can be compared directly against its state or against another item's state
if Indoor_Temperature > '20 °C' || Indoor_Temperature > Outdoor_Temperature
# do something
end
# This is possible but unnecessary
Indoor_Temperature.state > '20 °C' || Indoor_Temperature.state > Outdoor_Temperature.state
Note: all boolean helper methods are available depending on the item / state type. For example up?
, down?
, closed?
, open?
, etc.
Check if an Item’s state is NULL of UNDEF
if My_Item.state?
logger.info 'My_Item is not NULL nor UNDEF'
end
Compare Item’s State
String_Item == 'test string'
Number_Item > 5.3
items['Number_Item'] == 10
Temperature_Item > '24 °C'
Temperature_Item > 24| '°C'
Indoor_Temperature > Outdoor_Temperature
Indoor_Temperature > Outdoor_Temperature + '5 °C'
Indoor_Temperature - Outdoor_Temperature > '5 °C'
Get the Thing Linked to an Item
linked_thing = My_Item.thing
thing_uid = My_Item.thing.uid
Get All Linked Things
An item can be linked to multiple things.
My_Item.things.each do |thing|
logger.info("Thing: #{thing.uid}")
end
Groups
Get the Members or All Members of a Group
gTest.members
gTest.all_members
Intersection of Two Groups
Group members work like a Ruby array so you can use &
for intersection, |
for union, and -
for difference.
curtains_in_family_room = gFamilyRoom.members & gCurtains.members
Iterate Over Members of a Group
gTest.each do |item|
# process item
end
# The same:
gTest.members.each do |item|
# process item
end
# Iterate over all members, including members of members
gTest.all_members.each do |item|
# process item
end
Filter Members of a Group
members_that_are_on = gTest.grep(ON)
# Alternatively
members_that_are_on = gTest.select(&:on?)
# exclude state
members_that_are_not_on = gTest.grep_v(ON)
# the same as:
members_that_are_not_on = gTest.reject(&:on?)
# Filter with code:
high_temperatures = gTemperatures.select(&:state?).select { |item| item > '30 °C' }
Get the First Item in a Filtered List of Group Members
Because group acts like an array, simply use Ruby’s Array#first
my_item = gTest.grep(ON).first
Get first 5 Items from a filtered list of Group members
my_item = gTest.grep(ON)[0, 5]
my_item = gTest.grep(ON)[0..4]
my_item = gTest.grep(ON)[0...5]
my_item = gTest.grep(ON).slice(0, 5)
See Accessing elements in a Ruby array.
Get a sorted list of Group members matching a condition
sorted_items_by_battery_level = gBattery.select(&:state?) # only include non NULL / UNDEF members
.select { |item| item < 20 } # select only those with low battery
.sort # sort is done by comparing items, which does it by their states
Get a List of Values Mapped from the Members of a Group
battery_levels = gBattery.select(&:state?) # only include non NULL / UNDEF members
.sort
.map { |item| "#{item.label}: #{item}" } # Use item state default formatting
Perform Arithmetic on Values from Members of a Group
weekly_rainfall = gRainWeeklyForecast.sum
Rules
Create a Rule
rule 'my first rule' do
received_command My_Switch, to: ON
run do
My_Light.on
end
end
This applies to file-based rules. See Rules
Create a Rule with One Line of Code
received_command(My_Switch, to: ON) { My_Light.on }
This applies to file-based rules. See Terse Rules
Create a Rule in the Main UI
Get the Triggering Item
event.item
Get the Triggering Item’s Name
event.item.name
Get the Triggering Item’s Label
event.item.label
Get the Triggering Item’s State
event.state
or
event.item.state
The item’s state can also be obtained by accessing the triggering item itself.
# Item can be compared against their state
if event.item == ON
# do something
end
# or
if event.item.on?
# do something
end
Get the Triggering Item’s Previous State
event.was
Example:
if event.was.on?
# do something
end
Compare Triggering Item’s State Against Previous State
event.state > event.was
Get the Received Command
event.command
Example:
if event.command.on?
# do something
end
Create a Member-of-Group Trigger
rule 'Trigger by Member of' do
changed gGroupName.members
run do |event|
logger.info "Triggered item: #{event.item.name}"
end
end
Run a Rule on Start Up
rule 'initialize things' do
on_start # This also triggers whenever the script (re)loads
run { logger.info 'Here we go!' }
end
Use Multiple Triggers
rule 'multiple triggers' do
changed Switch1, to: ON
changed Switch2, to: ON
run { |event| logger.info "Switch: #{event.item.name} changed to: #{event.item}" }
end
When the trigger conditions are the same, the triggers can be combined
rule 'multiple triggers' do
changed Switch1, Switch2, to: ON
run { |event| logger.info "Switch: #{event.item.name} changed to: #{event.item}" }
end
Use Multiple Conditions
rule 'multiple conditions' do
changed Button_Action, to: ['single', 'double']
run { |event| logger.info "Action: #{event.item}" }
end
Create a Simple Cron Rule
rule 'run every day' do
every :day, at: '2:35pm'
run { Amazon_Echo_TTS << "It's time to pick up the kids!" }
end
rule 'run every 5 mins' do
every 5.minutes
run { logger.info 'openHAB is awesome' }
end
rule 'Anniversary Reminder' do
every '10-15' # Trigger on 15th of October at midnight
run do
things['mail:smtp:mymailthing'].sendMail('me@example.com', 'Anniversary Reminder!', 'Today is your anniversary!')
end
end
See Every
Create a Complex Cron Rule
rule 'cron rule' do
cron '0 0,15 15-19 L * ?'
run { logger.info 'Cron run' }
end
or an easier syntax:
rule 'cron rule' do
cron second: 0, minute: '0,15', hour: '15-19', dom: 'L'
run { logger.info 'Cron run' }
end
See Cron
Use Rule Guards
rule 'motion sensor' do
updated Motion_Sensor, to: ON
only_if Sensor_Enable # Run rule only if Sensor_Enable item is ON
not_if { Sun_Elevation.positive? } # and not while the sun is up
run { LightItem.on }
end
See Guards
Restrict Rule Executions to Certain Time of Day
rule 'doorbell' do
updated DoorBell_Button, to: 'single'
between '6am'..'8:30pm'
run { play_sound 'doorbell_chime.mp3' }
end
Stop a Rule if the Triggering Item’s State is NULL or UNDEF
Use next
within a file-based rule, because it’s in a block:
next unless event.item.state?
Use return
within a UI rule:
return unless event.item.state?
Suppress Item State Flapping
Only execute a rule when an item state changed and stayed the same for a period of time. This method can only be done using a file-based rule.
rule 'Announce pool temperature' do
changed Pool_Temperature, for: 10.minutes # Only when temp is stable for at least 10 minutes
only_if Pool_Heater # And only when the pool heater is running
run { say "The pool temperature is now #{Pool_Temperature}" }
end
Add a Pause / Sleep / Delay
sleep 1.5 # sleep for 1.5 seconds
See Ruby docs on sleep
sleep
should be avoided if possible. A delay can be inserted in between two execution blocks to achieve the same result. This delay is implemented with a timer. This is available only on file-based rules.
rule 'delay something' do
on_start
run { logger.info 'This will run immediately' }
delay 10.seconds
run { logger.info 'This will run 10 seconds after' }
end
Alternatively a timer can be used in either a file-based rule or in a UI based rule:
rule 'delay something' do
on_start
run do
logger.info 'This will run immediately'
after(10.seconds) do
logger.info 'This will run 10 seconds after'
end
end
end
Things
Get Thing Status
things['lgwebos:WebOSTV:main-tv'].status
Check if Thing is Online
things['lgwebos:WebOSTV:main-tv'].online?
or
things['lgwebos:WebOSTV:main-tv'].status == ThingStatus::ONLINE
Enable/Disable a Thing
thing_manager = OpenHAB::Core::OSGI.service('org.openhab.core.thing.ThingManager')
thing = things['lgwebos:WebOSTV:main-tv']
thing_manager.set_enabled(thing.uid, false)
logger.info "TV enabled: #{thing.enabled?}"
thing_manager.set_enabled(thing.uid, true)
logger.info "TV enabled: #{thing.enabled?}"
Timers
Create a Timer
after 3.minutes do
My_Light.on
end
See Timers
Reschedule a Timer
A timer can be rescheduled inside the timer body
after 3.minutes do |timer|
My_Light.on
timer.reschedule # This will reschedule it for the same initial duration, i.e. 3 minutes in this case
end
Or it can be rescheduled from outside the timer
my_timer = after 3.minutes do
My_Light.on
end
my_timer.reschedule # Use the same initial duration
It can be rescheduled to a different duration
after 3.minutes do |timer|
My_Light.on
timer.reschedule 1.minute
end
Manage Multiple Timers
Multiple timers can be managed in the traditional way by storing the timer objects in a hash
@timers = {}
rule 'a timer for each group member' do
received_command gOutdoorLights.members do
run do |event|
if @timers[event.item]
@timers[event.item].reschedule
else
@timers[event.item] = after 3.minutes do # Use the triggering item as the timer ID
event.item.off
@timers.delete(event.item)
end
end
end
end
However, a built in mechanism is available to help manage multiple timers. This is done using timer IDs. The following rule automatically finds and reschedules the timer matching the same ID, which corresponds to each group member.
rule 'a timer for each group member' do
received_command gOutdoorLights.members do
run do |event|
after 3.minutes, id: event.item do # Use the triggering item as the timer ID
event.item.off
end
end
end
Furthermore, you can manipulate the managed timers using the built-in timers[]
hash.
# timers[] is a special hash to access the timers created with an id
# Note here we use Ruby's safe navigation operator in case the timer
# no longer exists, in which case timers[id] returns nil
rule 'cancel all timers' do
received_command Cancel_All_Timers, to: ON # Send a command to this item to cancel all timers
run do
gOutdoorLights.each do |item_as_timer_id|
timers[item_as_timer_id]&.cancel
end
end
end
rule 'reschedule all timers' do
received_command Reschedule_All_Timers, to: ON # Send a command to this item to restart all timers
run do
gOutdoorLights.each do |item_as_timer_id|
timers[item_as_timer_id]&.reschedule
end
end
end
Use Metadata
metadata = My_Item.meta['namespace'].value
See Metadata
Use Persistence
daily_max = My_Item.maximum_since(24.hours)
See Persistence
Use Semantic Model
# get the lightbulbs (equipment) in the room (location)
room_lights = LivingRoom_Motion.location.equipments(Semantics::Lightbulb)
# get the switches (points)
light_switches = room_lights.members.points(Semantics::Switch)
# turn them all on if they're not already on
light_switches.ensure.on
See Semantics
Use Logging
logger.info("My Item's state is: #{My_Item}")
See Logging
Use Actions
See Actions
Publish an MQTT Message
things['mqtt:broker:mybroker'].publishMQTT('topic/name', 'payload')
Send an Email
things['mail:smtp:mymailthing'].sendMail('me@example.com', 'Subject', 'message body')
Play Sound Through the Default Audio Sink
play_sound 'sound_file.mp3'
Execute a Command
Exec.executeCommandLine('/path/to/program')
Date/Time
Use ZonedDateTime
ZonedDateTime.now.plus_minutes(30)
Convert ZonedDateTime to Ruby Time
Time.at(ZonedDateTime.now.to_epoch_second)
Convert Ruby Time to ZonedDateTime
ruby_time = Time.now
ruby_time.to_java(ZonedDateTime)
Work with Time of Day
if TimeOfDay.now > '7am'
logger.info 'Wake up!'
end
# The range can cross midnight
if TimeOfDay.now.between?('10pm'..'5am')
logger.info 'Sleep time'
end
See TimeOfDay
Work with MonthDay
if MonthDay.now == '02-14'
logger.info "Happy Valentine's Day!"
end
See MonthDay
Ruby
Install Additional Gems
gemfile do
source 'https://rubygems.org'
gem 'httparty'
end
See Inline Bundler
Use Shared Library
See Shared Code
Miscellaneous
Get the UID of a Rule
This applies to file-based rules:
rule_obj = rule 'my rule name' do
received_command My_Item
run do
# rule code here
end
end
rule_uid = rule_obj.uid
Get the UID of a Rule by Name
rule_uid = OpenHAB::Core.rule_registry.all.select { |rule| rule.name == 'This is the name of my rule' }.first.uid
Enable or Disable a Rule by UID
rule_manager = OpenHAB::Core::OSGI.service('org.openhab.core.automation.RuleManager')
rule_manager.set_enabled(rule_uid, true) # enable rule
rule_manager.set_enabled(rule_uid, false) # disable rule
Run a rule by UID
rule_manager = OpenHAB::Core::OSGI.service('org.openhab.core.automation.RuleManager')
rule_manager.run_now(rule_uid)
Use a Java Class
java_import java.time.format.DateTimeFormatter
formatter = DateTimeFormatter.of_pattern('yyyy MM dd')
formatter = Java::JavaTimeFormat::DateTimeFormatter.of_pattern('yyyy MM dd')