openhab-jrubyscripting 5.0.0.rc2 → 5.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/items/generic_item.rb +13 -5
  3. data/lib/openhab/core/items/metadata/hash.rb +17 -34
  4. data/lib/openhab/core/items/persistence.rb +2 -0
  5. data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
  6. data/lib/openhab/core/profile_factory.rb +2 -0
  7. data/lib/openhab/core/provider.rb +8 -1
  8. data/lib/openhab/core/rules/provider.rb +25 -0
  9. data/lib/openhab/core/rules/registry.rb +76 -0
  10. data/lib/openhab/core/rules/rule.rb +150 -0
  11. data/lib/openhab/core/rules.rb +25 -0
  12. data/lib/openhab/core/timer.rb +5 -7
  13. data/lib/openhab/core/types.rb +1 -1
  14. data/lib/openhab/core.rb +0 -16
  15. data/lib/openhab/core_ext/java/list.rb +436 -0
  16. data/lib/openhab/core_ext/java/map.rb +66 -0
  17. data/lib/openhab/core_ext/java/zoned_date_time.rb +1 -2
  18. data/lib/openhab/core_ext/ruby/date.rb +2 -0
  19. data/lib/openhab/core_ext/ruby/date_time.rb +53 -0
  20. data/lib/openhab/core_ext/ruby/time.rb +88 -86
  21. data/lib/openhab/dsl/events/watch_event.rb +1 -1
  22. data/lib/openhab/dsl/items/builder.rb +8 -3
  23. data/lib/openhab/dsl/items/ensure.rb +6 -2
  24. data/lib/openhab/dsl/items/timed_command.rb +10 -11
  25. data/lib/openhab/dsl/rules/automation_rule.rb +36 -13
  26. data/lib/openhab/dsl/rules/builder.rb +99 -8
  27. data/lib/openhab/dsl/rules/name_inference.rb +0 -5
  28. data/lib/openhab/dsl/rules/terse.rb +1 -2
  29. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +17 -53
  30. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +0 -3
  31. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
  32. data/lib/openhab/dsl/rules.rb +0 -21
  33. data/lib/openhab/dsl/thread_local.rb +2 -2
  34. data/lib/openhab/dsl/timer_manager.rb +3 -1
  35. data/lib/openhab/dsl/version.rb +1 -1
  36. data/lib/openhab/dsl.rb +12 -105
  37. data/lib/openhab/log.rb +2 -2
  38. data/lib/openhab/rspec/example_group.rb +42 -0
  39. data/lib/openhab/rspec/helpers.rb +31 -8
  40. data/lib/openhab/rspec/hooks.rb +3 -6
  41. data/lib/openhab/rspec/karaf.rb +45 -27
  42. data/lib/openhab/rspec/mocks/synchronous_executor.rb +11 -4
  43. data/lib/openhab/rspec/mocks/timer.rb +2 -1
  44. data/lib/openhab/rspec/suspend_rules.rb +4 -2
  45. metadata +23 -2
@@ -2,103 +2,105 @@
2
2
 
3
3
  require "forwardable"
4
4
 
5
- module OpenHAB
6
- module CoreExt
7
- module Ruby
8
- # Extensions to Time and DateTime
9
- module TimeExtensions
10
- extend Forwardable
11
-
12
- # @!visibility private
13
- def self.included(base)
14
- base.send :alias_method, :plus_without_temporal, :+
15
- base.send :alias_method, :+, :plus_with_temporal
16
- base.send :alias_method, :minus_without_temporal, :-
17
- base.send :alias_method, :-, :minus_with_temporal
18
- end
5
+ # Extensions to Time
6
+ class Time
7
+ extend Forwardable
19
8
 
