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.
- checksums.yaml +4 -4
- data/lib/openhab/core/items/generic_item.rb +13 -5
- data/lib/openhab/core/items/metadata/hash.rb +17 -34
- data/lib/openhab/core/items/persistence.rb +2 -0
- data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
- data/lib/openhab/core/profile_factory.rb +2 -0
- data/lib/openhab/core/provider.rb +8 -1
- data/lib/openhab/core/rules/provider.rb +25 -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/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/zoned_date_time.rb +1 -2
- data/lib/openhab/core_ext/ruby/date.rb +2 -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 +99 -8
- data/lib/openhab/dsl/rules/name_inference.rb +0 -5
- data/lib/openhab/dsl/rules/terse.rb +1 -2
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +17 -53
- 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 +2 -2
- data/lib/openhab/rspec/example_group.rb +42 -0
- data/lib/openhab/rspec/helpers.rb +31 -8
- data/lib/openhab/rspec/hooks.rb +3 -6
- data/lib/openhab/rspec/karaf.rb +45 -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 +23 -2
@@ -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,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(
|
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.
|
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
|
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
|