I have a bunch of inovelli dimmer switches and each switch has multiple scenes depending on how many times you tap up or down. Instead of making individual rules for all of these I wrote one rule in jruby. It turned out to be super handy so I thought I’d share it. It should work with basically any type of openhab item state combo, not just switches. I know something similar could be done with python or javascript, but I thought the ruby approach was just so much cleaner. If you haven’t tried the JRuby Scripting addon I definitely recommend giving it a shot.
require 'openhab'
UPx1 = "2.0"
UPRELEASE = "2.1"
UPHOLD = "2.2"
UPx2 = "2.3"
UPx3 = "2.4"
UPx4 = "2.5"
DOWNx1 = "1.0"
DOWNRELEASE = "1.1"
DOWNHOLD = "1.2"
DOWNx2 = "1.3"
DOWNx3 = "1.4"
DOWNx4 = "1.5"
class Scene
@@scenes = Hash.new{|h, k| h[k] = {}}
def initialize
@switch_statuses = Hash.new{|h, k| h[k] = {}}
@item_commands = {}
end
def switch_status(switch, status)
@switch_statuses[switch.name][status.to_s] ||= {}
self
end
def item_command(item, command)
@item_commands[item.name] = command
self
end
def add
@switch_statuses.each do |switch, statuses|
statuses.each_key{|status| @@scenes[switch][status] = @item_commands }
end
end
def self.switches
@@scenes.keys.map{|k| items[k]}
end
def self.send_commands(switch)
item_command_hash = @@scenes[switch.name][switch.state.to_s] || return
item_command_hash.each_pair do |i, command|
if items.include? i
item = items[i]
logger.info("Send Item: #{i} Command: #{command}")
if item.is_a?(Group)
item.group << command
else
item << command
end
else
logger.info("Item #{i} not found!")
end
end
end
end
# Define your Scenes here. I've given a few examples.
Scene.new.switch_status(FamilyRoom_Dimmer_1_SceneNumber, UPx1)
.switch_status(FamilyRoom_Dimmer_2_SceneNumber, UPx1)
.item_command(FamilyRoom_Lights_Color, "ON").add
Scene.new.switch_status(FamilyRoom_Dimmer_1_SceneNumber, UPx2)
.switch_status(FamilyRoom_Dimmer_2_SceneNumber, UPx2)
.item_command(FamilyRoom_Lights_Color, "100").add
Scene.new.switch_status(FamilyRoom_Dimmer_1_SceneNumber, DOWNx1)
.switch_status(FamilyRoom_Dimmer_2_SceneNumber, DOWNx1)
.item_command(FamilyRoom_Lights_Color, "OFF").add
Scene.new.switch_status(FamilyRoom_Dimmer_1_SceneNumber, DOWNx2)
.switch_status(FamilyRoom_Dimmer_2_SceneNumber, DOWNx2)
.item_command(FamilyRoom_Lights_Color, "30").add
Scene.new.switch_status(FamilyRoom_Dimmer_1_SceneNumber, DOWNx3)
.item_command(FamilyRoom_Projector_Power, "ON")
.item_command(FamilyRoom_Curtain_BlindsControl, "DOWN").add
Scene.new.switch_status(FamilyRoom_Projector_Power, "OFF")
.item_command(FamilyRoom_Curtain_BlindsControl, "UP").add
rule 'Switch Scenes' do
changed Scene.switches
triggered do |switch|
Scene.send_commands(switch)
end
end
I created a Scene class has 3 main methods.
switch_status which takes an item and state. This is the item you want to watch and the state you are trying to use. eg: switch_status(MySwitch_1_SceneNumber, “1.3”). Which would trigger when I tap my switch down twice.
item_command takes the item that you are trying to control and the command you want to give it. eg: item_command(FamilyRoom_Lights,“ON”)
add is placed at the end of the method chain.
Both switch_status and item_command can be chained multiple times to add more switches or items to control for the scene. I also defined a few constants at the top so I didn’t have to remember what state value went to what amount of switch taps.