20
- #
21
- # @!method +(other)
22
- #
23
- # Extends {#+} to allow adding a {java.time.temporal.TemporalAmount TemporalAmount}
24
- #
25
- # @param [java.time.temporal.TemporalAmount] other
26
- # @return [ZonedDateTime] If other is a {java.time.temporal.TemporalAmount TemporalAmount}
27
- # @return [Time] If other is a Numeric
28
- #
29
- def plus_with_temporal(other)
30
- return to_zoned_date_time + other if other.is_a?(java.time.temporal.TemporalAmount)
9
+ #
10
+ # @!method +(other)
11
+ #
12
+ # Extends {#+} to allow adding a {java.time.temporal.TemporalAmount TemporalAmount}
13
+ #
14
+ # @param [java.time.temporal.TemporalAmount] other
15
+ # @return [ZonedDateTime] If other is a {java.time.temporal.TemporalAmount TemporalAmount}
16
+ # @return [Time] If other is a Numeric
17
+ #
18
+ def plus_with_temporal(other)
19
+ return to_zoned_date_time + other if other.is_a?(java.time.temporal.TemporalAmount)
31
20
 
32
- plus_without_temporal(other)
33
- end
21
+ plus_without_temporal(other)
22
+ end
23
+ alias_method :plus_without_temporal, :+
24
+ alias_method :+, :plus_with_temporal
34
25
 
35
- #
36
- # @!method -(other)
37
- #
38
- # Extends {#-} to allow subtracting a {java.time.temporal.TemporalAmount TemporalAmount}
39
- #
40
- # @param [java.time.temporal.TemporalAmount] other
41
- # @return [ZonedDateTime] If other is a {java.time.temporal.TemporalAmount TemporalAmount}
42
- # @return [Time] If other is a Numeric
43
- #
44
- def minus_with_temporal(other)
45
- return to_zoned_date_time - other if other.is_a?(java.time.temporal.TemporalAmount)
26
+ #
27
+ # @!method -(other)
28
+ #
29
+ # Extends {#-} to allow subtracting a {java.time.temporal.TemporalAmount TemporalAmount}
30
+ # or any other date/time class that responds to #to_zoned_date_time.
31
+ #
32
+ # Subtractions with another object of the same class (e.g. Time - Other Time, or DateTime - Other DateTime)
33
+ # remains unchanged from its original behavior.
34
+ #
35
+ # @example Time - Duration -> ZonedDateTime
36
+ # zdt_one_hour_ago = Time.now - 1.hour
37
+ #
38
+ # @example Time - ZonedDateTime -> Duration
39
+ # java_duration = Time.now - 1.hour.ago
40
+ #
41
+ # @example Time - Numeric -> Time
42
+ # time_one_hour_ago = Time - 3600
43
+ #
44
+ # @example Time - Time -> Float
45
+ # one_day_in_secs = Time.new(2002, 10, 31) - Time.new(2002, 10, 30)
46
+ #
47
+ # @param [java.time.temporal.TemporalAmount, #to_zoned_date_time] other
48
+ # @return [ZonedDateTime] If other is a {java.time.temporal.TemporalAmount TemporalAmount}
49
+ # @return [Duration] If other responds to #to_zoned_date_time
50
+ # @return [Time] If other is a Numeric
51
+ # @return [Float] If other is a Time
52
+ #
53
+ def minus_with_temporal(other)
54
+ return to_zoned_date_time - other if other.is_a?(java.time.temporal.TemporalAmount)
46
55
 
47
- minus_without_temporal(other)
48
- end
56
+ # Exclude subtracting against the same class
57
+ if other.respond_to?(:to_zoned_date_time) && !other.is_a?(self.class)
58
+ return to_zoned_date_time - other.to_zoned_date_time
59
+ end
49
60
 
50
- # @return [LocalDate]
51
- def to_local_date(_context = nil)
52
- java.time.LocalDate.of(year, month, day)
53
- end
61
+ minus_without_temporal(other)
62
+ end
63
+ alias_method :minus_without_temporal, :-
64
+ alias_method :-, :minus_with_temporal
54
65
 
55
- # @!method to_local_time
56
- # @return [LocalTime]
57
- def_delegator :to_zoned_date_time, :to_local_time
66
+ # @return [LocalDate]
67
+ def to_local_date(_context = nil)
68
+ java.time.LocalDate.of(year, month, day)
69
+ end
58
70
 
