Skip to content

Commit

Permalink
Support TimedCommand on GroupItem and Enumerable (#377)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimtng authored Jan 3, 2025
1 parent 3842e0e commit 5fc181e
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 16 deletions.
18 changes: 11 additions & 7 deletions lib/openhab/core/items.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,17 @@ def def_command_methods(klass)
RUBY

Enumerable.class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{command} # def on
each(&:#{command}) # each(&:on)
end # end
#
def #{command}! # def on!
each(&:#{command}!) # each(&:on!)
end # end
ruby2_keywords def #{command}(*args, &block) # ruby2_keywords def on(*args, &block)
each do |member| # each do |member|
member.#{command}(*args, &block) # member.on(*args, &block)
end # end
end # end
#
ruby2_keywords def #{command}!(*args, &block) # ruby2_keywords def on!(*args, &block)
each do |member| # each do |member|
member.#{command}!(*args, &block) # member.on!(*args, &block)
end # end
end # end
RUBY
else
logger.trace { "Defining #{klass}/Enumerable##{command} for #{value}" }
Expand Down
5 changes: 4 additions & 1 deletion lib/openhab/core/items/group_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ def type_details
end

# Delegate missing methods to {base_item} if possible
def method_missing(method, *args, &block)
# Command methods and predicate methods for GroupItem are performed here
# instead of being statically defined in items.rb
# because base_item is needed to determine the command/data types but is not available in the static context
ruby2_keywords def method_missing(method, *args, &block)
return base_item.__send__(method, *args, &block) if base_item&.respond_to?(method) # rubocop:disable Lint/RedundantSafeNavigation nil responds to :to_a

super
Expand Down
10 changes: 10 additions & 0 deletions spec/openhab/core/items/group_item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@
end
end

it "supports command methods" do
items.build do
group_item "Switches", type: :switch do
switch_item "SwitchOne"
end
end

Switches.on
end

describe "#method_missing" do
it "has command methods for the group type" do
items.build do
Expand Down
2 changes: 1 addition & 1 deletion spec/openhab/dsl/items/builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ def build_and_update(org_config, new_config, item_to_keep: :new_item, &block)
end

it "sets initial state on a group item" do
items.build { group_item "GroupItem1", type: "Switch", state: ON }
items.build { group_item "GroupItem1", type: :switch, state: ON }
expect(GroupItem1.state).to be ON
end

Expand Down
59 changes: 52 additions & 7 deletions spec/openhab/dsl/items/timed_command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,49 @@ def self.test_it(initial_state, command)
expect(manualitem.state).to eq OFF
end

it "works with GroupItem" do
items.build { group_item "Group1", type: "Switch", autoupdate: true }
Group1.update(OFF)
Group1.command(ON, for: 1.second)
expect(Group1).to be_on
time_travel_and_execute_timers(2.seconds)
expect(Group1).to be_off
context "with GroupItem" do
it "works" do
items.build do
group_item "Group1", type: :switch do
switch_item "Switch1"
end
end
Group1.command(ON, for: 1.second)
expect(Group1).to be_on
time_travel_and_execute_timers(2.seconds)
expect(Group1).to be_off
end

it "works in command methods" do
items.build do
group_item "Group1", type: :switch do
switch_item "Switch1"
end
end
Group1.on for: 1.second
expect(Group1).to be_on
time_travel_and_execute_timers(2.seconds)
expect(Group1).to be_off
end

it "cancels implicit timer when its group member received a command" do
items.build do
group_item "Group1", type: :number, function: "AVG" do
number_item "Number1", state: 0
end
end
Group1.update(0)
Group1.command(1, for: 1.second)
expect(Group1.state).to eq 1
time_travel_and_execute_timers(2.seconds)
expect(Group1.state).to eq 0

Group1.command(1, for: 1.second)
Number1.command(2)
expect(Group1.state).to eq 2
time_travel_and_execute_timers(2.seconds)
expect(Group1.state).to eq 2
end
end

context "with Enumerable" do
Expand All @@ -317,6 +353,15 @@ def self.test_it(initial_state, command)
expect(Switch2).to be_off
end

it "works with command methods" do
[Switch1, Switch2].on for: 1.second
expect(Switch1).to be_on
expect(Switch2).to be_on
time_travel_and_execute_timers(2.seconds)
expect(Switch1).to be_off
expect(Switch2).to be_off
end

it "each member has its own timer" do
[Switch1, Switch2].command(ON, for: 1.second)
Switch1.on
Expand Down

0 comments on commit 5fc181e

Please sign in to comment.