openhab-jrubyscripting 5.0.0.rc2 → 5.0.0.rc4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/openhab/core/actions.rb +6 -2
- data/lib/openhab/core/items/generic_item.rb +13 -5
- data/lib/openhab/core/items/metadata/hash.rb +19 -35
- data/lib/openhab/core/items/persistence.rb +3 -1
- data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
- data/lib/openhab/core/items/semantics.rb +18 -22
- data/lib/openhab/core/profile_factory.rb +15 -3
- data/lib/openhab/core/provider.rb +11 -4
- data/lib/openhab/core/rules/module.rb +26 -0
- data/lib/openhab/core/rules/provider.rb +40 -0
- data/lib/openhab/core/rules/registry.rb +76 -0
- data/lib/openhab/core/rules/rule.rb +150 -0
- data/lib/openhab/core/rules.rb +25 -0
- data/lib/openhab/core/script_handling.rb +32 -3
- data/lib/openhab/core/timer.rb +5 -7
- data/lib/openhab/core/types.rb +1 -1
- data/lib/openhab/core.rb +0 -16
- data/lib/openhab/core_ext/java/list.rb +436 -0
- data/lib/openhab/core_ext/java/map.rb +66 -0
- data/lib/openhab/core_ext/java/month.rb +1 -1
- data/lib/openhab/core_ext/java/zoned_date_time.rb +1 -2
- data/lib/openhab/core_ext/ruby/date.rb +3 -0
- data/lib/openhab/core_ext/ruby/date_time.rb +53 -0
- data/lib/openhab/core_ext/ruby/time.rb +88 -86
- data/lib/openhab/dsl/events/watch_event.rb +1 -1
- data/lib/openhab/dsl/items/builder.rb +8 -3
- data/lib/openhab/dsl/items/ensure.rb +6 -2
- data/lib/openhab/dsl/items/timed_command.rb +10 -11
- data/lib/openhab/dsl/rules/automation_rule.rb +36 -13
- data/lib/openhab/dsl/rules/builder.rb +100 -9
- data/lib/openhab/dsl/rules/name_inference.rb +0 -5
- data/lib/openhab/dsl/rules/rule_triggers.rb +1 -1
- data/lib/openhab/dsl/rules/terse.rb +1 -2
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +18 -54
- data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +0 -3
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
- data/lib/openhab/dsl/rules.rb +0 -21
- data/lib/openhab/dsl/thread_local.rb +2 -2
- data/lib/openhab/dsl/timer_manager.rb +3 -1
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/dsl.rb +12 -105
- data/lib/openhab/log.rb +9 -2
- data/lib/openhab/rspec/example_group.rb +42 -0
- data/lib/openhab/rspec/helpers.rb +31 -8
- data/lib/openhab/rspec/hooks.rb +6 -10
- data/lib/openhab/rspec/karaf.rb +50 -27
- data/lib/openhab/rspec/mocks/synchronous_executor.rb +11 -4
- data/lib/openhab/rspec/mocks/timer.rb +2 -1
- data/lib/openhab/rspec/suspend_rules.rb +4 -2
- metadata +24 -3
- data/lib/openhab/dsl/script_handling.rb +0 -6
@@ -2,103 +2,105 @@
|
|
2
2
|
|
3
3
|
require "forwardable"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
33
|
-
|
21
|
+
plus_without_temporal(other)
|
22
|
+
end
|
23
|
+
alias_method :plus_without_temporal, :+
|
24
|
+
alias_method :+, :plus_with_temporal
|
34
25
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
minus_without_temporal(other)
|
62
|
+
end
|
63
|
+
alias_method :minus_without_temporal, :-
|
64
|
+
alias_method :-, :minus_with_temporal
|
54
65
|
|
55
|
-
|
56
|
-
|
57
|
-
|
66
|
+
# @return [LocalDate]
|
67
|
+
def to_local_date(_context = nil)
|
68
|
+
java.time.LocalDate.of(year, month, day)
|
69
|
+
end
|
58
70
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
71
|
+
# @!method to_local_time
|
72
|
+
# @return [LocalTime]
|
73
|
+
def_delegator :to_zoned_date_time, :to_local_time
|
63
74
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
# @return [Month]
|
76
|
+
def to_month
|
77
|
+
java.time.Month.of(month)
|
78
|
+
end
|
68
79
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
#
|
94
|
-
#
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
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,
|
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
|
-
|
126
|
+
DSL.rules[timed_command_details.rule_uid].disable
|
127
127
|
super(command)
|
128
|
-
|
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
|
-
|
149
|
-
|
150
|
-
|
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.
|
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.
|
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
|
-
|
57
|
-
|
58
|
-
|
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(
|
96
|
+
@run_queue.dup.grep_v(BuilderDSL::Otherwise)
|
74
97
|
when false
|
75
|
-
@run_queue.dup.grep(
|
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?(
|
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
|
187
|
-
when
|
188
|
-
when
|
189
|
-
when
|
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
|
-
#
|
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,15 +1410,14 @@ 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(
|
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
|
-
added_rule.actions.first.configuration.put("script", script)
|
1420
|
+
added_rule.actions.first.configuration.put("script", script) if script
|
1331
1421
|
|
1332
1422
|
rule.execute(nil, { "event" => Struct.new(:attachment).new(start_attachment) }) if on_start?
|
1333
1423
|
added_rule
|
@@ -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.
|
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)
|
@@ -44,7 +44,7 @@ module OpenHAB
|
|
44
44
|
def append_trigger(type:, config:, attach: nil, conditions: nil)
|
45
45
|
config.transform_keys!(&:to_s)
|
46
46
|
RuleTriggers.trigger(type: type, config: config).tap do |trigger|
|
47
|
-
logger.trace("Appending trigger (#{trigger}) attach (#{attach}) conditions(#{conditions})")
|
47
|
+
logger.trace("Appending trigger (#{trigger.inspect}) attach (#{attach}) conditions(#{conditions})")
|
48
48
|
@triggers << trigger
|
49
49
|
@attachments[trigger.id] = attach if attach
|
50
50
|
@trigger_conditions[trigger.id] = conditions if conditions
|
@@ -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
|
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
|