59
- # @return [Month]
60
- def to_month
61
- java.time.Month.of(month)
62
- end
71
+ # @!method to_local_time
72
+ # @return [LocalTime]
73
+ def_delegator :to_zoned_date_time, :to_local_time
63
74
 
64
- # @return [MonthDay]
65
- def to_month_day
66
- java.time.MonthDay.of(month, day)
67
- end
75
+ # @return [Month]
76
+ def to_month
77
+ java.time.Month.of(month)
78
+ end
68
79
 
69
- # @param [ZonedDateTime, nil] context
70
- # A {ZonedDateTime} used to fill in missing fields
71
- # during conversion. Not used in this class.
72
- # @return [ZonedDateTime]
73
- def to_zoned_date_time(context = nil) # rubocop:disable Lint/UnusedMethodArgument
74
- to_java(ZonedDateTime)
75
- end
80
+ # @return [MonthDay]
81
+ def to_month_day
82
+ java.time.MonthDay.of(month, day)
83
+ end
76
84
 
77
- #
78
- # Converts to a {ZonedDateTime} if `other`
79
- # is also convertible to a ZonedDateTime.
80
- #
81
- # @param [#to_zoned_date_time] other
82
- # @return [Array, nil]
83
- #
84
- def coerce(other)
85
- [other.to_zoned_date_time(to_zoned_date_time), self] if other.respond_to?(:to_zoned_date_time)
86
- end
87
- end
88
- end
85
+ # @param [ZonedDateTime, nil] context
86
+ # A {ZonedDateTime} used to fill in missing fields
87
+ # during conversion. Not used in this class.
88
+ # @return [ZonedDateTime]
89
+ def to_zoned_date_time(context = nil) # rubocop:disable Lint/UnusedMethodArgument
90
+ to_java(java.time.ZonedDateTime)
89
91
  end
90
- end
91
92
 
92
- #
93
- # Extensions to Ruby Time
94
- #
95
- class Time
96
- include(OpenHAB::CoreExt::Ruby::TimeExtensions)
97
- end
93
+ #
94
+ # Converts to a {ZonedDateTime} if `other`
95
+ # is also convertible to a ZonedDateTime.
96
+ #
97
+ # @param [#to_zoned_date_time] other
98
+ # @return [Array, nil]
99
+ #
100
+ def coerce(other)
101
+ return unless other.respond_to?(:to_zoned_date_time)
98
102
 
99
- #
100
- # Extensions to Ruby DateTime
101
- #
102
- class DateTime
103
- include(OpenHAB::CoreExt::Ruby::TimeExtensions)
103
+ zdt = to_zoned_date_time
104
+ [other.to_zoned_date_time(zdt), zdt]
105
+ end
104
106
  end
@@ -4,7 +4,7 @@ module OpenHAB
4
4
  module DSL
5
5
  module Events
6
6
  #
7
- # Event object passed by a {Rules::Builder#watch} trigger.
7
+ # Event object passed by a {Rules::BuilderDSL#watch} trigger.
8
8
  #
9
9
  # @!attribute [r] path
10
10
  # @return [Pathname] The path that had an event
@@ -40,7 +40,7 @@ module OpenHAB
40
40
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
41
41
  def #{method}_item(*args, **kwargs, &block) # def dimmer_item(*args, **kwargs, &block)
