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
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module MonkeyPatch
8
+ #
9
+ # Patches OpenHAB types
10
+ #
11
+ module Types
12
+ java_import Java::OrgOpenhabCoreLibraryTypes::OpenClosedType
13
+
14
+ #
15
+ # Monkey patch for DSL use
16
+ #
17
+ class OpenClosedType
18
+ java_import Java::OrgOpenhabCoreLibraryItems::ContactItem
19
+
20
+ #
21
+ # Check if the supplied object is case equals to self
22
+ #
23
+ # @param [Object] other object to compare
24
+ #
25
+ # @return [Boolean] True if the other object is a ContactItem and has the same state
26
+ #
27
+ def ===(other)
28
+ super unless other.is_a? ContactItem
29
+
30
+ self == other.state
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ module OpenHAB
5
+ module DSL
6
+ module MonkeyPatch
7
+ #
8
+ # Patches OpenHAB types
9
+ #
10
+ module Types
11
+ java_import Java::OrgOpenhabCoreLibraryTypes::PercentType
12
+
13
+ #
14
+ # MonkeyPatching PercentType
15
+ #
16
+ class PercentType
17
+ #
18
+ # Need to override and point to super because default JRuby implementation doesn't point to == of parent class
19
+ #
20
+ # @param [Object] other object to check equality for
21
+ # @return [Boolean] True if other equals self, false otherwise
22
+ #
23
+ # rubocop:disable Lint/UselessMethodDefinition
24
+ def ==(other)
25
+ super
26
+ end
27
+ # rubocop:enable Lint/UselessMethodDefinition
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module MonkeyPatch
8
+ #
9
+ # Patches OpenHAB types
10
+ #
11
+ module Types
12
+ java_import Java::OrgOpenhabCoreLibraryTypes::QuantityType
13
+
14
+ #
15
+ # MonkeyPatching QuantityType
16
+ #
17
+ class QuantityType
18
+ #
19
+ # Compare QuantityType to supplied object
20
+ #
21
+ # @param [Object] other object to compare to
22
+ #
23
+ # @return [Integer] -1,0,1 or nil depending on value supplied,
24
+ # nil comparison to supplied object is not possible.
25
+ #
26
+ def <=>(other)
27
+ logger.trace("#{self.class} #{self} <=> #{other} (#{other.class})")
28
+ case other
29
+ when Java::OrgOpenhabCoreTypes::UnDefType then 1
30
+ when String then self <=> Quantity.new(other)
31
+ when OpenHAB::DSL::Types::Quantity then self <=> other.quantity
32
+ else
33
+ other = other.state if other.respond_to? :state
34
+ compare_to(other)
35
+ end
36
+ end
37
+
38
+ #
39
+ # Coerce objects into a QuantityType
40
+ #
41
+ # @param [Object] other object to coerce to a QuantityType if possible
42
+ #
43
+ # @return [Object] Numeric when applicable
44
+ #
45
+ def coerce(other)
46
+ logger.trace("Coercing #{self} as a request from #{other.class}")
47
+ case other
48
+ when String
49
+ [Quantity.new(other), self]
50
+ else
51
+ [other, self]
52
+ end
53
+ end
54
+
55
+ #
56
+ # Compare self to other using the spaceship operator
57
+ #
58
+ # @param [Object] other object to compare to
59
+ #
60
+ # @return [Boolean] True if equals
61
+ #
62
+ def ==(other)
63
+ (self <=> other).zero?
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Monkey patch types
4
+ require 'openhab/dsl/monkey_patch/types/open_closed_type'
5
+ require 'openhab/dsl/monkey_patch/types/on_off_type'
6
+ require 'openhab/dsl/monkey_patch/types/decimal_type'
7
+ require 'openhab/dsl/monkey_patch/types/percent_type'
8
+ require 'openhab/dsl/monkey_patch/types/quantity_type'
9
+ require 'openhab/dsl/monkey_patch/types/up_down_type'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ module OpenHAB
5
+ module DSL
6
+ module MonkeyPatch
7
+ #
8
+ # Patches OpenHAB types
9
+ #
10
+ module Types
11
+ java_import Java::OrgOpenhabCoreLibraryTypes::UpDownType
12
+
13
+ #
14
+ # MonkeyPatching UpDownType
15
+ #
16
+ class UpDownType
17
+ #
18
+ # Check if the supplied object is case equals to self
19
+ #
20
+ # @param [Object] other object to compare
21
+ #
22
+ # @return [Boolean] True if the other object is a RollershutterItem and has the same state
23
+ #
24
+ def ===(other)
25
+ super unless other.is_a? OpenHAB::DSL::Items::RollershutterItem
26
+
27
+ equals(other.state.as(UpDownType))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ #
6
+ # Provides support for interacting with OpenHAB Persistence service
7
+ #
8
+ module Persistence
9
+ #
10
+ # Sets a thread local variable to set the default persistence service
11
+ # for method calls inside the block
12
+ #
13
+ # @param [Object] service service either as a String or a Symbol
14
+ # @yield [] Block executed in context of the supplied persistence service
15
+ #
16
+ #
17
+ def persistence(service)
18
+ Thread.current.thread_variable_set(:persistence_service, service)
19
+ yield
20
+ ensure
21
+ Thread.current.thread_variable_set(:persistence_service, nil)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,342 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ #
8
+ # Creates and manages OpenHAB Rules
9
+ #
10
+ module Rules
11
+ #
12
+ # JRuby extension to OpenHAB Rule
13
+ #
14
+ # rubocop: disable Metrics/ClassLength
15
+ # Disabled because this class has a single responsibility, there does not appear a logical
16
+ # way of breaking it up into multiple classes
17
+ class AutomationRule < Java::OrgOpenhabCoreAutomationModuleScriptRulesupportSharedSimple::SimpleRule
18
+ include OpenHAB::Log
19
+ include OpenHAB::DSL::TimeOfDay
20
+ java_import java.time.ZonedDateTime
21
+
22
+ #
23
+ # Create a new Rule
24
+ #
25
+ # @param [Config] config Rule configuration
26
+ #
27
+ def initialize(config:)
28
+ super()
29
+ set_name(config.name)
30
+ set_description(config.description)
31
+ set_triggers(config.triggers)
32
+ @run_queue = config.run
33
+ @guard = config.guard
34
+ between = config.between&.yield_self { between(config.between) }
35
+ @between = between || OpenHAB::DSL::TimeOfDay::ALL_DAY
36
+ # Convert between to correct range or nil if not set
37
+ @trigger_delays = config.trigger_delays
38
+ end
39
+
40
+ #
41
+ # Execute the rule
42
+ #
43
+ # @param [Map] mod map provided by OpenHAB rules engine
44
+ # @param [Map] inputs map provided by OpenHAB rules engine containing event and other information
45
+ #
46
+ #
47
+ def execute(mod = nil, inputs = nil)
48
+ logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs&.pretty_inspect}" }
49
+ logger.trace { "Event details #{inputs['event'].pretty_inspect}" } if inputs&.key?('event')
50
+ if trigger_delay inputs
51
+ trigger_delay = trigger_delay(inputs)
52
+ process_trigger_delay(trigger_delay, mod, inputs)
53
+ else
54
+ # If guards are satisfied execute the run type blocks
55
+ # If they are not satisfied, execute the Othewise blocks
56
+ queue = create_queue(inputs)
57
+ process_queue(queue, mod, inputs)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ #
64
+ # Create the run queue based on guards
65
+ #
66
+ # @param [Map] inputs rule inputs
67
+ #
68
+ # @return [Queue] <description>
69
+ #
70
+ def create_queue(inputs)
71
+ case check_guards(event: inputs&.dig('event'))
72
+ when true
73
+ @run_queue.dup
74
+ when false
75
+ @run_queue.dup.grep(RuleConfig::Otherwise)
76
+ end
77
+ end
78
+
79
+ #
80
+ # Returns trigger delay from inputs if it exists
81
+ #
82
+ # @param [Map] inputs map from OpenHAB containing UID
83
+ #
84
+ # @return [Array] Array of trigger delays that match rule UID
85
+ #
86
+ def trigger_delay(inputs)
87
+ # Parse this to get the trigger UID:
88
+ # ["72698819-83cb-498a-8e61-5aab8b812623.event", "oldState", "module", \
89
+ # "72698819-83cb-498a-8e61-5aab8b812623.oldState", "event", "newState",\
90
+ # "72698819-83cb-498a-8e61-5aab8b812623.newState"]
91
+ @trigger_delays[inputs&.keys&.grep(/\.event$/)&.first&.chomp('.event')]
92
+ end
93
+
94
+ #
95
+ # Check if trigger guards prevent rule execution
96
+ #
97
+ # @param [Delay] trigger_delay rules delaying trigger because of
98
+ # @param [Map] inputs OpenHAB map object describing rule trigger
99
+ #
100
+ # @return [Boolean] True if the rule should execute, false if trigger guard prevents execution
101
+ #
102
+ def check_trigger_guards(trigger_delay, inputs)
103
+ old_state = inputs['oldState']
104
+ new_state = inputs['newState']
105
+ if check_from(trigger_delay, old_state)
106
+ return true if check_to(trigger_delay, new_state)
107
+
108
+ logger.trace("Skipped execution of rule '#{name}' because to state #{new_state}"\
109
+ " does not equal specified state(#{trigger_delay.to})")
110
+ else
111
+ logger.trace("Skipped execution of rule '#{name}' because old state #{old_state}"\
112
+ " does not equal specified state(#{trigger_delay.from})")
113
+ end
114
+ end
115
+
116
+ #
117
+ # Check the from state against the trigger delay
118
+ #
119
+ # @param [TriggerDelay] trigger_delay Information about the trigger delay
120
+ # @param [Item State] state from state to check
121
+ #
122
+ # @return [Boolean] true if no from state is defined or defined state equals supplied state
123
+ #
124
+ def check_from(trigger_delay, state)
125
+ trigger_delay.from.nil? || trigger_delay.from == state
126
+ end
127
+
128
+ #
129
+ # Check the to state against the trigger delay
130
+ #
131
+ # @param [TriggerDelay] trigger_delay Information about the trigger delay
132
+ # @param [Item State] state to-state to check
133
+ #
134
+ # @return [Boolean] true if no to state is defined or defined state equals supplied state
135
+ #
136
+ def check_to(trigger_delay, state)
137
+ trigger_delay.to.nil? || trigger_delay.to == state
138
+ end
139
+
140
+ #
141
+ # Process any matching trigger delays
142
+ #
143
+ # @param [Map] mod OpenHAB map object describing rule trigger
144
+ # @param [Map] inputs OpenHAB map object describing rule trigger
145
+ #
146
+ #
147
+ def process_trigger_delay(trigger_delay, mod, inputs)
148
+ if check_trigger_guards(trigger_delay, inputs)
149
+ logger.trace("Trigger Guards Matched for #{trigger_delay}, delaying rule execution")
150
+ # Add timer and attach timer to delay object, and also state being tracked to so timer can be cancelled if
151
+ # state changes
152
+ # Also another timer should not be created if changed to same value again but instead rescheduled
153
+ if trigger_delay.timer_active?
154
+ process_active_timer(inputs, mod, trigger_delay)
155
+ else
156
+ create_trigger_delay_timer(inputs, mod, trigger_delay)
157
+ end
158
+ else
159
+ logger.trace("Trigger Guards did not match for #{trigger_delay}, ignoring trigger.")
160
+ end
161
+ end
162
+
163
+ #
164
+ # Creatas a timer for trigger delays
165
+ #
166
+ # @param [Hash] inputs rule trigger inputs
167
+ # @param [Hash] mod rule trigger mods
168
+ # @param [TriggerDelay] trigger_delay specifications
169
+ #
170
+ #
171
+ def create_trigger_delay_timer(inputs, mod, trigger_delay)
172
+ logger.trace("Creating timer for rule #{name} and trigger delay #{trigger_delay}")
173
+ trigger_delay.timer = after(trigger_delay.duration) do
174
+ logger.trace("Delay Complete for #{trigger_delay}, executing rule")
175
+ trigger_delay.timer = nil
176
+ process_queue(@run_queue.dup, mod, inputs)
177
+ end
178
+ trigger_delay.tracking_to = inputs['newState']
179
+ end
180
+
181
+ #
182
+ # Process an active trigger timer
183
+ #
184
+ # @param [Hash] inputs rule trigger inputs
185
+ # @param [Hash] mod rule trigger mods
186
+ # @param [TriggerDelay] trigger_delay specifications
187
+ #
188
+ #
189
+ def process_active_timer(inputs, mod, trigger_delay)
190
+ state = inputs['newState']
191
+ if state == trigger_delay.tracking_to
192
+ logger.trace("Item changed to #{state} for #{trigger_delay}, rescheduling timer.")
193
+ trigger_delay.timer.reschedule(ZonedDateTime.now.plus(trigger_delay.duration))
194
+ else
195
+ logger.trace("Item changed to #{state} for #{trigger_delay}, cancelling timer.")
196
+ trigger_delay.timer.cancel
197
+ # Reprocess trigger delay after cancelling to track new state (if guards matched, etc)
198
+ process_trigger_delay(trigger_delay, mod, inputs)
199
+ end
200
+ end
201
+
202
+ #
203
+ # Check if any guards prevent execution
204
+ #
205
+ # @param [Map] event OpenHAB rule trigger event
206
+ #
207
+ # @return [Boolean] True if guards says rule should execute, false otherwise
208
+ #
209
+ def check_guards(event:)
210
+ if @guard.should_run? event
211
+ now = TimeOfDay::TimeOfDay.now
212
+ return true if @between.cover? now
213
+
214
+ logger.trace("Skipped execution of rule '#{name}' because the current time #{now} "\
215
+ "is not between #{@between.begin} and #{@between.end}")
216
+ else
217
+ logger.trace("Skipped execution of rule '#{name}' because of guard #{@guard}")
218
+ end
219
+ false
220
+ end
221
+
222
+ #
223
+ # Patch event to decorate event.item with our item wrapper
224
+ #
225
+ # @param [OpenHAB Event] event patch
226
+ #
227
+ def decorate_event_item(event)
228
+ return if event.nil?
229
+
230
+ class << event
231
+ def item
232
+ OpenHAB::Core::EntityLookup.lookup_item(item_name)
233
+ end
234
+ end
235
+ end
236
+
237
+ #
238
+ # Process the run queue
239
+ #
240
+ # @param [Array] run_queue array of procs of various types to execute
241
+ # @param [Map] mod OpenHAB map object describing rule trigger
242
+ # @param [Map] inputs OpenHAB map object describing rule trigge
243
+ #
244
+ #
245
+ def process_queue(run_queue, mod, inputs)
246
+ event = inputs&.dig('event')
247
+
248
+ while (task = run_queue.shift)
249
+ case task
250
+ when RuleConfig::Run then process_run_task(event, task)
251
+ when RuleConfig::Trigger then process_trigger_task(event, task)
252
+ when RuleConfig::Delay then process_delay_task(inputs, mod, run_queue, task)
253
+ when RuleConfig::Otherwise then process_otherwise_task(event, task)
254
+ end
255
+ end
256
+ end
257
+
258
+ #
259
+ # Process an otherwise block
260
+ #
261
+ # @param [OpenHab Event] event that triggered the rule
262
+ # @param [Task] task task containing otherwise block to execute
263
+ #
264
+ #
265
+ def process_otherwise_task(event, task)
266
+ decorate_event_item(event)
267
+ logger.trace { "Executing rule '#{name}' otherwise block with event(#{event})" }
268
+ task.block.call(event)
269
+ end
270
+
271
+ #
272
+ # Process delay task
273
+ #
274
+ # @param [Map] inputs Rule trigger inputs
275
+ # @param [Map] mod Rule modes
276
+ # @param [Queue] run_queue Queue of tasks for this rule
277
+ # @param [Delay] task to process
278
+ #
279
+ #
280
+ def process_delay_task(inputs, mod, run_queue, task)
281
+ remaining_queue = run_queue.slice!(0, run_queue.length)
282
+ after(task.duration) { process_queue(remaining_queue, mod, inputs) }
283
+ end
284
+
285
+ #
286
+ # Process a task that is caused by a group item
287
+ #
288
+ # @param [Map] event Rule event map
289
+ # @param [Trigger] task to execute
290
+ #
291
+ #
292
+ def process_trigger_task(event, task)
293
+ triggering_item = OpenHAB::Core::EntityLookup.lookup_item(event&.itemName)
294
+ logger.trace { "Executing rule '#{name}' trigger block with item (#{triggering_item})" }
295
+ task.block.call(triggering_item) if triggering_item
296
+ end
297
+
298
+ #
299
+ # Process a run task
300
+ #
301
+ # @param [OpenHab Event] event information
302
+ # @param [Run] task to execute
303
+ #
304
+ #
305
+ def process_run_task(event, task)
306
+ decorate_event_item(event)
307
+ logger.trace { "Executing rule '#{name}' run block with event(#{event})" }
308
+ task.block.call(event)
309
+ end
310
+
311
+ #
312
+ # Create a new hash in which all elements are converted to strings
313
+ #
314
+ # @param [Map] hash in which all elements should be converted to strings
315
+ #
316
+ # @return [Map] new map with values converted to strings
317
+ #
318
+ def inspect_hash(hash)
319
+ hash.each_with_object({}) do |(key, value), new_hash|
320
+ new_hash[inspect_item(key)] = inspect_item(value)
321
+ end
322
+ end
323
+
324
+ #
325
+ # Convert an individual element into a string based on if it a Ruby or Java object
326
+ #
327
+ # @param [Object] item to convert to a string
328
+ #
329
+ # @return [String] representation of item
330
+ #
331
+ def inspect_item(item)
332
+ if item.respond_to? :to_string
333
+ item.to_string
334
+ elsif item.respond_to? :to_str
335
+ item.to_str
336
+ end
337
+ end
338
+ end
339
+ end
340
+ end
341
+ end
342
+ # rubocop: enable Metrics/ClassLength