openhab-scripting 2.16.2 → 2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +12 -16
  3. data/lib/openhab/core/entity_lookup.rb +173 -0
  4. data/lib/openhab/core/openhab_setup.rb +31 -0
  5. data/lib/openhab/core/osgi.rb +61 -0
  6. data/lib/openhab/dsl/actions.rb +105 -0
  7. data/lib/openhab/dsl/dsl.rb +49 -0
  8. data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
  9. data/lib/openhab/dsl/group.rb +100 -0
  10. data/lib/openhab/dsl/items/datetime_item.rb +97 -0
  11. data/lib/openhab/dsl/items/items.rb +46 -0
  12. data/lib/openhab/dsl/items/number_item.rb +352 -0
  13. data/lib/openhab/dsl/items/rollershutter_item.rb +179 -0
  14. data/lib/openhab/dsl/items/string_item.rb +120 -0
  15. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
  16. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
  17. data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
  18. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
  19. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
  20. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
  21. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
  22. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
  23. data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
  24. data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
  25. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
  26. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
  27. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
  28. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
  29. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
  30. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +8 -0
  31. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
  32. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +32 -0
  33. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
  34. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
  35. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
  36. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
  37. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
  38. data/lib/openhab/dsl/monkey_patch/types/types.rb +9 -0
  39. data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +33 -0
  40. data/lib/openhab/dsl/persistence.rb +25 -0
  41. data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
  42. data/lib/openhab/dsl/rules/guard.rb +134 -0
  43. data/lib/openhab/dsl/rules/property.rb +102 -0
  44. data/lib/openhab/dsl/rules/rule.rb +116 -0
  45. data/lib/openhab/dsl/rules/rule_config.rb +151 -0
  46. data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
  47. data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
  48. data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
  49. data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
  50. data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
  51. data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
  52. data/lib/openhab/dsl/states.rb +61 -0
  53. data/lib/openhab/dsl/things.rb +91 -0
  54. data/lib/openhab/dsl/time_of_day.rb +232 -0
  55. data/lib/openhab/dsl/timers.rb +77 -0
  56. data/lib/openhab/dsl/types/datetime.rb +326 -0
  57. data/lib/openhab/dsl/types/quantity.rb +290 -0
  58. data/lib/openhab/dsl/units.rb +39 -0
  59. data/lib/openhab/log/configuration.rb +21 -0
  60. data/lib/openhab/log/logger.rb +172 -0
  61. data/lib/openhab/version.rb +1 -1
  62. metadata +60 -58
  63. data/lib/openhab/configuration.rb +0 -16
  64. data/lib/openhab/core/cron.rb +0 -27
  65. data/lib/openhab/core/debug.rb +0 -34
  66. data/lib/openhab/core/dsl.rb +0 -51
  67. data/lib/openhab/core/dsl/actions.rb +0 -107
  68. data/lib/openhab/core/dsl/entities.rb +0 -147
  69. data/lib/openhab/core/dsl/group.rb +0 -102
  70. data/lib/openhab/core/dsl/items/items.rb +0 -51
  71. data/lib/openhab/core/dsl/items/number_item.rb +0 -323
  72. data/lib/openhab/core/dsl/items/string_item.rb +0 -122
  73. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
  74. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
  75. data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
  76. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
  77. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
  78. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
  79. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
  80. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -182
  81. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
  82. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
  83. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
  84. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
  85. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
  86. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
  87. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
  88. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -7
  89. data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +0 -43
  90. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -60
  91. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
  92. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
  93. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
  94. data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +0 -58
  95. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -8
  96. data/lib/openhab/core/dsl/persistence.rb +0 -27
  97. data/lib/openhab/core/dsl/property.rb +0 -96
  98. data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -345
  99. data/lib/openhab/core/dsl/rule/guard.rb +0 -136
  100. data/lib/openhab/core/dsl/rule/rule.rb +0 -117
  101. data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
  102. data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
  103. data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
  104. data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
  105. data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
  106. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
  107. data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
  108. data/lib/openhab/core/dsl/states.rb +0 -63
  109. data/lib/openhab/core/dsl/things.rb +0 -93
  110. data/lib/openhab/core/dsl/time_of_day.rb +0 -231
  111. data/lib/openhab/core/dsl/timers.rb +0 -79
  112. data/lib/openhab/core/dsl/types/quantity.rb +0 -292
  113. data/lib/openhab/core/dsl/units.rb +0 -41
  114. data/lib/openhab/core/log.rb +0 -170
  115. data/lib/openhab/core/patch_load_path.rb +0 -7
  116. data/lib/openhab/core/startup_delay.rb +0 -23
  117. data/lib/openhab/osgi.rb +0 -59
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'delegate'
4
-
5
- module OpenHAB
6
- module Core
7
- module DSL
8
- #
9
- # Manages storing and restoring item state
10
- #
11
- module States
12
- java_import org.openhab.core.model.script.actions.BusEvent
13
-
14
- #
15
- # Delegates state storage to a Hash providing methods to operate with states
16
- #
17
- class StateStorage < SimpleDelegator
18
- #
19
- # Restore the stored states of all items
20
- #
21
- #
22
- def restore
23
- BusEvent.restoreStates(to_h)
24
- end
25
-
26
- #
27
- # Restore states for items that have changed
28
- #
29
- #
30
- def restore_changes
31
- BusEvent.restoreStates(select { |item, value| item != value })
32
- end
33
-
34
- #
35
- # Detect if any item have changed states since being stored
36
- #
37
- # @return [Boolean] True if any items have changed states, false otherwise
38
- #
39
- def changed?
40
- any? { |item, value| item != value }
41
- end
42
- end
43
-
44
- #
45
- # Store states of supplied items
46
- #
47
- # @param [Array] items to store states of
48
- #
49
- # @return [StateStorage] item states
50
- #
51
- def store_states(*items)
52
- items = items.flatten.map { |item| item.is_a?(Group) ? item.group : item }
53
- states = StateStorage.new(BusEvent.storeStates(*items).to_h)
54
- if block_given?
55
- yield
56
- states.restore
57
- end
58
- states
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'core/log'
5
- require 'core/dsl/actions'
6
- require 'delegate'
7
-
8
- module OpenHAB
9
- module Core
10
- module DSL
11
- #
12
- # Support for OpenHAB Things
13
- #
14
- module Things
15
- include Logging
16
-
17
- #
18
- # Ruby Delegator for Thing
19
- #
20
- class Thing < SimpleDelegator
21
- include OpenHAB::Core::DSL::Actions
22
- include Logging
23
-
24
- def initialize(thing)
25
- super
26
- define_action_methods
27
- end
28
-
29
- private
30
-
31
- java_import 'org.openhab.core.automation.annotation.RuleAction'
32
-
33
- #
34
- # Define methods from actions mapped to this thing
35
- #
36
- #
37
- def define_action_methods
38
- actions_for_thing(uid).each do |action|
39
- methods = action.java_class.declared_instance_methods
40
- methods.select { |method| method.annotation_present?(RuleAction.java_class) }
41
- .each { |method| define_action_method(action: action, method: method.name) }
42
- end
43
- end
44
-
45
- #
46
- # Define a method, delegating to supplied action class
47
- #
48
- # @param [Object] action object to delegate method to
49
- # @param [String] method Name of method to delegate
50
- #
51
- #
52
- def define_action_method(action:, method:)
53
- logger.trace("Adding action method '#{method}' to thing '#{uid}'")
54
- define_singleton_method(method) do |*args|
55
- action.public_send(method, *args)
56
- end
57
- end
58
- end
59
-
60
- #
61
- # Wraps all Things in a delegator to underlying set and provides lookup method
62
- #
63
- class Things < SimpleDelegator
64
- java_import org.openhab.core.thing.ThingUID
65
-
66
- # Gets a specific thing by name in the format binding_id:type_id:thing_id
67
- # @return Thing specified by name or nil if name does not exist in thing registry
68
- def[](uid)
69
- thing_uid = ThingUID.new(*uid.split(':'))
70
- # rubocop: disable Style/GlobalVars
71
- thing = $things.get(thing_uid)
72
- # rubocop: enable Style/GlobalVars
73
- return unless thing
74
-
75
- logger.trace("Retrieved Thing(#{thing}) from registry for uid: #{uid}")
76
- Thing.new(thing)
77
- end
78
- end
79
-
80
- #
81
- # Get all things known to OpenHAB
82
- #
83
- # @return [Set] of all Thing objects known to openhab
84
- #
85
- def things
86
- # rubocop: disable Style/GlobalVars
87
- Things.new($things.getAll.map { |thing| Thing.new(thing) }.to_set)
88
- # rubocop: enable Style/GlobalVars
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,231 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'core/log'
5
- require 'time'
6
- require 'date'
7
-
8
- module OpenHAB
9
- module Core
10
- module DSL
11
- # Namespace for classes and modules that handle Time Of Day - Times without specific dates e.g. 6:00:00
12
- # @author Brian O'Connell
13
- # @since 0.0.1
14
- module Tod
15
- java_import java.time.LocalTime
16
- java_import java.time.format.DateTimeFormatterBuilder
17
- java_import java.util.Locale
18
-
19
- # Class that encapsulates a Time of Day, often viewed as hour-minute-second
20
- # @author Brian O'Connell
21
- # @since 0.0.1
22
- class TimeOfDay
23
- include Comparable
24
-
25
- # Immutable Java object containing Time Of Day
26
- # @return [Java.Time.LocalTime] reprsenting the Time Of Day
27
- attr_reader :local_time
28
-
29
- # Constructs a TimeOfDay representing the time when called
30
- # @since 0.0.1
31
- # @return [TimeOfDay] representing time when method was invoked
32
- def self.now
33
- now = LocalTime.now()
34
- TimeOfDay.new(h: now.hour, m: now.minute, s: now.second)
35
- end
36
-
37
- # Constructs a TimeOfDay representing midnight
38
- # @since 0.0.1
39
- # @return [TimeOfDay] representing midnight
40
- def self.midnight
41
- TimeOfDay.new(h: 0, m: 0, s: 0)
42
- end
43
-
44
- # Constructs a TimeOfDay representing noon
45
- # @since 0.0.1
46
- # @return [TimeOfDay] representing noon
47
- def self.noon
48
- TimeOfDay.new(h: 12, m: 0, s: 0)
49
- end
50
-
51
- # Constructs a TimeOfDay representing the time when called
52
- # @since 0.0.1
53
- # @param [String] string representation of TimeOfDay. Valid formats include "HH:MM:SS", "HH:MM",
54
- # "H:MM", "HH", "H", "H:MM am"
55
- # @return [TimeOfDay] object created by parsing supplied string
56
- def self.parse(string)
57
- format = /(am|pm)$/i.match?(string) ? 'h[:mm[:ss]][ ]a' : 'H[:mm[:ss]]'
58
- local_time = LocalTime.parse(string, DateTimeFormatterBuilder.new
59
- .parseCaseInsensitive.appendPattern(format).toFormatter(Locale::ENGLISH))
60
- TimeOfDay.new(h: local_time.hour, m: local_time.minute, s: local_time.second)
61
- rescue java.time.format.DateTimeParseException => e
62
- raise ArgumentError, e.message
63
- end
64
-
65
- # Constructs a TimeOfDay representing the time when called
66
- # @since 0.0.1
67
- # @option opts [Number] :h Hour of the day, defaults to 0
68
- # @option opts [Number] :m Minute of the day, defaults to 0
69
- # @option opts [Number] :s Second of the day, defaults to 0
70
- # @return [TimeOfDay] representing time when method was invoked
71
- # rubocop: disable Naming/MethodParameterName
72
- # This method has a better feel with short parameter names
73
- def initialize(h: 0, m: 0, s: 0)
74
- @local_time = LocalTime.of(h, m, s)
75
- freeze
76
- end
77
- # rubocop: enable Naming/MethodParameterName
78
-
79
- # Returns true if the time falls within a range
80
- def between?(range)
81
- between(range).cover? self
82
- end
83
-
84
- # Returns the hour of the TimeOfDay
85
- # @since 0.0.1
86
- # @return [Number] Hour of the day, from 0 to 23
87
- def hour
88
- @local_time.hour
89
- end
90
-
91
- # Returns the minute of the TimeOfDay
92
- # @since 0.0.1
93
- # @return [Number] minute of the day, from 0 to 59
94
- def minute
95
- @local_time.minute
96
- end
97
-
98
- # Returns the second of the TimeOfDay
99
- # @since 0.0.1
100
- # @return [Number] second of the day, from 0 to 59
101
- def second
102
- @local_time.second
103
- end
104
-
105
- # Returns the string representation of the TimeOfDay
106
- # @since 0.0.1
107
- # @return [String] in any of the following formats depending on time representation HH:mm, HH:mm:ss,
108
- # HH:mm:ss.SSS, HH:mm:ss.SSSSSS, HH:mm:ss.SSSSSSSSS
109
- def to_s
110
- @local_time.to_s
111
- end
112
-
113
- # Compares one TimeOfDay to another
114
- # @since 0.0.1
115
- # @return [Number, nil] -1,0,1 if other TimeOfDay is less than, equal to, or greater than this TimeOfDay
116
- # or nil if an object other than TimeOfDay is provided
117
- def <=>(other)
118
- case other
119
- when TimeOfDay
120
- @local_time.compare_to(other.local_time)
121
- when String
122
- @local_time.compare_to(TimeOfDay.parse(other).local_time)
123
- else
124
- -(other <=> self)
125
- end
126
- end
127
- end
128
-
129
- # Modules that refines the Ruby Range object cover? and include? methods to support TimeOfDay ranges
130
- class TimeOfDayRangeElement < Numeric
131
- include Comparable
132
- include Logging
133
-
134
- NUM_SECONDS_IN_DAY = (60 * 60 * 24)
135
-
136
- attr_reader :sod
137
-
138
- def initialize(sod:, range_begin:)
139
- @sod = sod
140
- @range_begin = range_begin
141
-
142
- super()
143
- end
144
-
145
- # Returns the current second of day advanced by 1 second
146
- def succ
147
- TimeOfDayRangeElement.new(sod: @sod + 1, range_begin: @range_begin)
148
- end
149
-
150
- # Compares one TimeOfDayRangeElement to another
151
- # @since 2.4.0
152
- # @return [Number, nil] -1,0,1 if other is less than, equal to, or greater than this TimeOfDay
153
- def <=>(other)
154
- other_second_of_day = to_second_of_day(other)
155
- logger.trace do
156
- "SOD(#{sod}) "\
157
- "other SOD(#{other_second_of_day}) "\
158
- "Other Class (#{other.class}) "\
159
- "Result (#{sod <=> other_second_of_day})"
160
- end
161
- sod <=> other_second_of_day
162
- end
163
-
164
- private
165
-
166
- #
167
- # Convert object to the seconds of a day they reprsent
168
- #
169
- # @param [Object] object TimeofDay,String,Time, or TimeOfDayRangeElement to convert
170
- #
171
- # @return [Integer] seconds of day represented by supplied object
172
- #
173
- def to_second_of_day(object)
174
- case object
175
- when TimeOfDay then adjust_second_of_day(object.local_time.to_second_of_day)
176
- when String then adjust_second_of_day(TimeOfDay.parse(object).local_time.to_second_of_day)
177
- when Time then adjust_second_of_day(TimeOfDay.new(h: object.hour, m: object.min,
178
- s: object.sec).local_time.to_second_of_day)
179
- when TimeOfDayRangeElement then object.sod
180
- else raise ArgumentError, 'Supplied argument cannot be converted into Time Of Day Object'
181
- end
182
- end
183
-
184
- def adjust_second_of_day(second_of_day)
185
- second_of_day += NUM_SECONDS_IN_DAY if second_of_day < @range_begin
186
- second_of_day
187
- end
188
- end
189
-
190
- # Creates a range that can be compared against time of day objects or strings
191
- # to see if they are within the range
192
- # @since 2.4.0
193
- # @return Range object representing a TimeOfDay Range
194
- module_function
195
-
196
- def between(range)
197
- raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
198
-
199
- start = to_time_of_day(range.begin)
200
- ending = to_time_of_day(range.end)
201
-
202
- start_sod = start.local_time.to_second_of_day
203
- ending_sod = ending.local_time.to_second_of_day
204
- ending_sod += TimeOfDayRangeElement::NUM_SECONDS_IN_DAY if ending_sod < start_sod
205
-
206
- start_range = TimeOfDayRangeElement.new(sod: start_sod, range_begin: start_sod)
207
- ending_range = TimeOfDayRangeElement.new(sod: ending_sod, range_begin: start_sod)
208
- range.exclude_end? ? (start_range...ending_range) : (start_range..ending_range)
209
- end
210
-
211
- #
212
- # Convert object to TimeOfDay object
213
- #
214
- # @param [Object] object TimeOfDay or String to be converted
215
- #
216
- # @return [TimeOfDay] TimeOfDay created from supplied object
217
- #
218
- private_class_method def to_time_of_day(object)
219
- case object
220
- when String then TimeOfDay.parse(object)
221
- else object
222
- end
223
- end
224
-
225
- MIDNIGHT = TimeOfDay.midnight
226
- NOON = TimeOfDay.noon
227
- ALL_DAY = between(TimeOfDay.new(h: 0, m: 0, s: 0)..TimeOfDay.new(h: 23, m: 59, s: 59))
228
- end
229
- end
230
- end
231
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'delegate'
5
- require 'forwardable'
6
-
7
- module OpenHAB
8
- module Core
9
- module DSL
10
- #
11
- # Provides access to and ruby wrappers around OpenHAB timers
12
- #
13
- module Timers
14
- java_import org.openhab.core.model.script.actions.ScriptExecution
15
- java_import java.time.ZonedDateTime
16
-
17
- # Ruby wrapper for OpenHAB Timer
18
- # This class implements delegator to delegate methods to the OpenHAB timer
19
- #
20
- # @author Brian O'Connell
21
- # @since 2.0.0
22
- class Timer < SimpleDelegator
23
- extend Forwardable
24
-
25
- def_delegator :@timer, :is_active, :active?
26
- def_delegator :@timer, :is_running, :running?
27
- def_delegator :@timer, :has_terminated, :terminated?
28
-
29
- #
30
- # Create a new Timer Object
31
- #
32
- # @param [Duration] duration Duration until timer should fire
33
- # @param [Block] block Block to execute when timer fires
34
- #
35
- def initialize(duration:, &block)
36
- @duration = duration
37
-
38
- # A semaphore is used to prevent a race condition in which calling the block from the timer thread
39
- # occurs before the @timer variable can be set resulting in @timer being nil
40
- semaphore = Mutex.new
41
-
42
- timer_block = proc { semaphore.synchronize { block.call(self) } }
43
-
44
- semaphore.synchronize do
45
- @timer = ScriptExecution.createTimer(
46
- ZonedDateTime.now.plus(@duration), timer_block
47
- )
48
- super(@timer)
49
- end
50
- end
51
-
52
- #
53
- # Reschedule timer
54
- #
55
- # @param [Duration] duration
56
- #
57
- # @return [<Type>] <description>
58
- #
59
- def reschedule(duration = nil)
60
- duration ||= @duration
61
- @timer.reschedule(ZonedDateTime.now.plus(duration))
62
- end
63
- end
64
-
65
- #
66
- # Execute the supplied block after the specified duration
67
- #
68
- # @param [Duration] duration after which to execute the block
69
- # @param [Block] block to execute, block is passed a Timer object
70
- #
71
- # @return [Timer] Timer object
72
- #
73
- def after(duration, &block)
74
- Timer.new(duration: duration, &block)
75
- end
76
- end
77
- end
78
- end
79
- end