42
42
  item(#{method.inspect}, *args, **kwargs, &block) # item(:dimmer, *args, **kwargs, &block)
43
- end
43
+ end # end
44
44
  RUBY
45
45
  end
46
46
  end
@@ -251,7 +251,12 @@ module OpenHAB
251
251
  @autoupdate = autoupdate
252
252
  @channels = []
253
253
  @expire = nil
254
- self.expire(*Array(expire)) if expire
254
+ if expire
255
+ expire = Array(expire)
256
+ expire_config = expire.pop if expire.last.is_a?(Hash)
257
+ expire_config ||= {}
258
+ self.expire(*expire, **expire_config)
259
+ end
255
260
  self.alexa(alexa) if alexa
256
261
  self.ga(ga) if ga
257
262
  self.homekit(homekit) if homekit
@@ -365,7 +370,7 @@ module OpenHAB
365
370
  # end
366
371
  # end
367
372
  #
368
- def channel(channel, **config)
373
+ def channel(channel, config = {})
369
374
  @channels << [channel, config]
370
375
  end
371
376
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "ruby2_keywords"
4
+
3
5
  module OpenHAB
4
6
  module DSL
5
7
  module Items
@@ -21,6 +23,9 @@ module OpenHAB
21
23
  end
22
24
 
23
25
  # Extensions for {::GenericItem} to implement {Ensure}'s functionality
26
+ #
27
+ # @see OpenHAB::DSL.ensure ensure
28
+ # @see OpenHAB::DSL.ensure_states ensure_states
24
29
  module GenericItem
25
30
  include Ensurable
26
31
 
@@ -71,14 +76,13 @@ module OpenHAB
71
76
  end
72
77
 
73
78
  # activate `ensure_states` before forwarding to the wrapped object
74
- def method_missing(method, *args, &block)
79
+ ruby2_keywords def method_missing(method, *args, &block)
75
80
  return super unless @item.respond_to?(method)
76
81
 
77
82
  DSL.ensure_states do
78
83
  @item.__send__(method, *args, &block)
79
84
  end
80
85
  end
81
- ruby2_keywords :method_missing if respond_to? :ruby2_keywords
82
86
 
83
87
  # .
84
88
  def respond_to_missing?(method, include_private = false)
@@ -123,9 +123,9 @@ module OpenHAB
123
123
  timed_command_details.on_expire = on_expire unless on_expire.nil?
124
124
  timed_command_details.timer.reschedule(duration)
125
125
  # disable the cancel rule while we send the new command
126
- Core.rule_manager.set_enabled(timed_command_details.rule_uid, false)
126
+ DSL.rules[timed_command_details.rule_uid].disable
127
127
  super(command)
128
- Core.rule_manager.set_enabled(timed_command_details.rule_uid, true)
128
+ DSL.rules[timed_command_details.rule_uid].enable
129
129
  timed_command_details
130
130
  end
131
131
  end
@@ -145,10 +145,9 @@ module OpenHAB
145
145
 
146
146
  timed_command_details.timer = timed_command_timer(timed_command_details, duration)
147
147
  cancel_rule = TimedCommandCancelRule.new(timed_command_details)
148
- timed_command_details.rule_uid = Core.automation_manager
149
- .add_rule(cancel_rule)
150
- .uid
151
- Rules.script_rules[timed_command_details.rule_uid] = cancel_rule
148
+ unmanaged_rule = Core.automation_manager.add_unmanaged_rule(cancel_rule)
149
+ timed_command_details.rule_uid = unmanaged_rule.uid
150
+ Core::Rules::Provider.current.add(unmanaged_rule)
152
151
  logger.trace "Created Timed Command #{timed_command_details}"
153
152
  timed_command_details
154
153
  end
@@ -160,7 +159,7 @@ module OpenHAB
160
159
  DSL.after(duration) do
161
160
  timed_command_details.mutex.synchronize do
162
161
  logger.trace "Timed command expired - #{timed_command_details}"
163
- DSL.remove_rule(timed_command_details.rule_uid)
162
+ DSL.rules.remove(timed_command_details.rule_uid)
164
163
  timed_command_details.resolution = :expired
165
164
  case timed_command_details.on_expire
166
165
  when Proc
@@ -200,11 +199,9 @@ module OpenHAB
200
199
  type: Rules::Triggers::Changed::ITEM_STATE_CHANGE,
201
200
  config: { "itemName" => timed_command_details.item.name }
202
201
  )]
202
+ self.visibility = Core::Rules::Visibility::HIDDEN
203
203
  end
204
204
 
205
- # Cleanup the rule; nothing to do here.
206
- def cleanup; end
207
-
208
205
  #
209
206
  # Execute the rule
210
207
  #
@@ -217,7 +214,7 @@ module OpenHAB
217
214
  logger.trace "Canceling implicit timer #{@timed_command_details.timer} for "\
