Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/openhab/dsl/rules/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,9 @@ def on_load(delay: nil, attach: nil)
# prevent overwriting @on_load
raise ArgumentError, "on_load can only be used once within a rule" if @on_load

@on_load = { module: SecureRandom.uuid, delay: }
rule_uid = Thread.current[:openhab_rule_uid]
module_id = rule_uid ? "#{rule_uid}:on_load" : SecureRandom.uuid
@on_load = { module: module_id, delay: }
attachments[@on_load[:module]] = attach
end

Expand Down
37 changes: 25 additions & 12 deletions lib/openhab/dsl/rules/rule_triggers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def initialize
@triggers = []
@trigger_conditions = Hash.new(Triggers::Conditions::Generic::ANY)
@attachments = {}
@module_counter = 0
end

#
Expand All @@ -43,7 +44,9 @@ def initialize
#
def append_trigger(type:, config:, attach: nil, conditions: nil, label: nil)
config.transform_keys!(&:to_s)
RuleTriggers.trigger(type:, config:, label:).tap do |trigger|
@module_counter += 1
id = infer_module_id(@module_counter)
RuleTriggers.trigger(type:, config:, label:, id:).tap do |trigger|
logger.trace { "Appending trigger (#{trigger.inspect}) attach (#{attach}) conditions(#{conditions})" }
@triggers << trigger
@attachments[trigger.id] = attach if attach
Expand All @@ -57,28 +60,21 @@ def append_trigger(type:, config:, attach: nil, conditions: nil, label: nil)
# @param [String] type of trigger
# @param [Map] config map
# @param [String] label for the trigger
# @param [String] id for the trigger
#
# @return [org.openhab.core.automation.Trigger] configured by type and supplied config
#
def self.trigger(type:, config:, label: nil)
def self.trigger(type:, config:, label: nil, id: nil)
id ||= SecureRandom.uuid
logger.trace { "Creating trigger of type '#{type}' config: #{config}" }
org.openhab.core.automation.util.TriggerBuilder.create
.with_id(uuid)
.with_id(id)
.with_type_uid(type)
.with_configuration(Core::Configuration.new(config))
.with_label(label)
.build
end

#
# Generate a UUID for triggers
#
# @return [String] UUID
#
def self.uuid
SecureRandom.uuid
end

#
# Inspect the config object
#
Expand All @@ -92,6 +88,23 @@ def inspect
Attachments: #{attachments.inspect}>
TEXT
end

private

#
# Generate a deterministic module ID for a trigger based on the rule's UID and the module index
#
# Falls back to a random UUID if no rule UID is available in the thread context.
#
# @param [Integer] index The 1-based index of the module within the rule
# @return [String] The inferred module ID
#
def infer_module_id(index)
rule_uid = Thread.current[:openhab_rule_uid]
return SecureRandom.uuid unless rule_uid

"#{rule_uid}:#{index}"
end
end
end
end
Expand Down
43 changes: 43 additions & 0 deletions spec/openhab/dsl/rules/builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,49 @@ def triggered?
end
end

describe "module id inference" do
it "infers trigger ids from the rule uid" do
items.build { switch_item "MySwitch" }
my_rule = rule id: "my_test_rule" do
changed MySwitch
run { nil }
end
expect(my_rule.triggers.first.id).to eq "my_test_rule:1"
end

it "infers sequential trigger ids for multiple triggers" do
items.build do
switch_item "MySwitch1"
switch_item "MySwitch2"
end
my_rule = rule id: "my_test_rule" do
changed MySwitch1
changed MySwitch2
run { nil }
end
expect(my_rule.triggers.map(&:id)).to eq %w[my_test_rule:1 my_test_rule:2]
end

it "uses a uuid as fallback trigger id when no rule uid is available" do
items.build { switch_item "MySwitch" }
rule_triggers = OpenHAB::DSL::Rules::RuleTriggers.new
trigger = rule_triggers.append_trigger(
type: "core.ItemStateChangeTrigger",
config: { "itemName" => "MySwitch" }
)
expect(trigger.id).to match(/\A[0-9a-f-]{36}\z/)
end

it "infers on_load module id from the rule uid" do
attachment = nil
rule id: "my_load_rule" do
on_load attach: :test_attach
run { |event| attachment = event.attachment }
end
expect(attachment).to eq :test_attach
end
end

describe "#on_start" do
it "works with default level" do
rule = rule do
Expand Down
Loading