From c36014660d726937485d45e44eed9f72f5144e86 Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Mon, 13 May 2024 23:44:41 -0400 Subject: [PATCH] Support filtered item|thing_added|removed and channel_linked|unlinked triggers (#266) --- lib/openhab/core/dto/item_channel_link.rb | 5 ++ lib/openhab/dsl/rules/builder.rb | 76 +++++++++++----- spec/openhab/dsl/rules/builder_spec.rb | 103 ++++++++++++++++++++++ 3 files changed, 160 insertions(+), 24 deletions(-) diff --git a/lib/openhab/core/dto/item_channel_link.rb b/lib/openhab/core/dto/item_channel_link.rb index ab17777079..17f39a83a1 100644 --- a/lib/openhab/core/dto/item_channel_link.rb +++ b/lib/openhab/core/dto/item_channel_link.rb @@ -27,6 +27,11 @@ def item def channel_uid Things::ChannelUID.new(channelUID) end + + # @return [String] + def to_s + "#{item_name} -> #{channelUID}" + end end end end diff --git a/lib/openhab/dsl/rules/builder.rb b/lib/openhab/dsl/rules/builder.rb index 8788934a97..a6785fd762 100644 --- a/lib/openhab/dsl/rules/builder.rb +++ b/lib/openhab/dsl/rules/builder.rb @@ -992,9 +992,14 @@ def channel(*channels, thing: nil, triggered: nil, attach: nil) # # Creates a channel linked trigger # + # @param [Item, String, nil] item The item to create a trigger for. If nil, all items are matched. + # @param [Core::Things::Channel, Core::Things::ChannelUID, String, nil] channel + # The channel to create a trigger for. If nil, all channels are matched. # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for filtering with item and channel was added + # # @example # rule "channel linked" do # channel_linked @@ -1002,9 +1007,10 @@ def channel(*channels, thing: nil, triggered: nil, attach: nil) # logger.info("#{event.link.item.name} linked to #{event.link.channel_uid}.") # end # end - def channel_linked(attach: nil) - @ruby_triggers << [:channel_linked] - event("openhab/links/*/added", types: "ItemChannelLinkAddedEvent", attach: attach) + def channel_linked(item: nil, channel: nil, attach: nil) + pattern = (item.nil? && channel.nil?) ? "*" : "#{item || "*"}-#{channel || "*"}" + @ruby_triggers << [:channel_linked, pattern] + event("openhab/links/#{pattern}/added", types: "ItemChannelLinkAddedEvent", attach: attach) end # @@ -1013,9 +1019,14 @@ def channel_linked(attach: nil) # Note that the item or the thing it's linked to may no longer exist, # so if you try to access those objects they'll be nil. # + # @param [Item, String, nil] item The item to create a trigger for. If nil, all items are matched. + # @param [Core::Things::Channel, Core::Things::ChannelUID, String, nil] channel + # The channel to create a trigger for. If nil, all channels are matched. # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for filtering with item and channel was added + # # @example # rule "channel unlinked" do # channel_unlinked @@ -1023,9 +1034,10 @@ def channel_linked(attach: nil) # logger.info("#{event.link.item_name} unlinked from #{event.link.channel_uid}.") # end # end - def channel_unlinked(attach: nil) - @ruby_triggers << [:channel_linked] - event("openhab/links/*/removed", types: "ItemChannelLinkRemovedEvent", attach: attach) + def channel_unlinked(item: nil, channel: nil, attach: nil) + pattern = (item.nil? && channel.nil?) ? "*" : "#{item || "*"}-#{channel || "*"}" + @ruby_triggers << [:channel_unlinked, pattern] + event("openhab/links/#{pattern}/removed", types: "ItemChannelLinkRemovedEvent", attach: attach) end # @@ -1556,9 +1568,12 @@ def received_command(*items, command: nil, commands: nil, attach: nil) # # Creates an item added trigger # + # @param [String, nil] pattern The pattern to match items against # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for pattern filter was added + # # @example # rule "item added" do # item_added @@ -1566,17 +1581,20 @@ def received_command(*items, command: nil, commands: nil, attach: nil) # logger.info("#{event.item.name} added.") # end # end - def item_added(attach: nil) - @ruby_triggers << [:item_added] - event("openhab/items/*/added", types: "ItemAddedEvent", attach: attach) + def item_added(pattern = "*", attach: nil) + @ruby_triggers << [:item_added, pattern] + event("openhab/items/#{pattern}/added", types: "ItemAddedEvent", attach: attach) end # # Creates an item removed trigger # + # @param [String, nil] pattern The pattern to match items against # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for pattern filter was added + # # @example # rule "item removed" do # item_removed @@ -1584,14 +1602,15 @@ def item_added(attach: nil) # logger.info("#{event.item.name} removed.") # end # end - def item_removed(attach: nil) - @ruby_triggers << [:item_removed] - event("openhab/items/*/removed", types: "ItemRemovedEvent", attach: attach) + def item_removed(pattern = "*", attach: nil) + @ruby_triggers << [:item_removed, pattern] + event("openhab/items/#{pattern}/removed", types: "ItemRemovedEvent", attach: attach) end # # Creates an item updated trigger # + # @param [String, nil] pattern The pattern to match items against # @param [Object] attach object to be attached to the trigger # @return [void] # @@ -1603,17 +1622,20 @@ def item_removed(attach: nil) # end # end # - def item_updated(attach: nil) - @ruby_triggers << [:item_updated] - event("openhab/items/*/updated", types: "ItemUpdatedEvent", attach: attach) + def item_updated(pattern = "*", attach: nil) + @ruby_triggers << [:item_updated, pattern] + event("openhab/items/#{pattern}/updated", types: "ItemUpdatedEvent", attach: attach) end # # Creates a thing added trigger # + # @param [String, nil] pattern The pattern to match things against # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for pattern filter was added + # # @example # rule "thing added" do # thing_added @@ -1621,17 +1643,20 @@ def item_updated(attach: nil) # logger.info("#{event.thing.uid} added.") # end # end - def thing_added(attach: nil) - @ruby_triggers << [:thing_added] - event("openhab/things/*/added", types: "ThingAddedEvent", attach: attach) + def thing_added(pattern = "*", attach: nil) + @ruby_triggers << [:thing_added, pattern] + event("openhab/things/#{pattern}/added", types: "ThingAddedEvent", attach: attach) end # # Creates a thing removed trigger # + # @param [String, nil] pattern The pattern to match things against # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for pattern filter was added + # # @example # rule "thing removed" do # thing_removed @@ -1639,17 +1664,20 @@ def thing_added(attach: nil) # logger.info("#{event.thing.uid} removed.") # end # end - def thing_removed(attach: nil) - @ruby_triggers << [:thing_removed] - event("openhab/things/*/removed", types: "ThingRemovedEvent", attach: attach) + def thing_removed(pattern = "*", attach: nil) + @ruby_triggers << [:thing_removed, pattern] + event("openhab/things/#{pattern}/removed", types: "ThingRemovedEvent", attach: attach) end # # Creates a thing updated trigger # + # @param [String, nil] pattern The pattern to match things against # @param [Object] attach object to be attached to the trigger # @return [void] # + # @since openHAB 4.0 Support for pattern filter was added + # # @example # rule "thing updated" do # thing_updated @@ -1658,9 +1686,9 @@ def thing_removed(attach: nil) # end # end # - def thing_updated(attach: nil) - @ruby_triggers << [:thing_updated] - event("openhab/things/*/updated", types: "ThingUpdatedEvent", attach: attach) + def thing_updated(pattern = "*", attach: nil) + @ruby_triggers << [:thing_updated, pattern] + event("openhab/things/#{pattern}/updated", types: "ThingUpdatedEvent", attach: attach) end # diff --git a/spec/openhab/dsl/rules/builder_spec.rb b/spec/openhab/dsl/rules/builder_spec.rb index 2cf15f1316..55e918a0cc 100644 --- a/spec/openhab/dsl/rules/builder_spec.rb +++ b/spec/openhab/dsl/rules/builder_spec.rb @@ -741,6 +741,49 @@ def self.test_channel_trigger(channel = nil, event: "", &block) expect(linked_item).to be StringItem1 expect(linked_thing).to be things["astro:sun:home"] end + + context "with filtering", if: OpenHAB::Core.version >= OpenHAB::Core::V4_0 do + it "filters by item" do + linked_item = linked_thing = nil + channel_linked(item: "StringItem1") do |event| + linked_item = event.link.item + linked_thing = event.link.channel_uid.thing + end + + items.build { string_item "StringItem1", channel: "astro:sun:home:season#name" } + + expect(linked_item).to be StringItem1 + expect(linked_thing).to be things["astro:sun:home"] + end + + it "filters by channel" do + linked_item = linked_channel = nil + channel_linked(channel: "astro:sun:home:season#name") do |event| + linked_item = event.link.item + linked_channel = event.link.channel_uid + end + + items.build { string_item "StringItem1", channel: "astro:sun:home:season#name" } + StringItem1.link("astro:sun:home:zodiac#sign") + + expect(linked_item).to be StringItem1 + expect(linked_channel).to eq "astro:sun:home:season#name" + end + + it "filters by item and channel" do + linked_item = linked_channel = nil + channel_linked(item: "StringItem1", channel: "astro:sun:home:season#name") do |event| + linked_item = event.link.item + linked_channel = event.link.channel_uid + end + + items.build { string_item "StringItem1", channel: "astro:sun:home:season#name" } + StringItem1.link("astro:sun:home:zodiac#sign") + + expect(linked_item).to be StringItem1 + expect(linked_channel).to eq "astro:sun:home:season#name" + end + end end describe "#received_command" do @@ -847,6 +890,20 @@ def self.test_command_trigger(item, members: false, command: nil, expect_trigger expect(new_item.name).to eql "Item1" end + + it "supports pattern filter", if: OpenHAB::Core.version >= OpenHAB::Core::V4_0 do + new_item = nil + item_added("Item1") do |event| + new_item = event.item + end + + items.build { switch_item Item1 } + expect(new_item.name).to eql "Item1" + + new_item = nil + items.build { switch_item Item2 } + expect(new_item).to be_nil + end end describe "#item_removed" do @@ -861,6 +918,22 @@ def self.test_command_trigger(item, members: false, command: nil, expect_trigger expect(removed_item.name).to eql "Item1" end + + it "supports pattern filter", if: OpenHAB::Core.version >= OpenHAB::Core::V4_0 do + removed_item = nil + item_removed("Item1") do |event| + removed_item = event.item + end + + items.build { switch_item Item1 } + items.remove(Item1) + expect(removed_item.name).to eql "Item1" + + removed_item = nil + items.build { switch_item Item2 } + items.remove(Item2) + expect(removed_item).to be_nil + end end describe "#thing_added" do @@ -874,6 +947,20 @@ def self.test_command_trigger(item, members: false, command: nil, expect_trigger expect(new_thing.uid).to eql "astro:sun:home" end + + it "supports pattern filter", if: OpenHAB::Core.version >= OpenHAB::Core::V4_0 do + new_thing = nil + thing_added("astro:sun:home") do |event| + new_thing = event.thing + end + + things.build { thing "astro:sun:home", config: { "geolocation" => "0,0" } } + expect(new_thing.uid).to eql "astro:sun:home" + + new_thing = nil + things.build { thing "astro:sun:home2", config: { "geolocation" => "0,0" } } + expect(new_thing).to be_nil + end end describe "#thing_removed" do @@ -888,6 +975,22 @@ def self.test_command_trigger(item, members: false, command: nil, expect_trigger expect(removed_thing.uid).to eql "astro:sun:home" end + + it "supports pattern filter", if: OpenHAB::Core.version >= OpenHAB::Core::V4_0 do + removed_thing = nil + thing_removed("astro:sun:home") do |event| + removed_thing = event.thing + end + + things.build { thing "astro:sun:home", config: { "geolocation" => "0,0" } } + things.remove("astro:sun:home") + expect(removed_thing.uid).to eql "astro:sun:home" + + removed_thing = nil + things.build { thing "astro:sun:home2", config: { "geolocation" => "0,0" } } + things.remove("astro:sun:home2") + expect(removed_thing).to be_nil + end end describe "#updated" do