218
215
  "#{@timed_command_details.item.name} because received event #{inputs}"
219
216
  @timed_command_details.timer.cancel
220
- DSL.remove_rule(@timed_command_details.rule_uid)
217
+ DSL.rules.remove(@timed_command_details.rule_uid)
221
218
  @timed_command_details.resolution = :cancelled
222
219
  if @timed_command_details.on_expire.is_a?(Proc)
223
220
  logger.trace "Executing user supplied block on timed command cancelation"
@@ -226,6 +223,8 @@ module OpenHAB
226
223
  end
227
224
  TimedCommand.timed_commands.delete(@timed_command_details.item)
228
225
  rescue Exception => e
226
+ raise if defined?(::RSpec)
227
+
229
228
  logger.log_exception(e)
230
229
  end
231
230
  end
@@ -16,7 +16,7 @@ module OpenHAB
16
16
  # @param [Config] config Rule configuration
17
17
  #
18
18
  # Constructor sets a number of variables, no further decomposition necessary
19
- def initialize(config:)
19
+ def initialize(config)
20
20
  # Metrics disabled because only setters are called or defaults set.
21
21
  super()
22
22
  set_name(config.name)
@@ -29,8 +29,13 @@ module OpenHAB
29
29
  @guard = config.guard
30
30
  @between = config.between && DSL.between(config.between)
31
31
  @trigger_conditions = config.trigger_conditions
32
+ @trigger_conditions.each_value do |condition|
33
+ condition.rule = self if condition.respond_to?(:rule=)
34
+ end
32
35
  @attachments = config.attachments
33
36
  @thread_locals = ThreadLocal.persist
37
+ @cleanup_hooks = Set.new
38
+ @listener = nil
34
39
  end
35
40
 
36
41
  #
@@ -48,19 +53,37 @@ module OpenHAB
48
53
  process_queue(create_queue(inputs), mod, inputs)
49
54
  end
50
55
  rescue Exception => e
56
+ raise if defined?(::RSpec)
57
+
51
58
  @run_context.send(:logger).log_exception(e)
52
59
  end
53
60
  end
54
61
 
55
- #
56
- # Cleanup any resources associated with automation rule
57
- #
58
- def cleanup
59
- @trigger_conditions.each_value(&:cleanup)
62
+ # @!visibility private
63
+ def on_removal(listener)
64
+ @cleanup_hooks << listener
65
+ listen_for_removal unless @listener
60
66
  end
61
67
 
62
68
  private
63
69
 
70
+ def cleanup
71
+ @cleanup_hooks.each(&:cleanup)
72
+ end
73
+
74
+ def listen_for_removal
75
+ @listener ||= org.openhab.core.common.registry.RegistryChangeListener.impl do |method, element|
76
+ next unless method == :removed
77
+
78
+ logger.trace("Rule #{element.inspect} removed from registry")
79
+ next unless element.uid == uid
80
+
81
+ cleanup
82
+ $rules.remove_registry_change_listener(@listener)
83
+ end
84
+ $rules.add_registry_change_listener(@listener)
85
+ end
86
+
64
87
  #
65
88
  # Create the run queue based on guards
66
89
  #
@@ -70,9 +93,9 @@ module OpenHAB
70
93
  def create_queue(inputs)
71
94
  case check_guards(event: extract_event(inputs))
72
95
  when true
73
- @run_queue.dup.grep_v(Builder::Otherwise)
96
+ @run_queue.dup.grep_v(BuilderDSL::Otherwise)
74
97
  when false
75
- @run_queue.dup.grep(Builder::Otherwise)
98
+ @run_queue.dup.grep(BuilderDSL::Otherwise)
76
99
  end
77
100
  end
78
101
 
@@ -166,7 +189,7 @@ module OpenHAB
166
189
  event = extract_event(inputs)
167
190
 
168
191
  while (task = run_queue.shift)
169
- if task.is_a?(Builder::Delay)
192
+ if task.is_a?(BuilderDSL::Delay)
170
193
  process_delay_task(inputs, mod, run_queue, task)
171
194
  else
172
195
  process_task(event, task)
@@ -183,10 +206,10 @@ module OpenHAB
183
206
  def process_task(event, task)
184
207
  ThreadLocal.thread_local(**@thread_locals) do
185
208
  case task
186
- when Builder::Run then process_run_task(event, task)
187
- when Builder::Script then process_script_task(task)
188
- when Builder::Trigger then process_trigger_task(event, task)
189
- when Builder::Otherwise then process_otherwise_task(event, task)
209
+ when BuilderDSL::Run then process_run_task(event, task)
210
+ when BuilderDSL::Script then process_script_task(task)
211
+ when BuilderDSL::Trigger then process_trigger_task(event, task)
212
+ when BuilderDSL::Otherwise then process_otherwise_task(event, task)
190
213
  end
191
214
  end
192
215
  end
@@ -5,6 +5,7 @@ require "forwardable"
5
5
  require_relative "property"
6
6
  require_relative "guard"
7
7
  require_relative "rule_triggers"
8
+ require_relative "terse"
8
9
 
9
10
  Dir[File.expand_path("triggers/*.rb", __dir__)].sort.each do |f|
10
11
  require f
@@ -16,10 +17,100 @@ module OpenHAB
16
17
  # Creates and manages OpenHAB Rules
17
18
  #
18
19
  module Rules
20
+ # A rules builder allows you to create OpenHAB rules.
19
21
  #
20
- # Rule configuration for OpenHAB Rules engine
22
+ # Note that all methods on this module are also availabe directly on {OpenHAB::DSL}.
21
23
  #
22
24
  class Builder
25
+ include Terse
26
+
27
+ # @return [org.openhab.core.automation.RuleProvider]
28
+ attr_reader :provider
29
+
30
+ def initialize(provider)
31
+ @provider = Core::Rules::Provider.current(provider)
32
+ end
33
+
34
+ #
35
+ # Create a new rule
36
+ #
37
+ # @param [String] name The rule name
38
+ # @yield Block executed in the context of a {Rules::Builder}
39
+ # @yieldparam [Rules::Builder] rule
40
+ # Optional parameter to access the rule configuration from within execution blocks and guards.
41
+ # @return [Rule]
42
+ #
43
+ # @see OpenHAB::DSL::Rules::Builder Rule builder for details on rule triggers, guards and execution blocks
44
+ # @see Rules::Terse Terse Rules
45
+ #
46
+ # @example
47
+ # require "openhab/dsl"
48
+ #
49
+ # rule "name" do
50
+ # <zero or more triggers>
51
+ # <zero or more execution blocks>
52
+ # <zero or more guards>
53
+ # end
54
+ #
55
+ def rule(name = nil, id: nil, script: nil, binding: nil, &block)
56
+ raise ArgumentError, "Block is required" unless block
57
+
58
+ id ||= NameInference.infer_rule_id_from_block(block)
59
+ script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
60
+
61
+ builder = nil
62
+
63
+ ThreadLocal.thread_local(openhab_rule_type: "rule", openhab_rule_uid: id) do
64
+ builder = BuilderDSL.new(binding || block.binding)
65
+ builder.uid(id)
66
+ builder.instance_exec(builder, &block)
67
+ builder.guard = Guard.new(run_context: builder.caller, only_if: builder.only_if,
68
+ not_if: builder.not_if)
69
+
70
+ name ||= NameInference.infer_rule_name(builder)
71
+ name ||= id
72
+
73
+ builder.name(name)
74
+ logger.trace { builder.inspect }
75
+ builder.build(provider, script)
76
+ end
77
+ end
78
+
79
+ #
80
+ # Create a new script
81
+ #
82
+ # A script is a rule with no triggers. It can be called by various other actions,
83
+ # such as the Run Rules action.
84
+ #
85
+ # @param [String] name A descriptive name
86
+ # @param [String] id The script's ID
87
+ # @yield [] Block executed when the script is executed.
88
+ # @return [Rule]
89
+ #
90
+ def script(name = nil, id: nil, script: nil, &block)
91
+ raise ArgumentError, "Block is required" unless block
92
+
93
+ id ||= NameInference.infer_rule_id_from_block(block)
94
+ name ||= id
95
+ script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
96
+
97
+ builder = nil
98
+ ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
99
+ builder = BuilderDSL.new(block.binding)
100
+ builder.uid(id)
101
+ builder.tags(["Script"])
102
+ builder.name(name)
103
+ builder.script(&block)
104
+ logger.trace { builder.inspect }
105
+ builder.build(provider, script)
106
+ end
107
+ end
108
+ end
109
+
110
+ #
111
+ # Rule configuration for OpenHAB Rules engine
112
+ #
113
+ class BuilderDSL
23
114
  include Core::EntityLookup
24
115
  include DSL
25
116
  prepend Triggers
@@ -1319,12 +1410,11 @@ module OpenHAB
1319
1410
  # @param [String] script The source code of the rule
1320
1411
  #
1321
1412
  # @!visibility private
1322
- def build(script)
1413
+ def build(provider, script)
1323
1414
  return unless create_rule?
1324
1415
 
1325
- rule = AutomationRule.new(config: self)
1326
- added_rule = add_rule(rule)
1327
- Rules.script_rules[rule.uid] = rule
1416
+ rule = AutomationRule.new(self)
1417
+ added_rule = add_rule(provider, rule)
1328
1418
  # add config so that MainUI can show the script
1329
1419
  added_rule.actions.first.configuration.put("type", "application/x-ruby")
1330
1420
  added_rule.actions.first.configuration.put("script", script)
@@ -1383,8 +1473,7 @@ module OpenHAB
1383
1473
  #
1384
1474
  # @param [org.openhab.core.automation.module.script.rulesupport.shared.simple.SimpleRule] rule to add
1385
1475
  #
1386
- #
1387
- def add_rule(rule)
1476
+ def add_rule(provider, rule)
1388
1477
  base_uid = rule.uid
1389
1478
  duplicate_index = 1
1390
1479
  while $rules.get(rule.uid)
@@ -1392,7 +1481,9 @@ module OpenHAB
1392
1481
  rule.uid = "#{base_uid} (#{duplicate_index})"
1393
1482
  end
1394
1483
  logger.trace("Adding rule: #{rule}")
1395
- Core.automation_manager.add_rule(rule)
1484
+ unmanaged_rule = Core.automation_manager.add_unmanaged_rule(rule)
1485
+ provider.add(unmanaged_rule)
1486
+ unmanaged_rule
1396
1487
  end
1397
1488
  end
1398
1489
  end
@@ -23,11 +23,6 @@ module OpenHAB
23
23
  private_constant :KNOWN_TRIGGER_TYPES
24
24
 
25
25
  class << self
26
- # takes a freeform rule name and makes it more palatable as an id
27
- def infer_rule_id_from_name(name)
28
- name.downcase.delete("'\"").gsub(/\W+/, "_")
29
- end
30
-
31
26
  # get the block's source location, and simplify to a simple filename
32
27
  def infer_rule_id_from_block(block)
33
28
  file = File.basename(block.source_location.first)
@@ -26,13 +26,12 @@ module OpenHAB
26
26
  # @param id [String] The ID for the rule.
27
27
  # @yield The execution block for the rule.
28
28
  # @return [void]
29
- # @see Builder#$1
29
+ # @see BuilderDSL#$1
30
30
  def def_terse_rule(trigger)
31
31
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
32
32
  def #{trigger}(*args, name: nil, id: nil, **kwargs, &block) # def changed(*args, name: nil, id: nil, **kwargs, &block)
33
33
  raise ArgumentError, "Block is required" unless block # raise ArgumentError, "Block is required" unless block
34
34
  #
35
- id ||= NameInference.infer_rule_id_from_name(name) if name # id ||= NameInference.infer_rule_id_from_name(name) if name
36
35
  id ||= NameInference.infer_rule_id_from_block(block) # id ||= NameInference.infer_rule_id_from_block(block)
37
36
  script = block.source rescue nil # script = block.source rescue nil
38
37
  caller_binding = block.binding # caller_binding = block.binding