openhab-scripting 2.14.1 → 2.16.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +3 -0
  3. data/lib/openhab/core/dsl.rb +4 -0
  4. data/lib/openhab/core/dsl/actions.rb +1 -1
  5. data/lib/openhab/core/dsl/entities.rb +41 -4
  6. data/lib/openhab/core/dsl/gems.rb +1 -1
  7. data/lib/openhab/core/dsl/group.rb +3 -1
  8. data/lib/openhab/core/dsl/items/items.rb +3 -1
  9. data/lib/openhab/core/dsl/items/number_item.rb +158 -52
  10. data/lib/openhab/core/dsl/items/string_item.rb +23 -3
  11. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +20 -5
  12. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +2 -0
  13. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +66 -42
  14. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +72 -0
  15. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +2 -1
  16. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +2 -1
  17. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +1 -0
  18. data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +43 -0
  19. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +41 -5
  20. data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +58 -0
  21. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +1 -0
  22. data/lib/openhab/core/dsl/persistence.rb +27 -0
  23. data/lib/openhab/core/dsl/property.rb +15 -4
  24. data/lib/openhab/core/dsl/rule/automation_rule.rb +348 -0
  25. data/lib/openhab/core/dsl/rule/guard.rb +43 -6
  26. data/lib/openhab/core/dsl/rule/rule.rb +80 -367
  27. data/lib/openhab/core/dsl/rule/rule_config.rb +153 -0
  28. data/lib/openhab/core/dsl/rule/triggers/changed.rb +145 -0
  29. data/lib/openhab/core/dsl/rule/{channel.rb → triggers/channel.rb} +22 -8
  30. data/lib/openhab/core/dsl/rule/triggers/command.rb +106 -0
  31. data/lib/openhab/core/dsl/rule/{cron.rb → triggers/cron.rb} +36 -14
  32. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +126 -0
  33. data/lib/openhab/core/dsl/rule/triggers/updated.rb +100 -0
  34. data/lib/openhab/core/dsl/time_of_day.rb +53 -25
  35. data/lib/openhab/core/dsl/timers.rb +2 -6
  36. data/lib/openhab/core/dsl/types/quantity.rb +106 -69
  37. data/lib/openhab/core/log.rb +3 -8
  38. data/lib/openhab/core/startup_delay.rb +1 -0
  39. data/lib/openhab/osgi.rb +7 -0
  40. data/lib/openhab/version.rb +1 -1
  41. metadata +14 -6
  42. data/lib/openhab/core/dsl/rule/item.rb +0 -203
  43. data/lib/openhab/core/dsl/rule/triggers.rb +0 -77
@@ -39,15 +39,11 @@ module OpenHAB
39
39
  # occurs before the @timer variable can be set resulting in @timer being nil
40
40
  semaphore = Mutex.new
41
41
 
42
- @block = proc do
43
- semaphore.synchronize do
44
- block.call(self)
45
- end
46
- end
42
+ timer_block = proc { semaphore.synchronize { block.call(self) } }
47
43
 
48
44
  semaphore.synchronize do
49
45
  @timer = ScriptExecution.createTimer(
50
- ZonedDateTime.now.plus(@duration), @block
46
+ ZonedDateTime.now.plus(@duration), timer_block
51
47
  )
52
48
  super(@timer)
53
49
  end
@@ -13,6 +13,9 @@ module OpenHAB
13
13
  #
14
14
  # Ruby implementation for OpenHAB quantities
15
15
  #
16
+ # rubocop: disable Metrics/ClassLength
17
+ # Disabled because this class has a single responsibility, there does not appear a logical
18
+ # way of breaking it up into multiple classes
16
19
  class Quantity < Numeric
17
20
  extend Forwardable
18
21
  include Logging
@@ -23,6 +26,7 @@ module OpenHAB
23
26
  java_import 'tec.uom.se.format.SimpleUnitFormat'
24
27
  java_import 'tec.uom.se.AbstractUnit'
25
28
 
29
+ # @return [Hash] Mapping of operation symbols to BigDecimal methods
26
30
  OPERATIONS = {
27
31
  '+' => 'add',
28
32
  '-' => 'subtract',
@@ -37,18 +41,15 @@ module OpenHAB
37
41
  #
38
42
  # Create a new Quantity
39
43
  #
40
- # @param [Java::org::openhab::core::library::types::QuantityType] quantity OpenHAB quantity to delegate to
44
+ # @param [object] quantity String,QuantityType or Numeric to be this quantity
41
45
  #
46
+ # Cop disabled, case statement is compact and idiomatic
42
47
  def initialize(quantity)
43
48
  @quantity = case quantity
44
- when String
45
- QuantityType.new(quantity)
46
- when QuantityType
47
- quantity
48
- when Numeric
49
- QuantityType.new(quantity.to_d.to_java, AbstractUnit::ONE)
50
- else
51
- raise "Unexpected type #{quantity.class} provided to Quantity initializer"
49
+ when String then QuantityType.new(quantity)
50
+ when QuantityType then quantity
51
+ when NumberItem, Numeric then QuantityType.new(quantity.to_d.to_java, AbstractUnit::ONE)
52
+ else raise ArgumentError, "Unexpected type #{quantity.class} provided to Quantity initializer"
52
53
  end
53
54
  super()
54
55
  end
@@ -76,20 +77,8 @@ module OpenHAB
76
77
  #
77
78
  def <=>(other)
78
79
  logger.trace("Comparing #{self} to #{other}")
79
- case other
80
- when Quantity
81
- logger.trace("Comparing Quantity #{self} to Quantity #{other}")
82
- convert_unit(quantity).compare_to(convert_unit(other.quantity))
83
- when QuantityType
84
- other = convert_unit(other)
85
- quantity.compare_to(other)
86
- when String
87
- other = QuantityType.new(other)
88
- other = convert_unit(other)
89
- quantity.compare_to(other)
90
- when Numeric
91
- quantity.compare_to(QuantityType.new(other, unit)) if unit
92
- end
80
+ my_qt, other_qt = unitize(*to_qt(coerce(other).reverse))
81
+ my_qt.compare_to(other_qt)
93
82
  end
94
83
 
95
84
  #
@@ -100,14 +89,12 @@ module OpenHAB
100
89
  # @return [Array] of self and other object as Quantity types, nil if object cannot be coerced
101
90
  #
102
91
  def coerce(other)
103
- logger.trace("Coercing #{self} as a request from #{other.class}")
92
+ logger.trace("Coercing #{self} as a request from #{other.class}")
104
93
  case other
105
- when Quantity
106
- [other.quantity, quantity]
107
- when QuantityType
108
- [other, quantity]
109
- when Numeric
110
- [Quantity.new(other), self]
94
+ when Quantity then [other.quantity, quantity]
95
+ when QuantityType then [other, quantity]
96
+ when NumberItem then [other.to_qt.quantity, quantity]
97
+ when Numeric, String then [Quantity.new(other), self]
111
98
  end
112
99
  end
113
100
 
@@ -121,6 +108,7 @@ module OpenHAB
121
108
  # @return [Object] result of delegation
122
109
  #
123
110
  def method_missing(meth, *args, &block)
111
+ logger.trace("Method missing, performing dynamic lookup for: #{meth}")
124
112
  if quantity.respond_to?(meth)
125
113
  quantity.__send__(meth, *args, &block)
126
114
  elsif ::Kernel.method_defined?(meth) || ::Kernel.private_method_defined?(meth)
@@ -130,6 +118,20 @@ module OpenHAB
130
118
  end
131
119
  end
132
120
 
121
+ #
122
+ # Checks if this method responds to the missing method
123
+ #
124
+ # @param [String] method_name Name of the method to check
125
+ # @param [Boolean] _include_private boolean if private methods should be checked
126
+ #
127
+ # @return [Boolean] true if this object will respond to the supplied method, false otherwise
128
+ #
129
+ def respond_to_missing?(method_name, _include_private = false)
130
+ quantity.respond_to?(method_name) ||
131
+ ::Kernel.method_defined?(method_name) ||
132
+ ::Kernel.private_method_defined?(method_name)
133
+ end
134
+
133
135
  #
134
136
  # Negate the quantity
135
137
  #
@@ -141,22 +143,10 @@ module OpenHAB
141
143
 
142
144
  OPERATIONS.each do |operation, method|
143
145
  define_method(operation) do |other|
144
- logger.trace("Executing math operation '#{operation}' on quantity #{inspect} with other type #{other.class} and value #{other.inspect}")
145
- a, b = case other
146
- when Quantity
147
- [quantity, other.quantity]
148
- when String
149
- [quantity, QuantityType.new(other)]
150
- when NumberItem
151
- a, b = other.coerce(self)
152
- logger.trace("Number Item coerced result a(#{a.class})='#{a}' b(#{b.class})='#{b}'")
153
- [a.quantity, b.quantity]
154
- when Numeric
155
- [quantity, QuantityType.new(other.to_d.to_java, AbstractUnit::ONE)]
156
- else
157
- raise TypeError,
158
- "Operation '#{operation}' cannot be performed between #{self} and #{other.class}"
159
- end
146
+ logger.trace("Executing math operation '#{operation}' on quantity #{inspect} "\
147
+ "with other type #{other.class} and value #{other.inspect}")
148
+
149
+ a, b = to_qt(coerce(other).reverse)
160
150
  logger.trace("Coerced a='#{a}' with b='#{b}'")
161
151
  a, b = unitize(a, b, operation)
162
152
  logger.trace("Unitized a='#{a}' b='#{b}'")
@@ -180,10 +170,22 @@ module OpenHAB
180
170
 
181
171
  private
182
172
 
173
+ # @return [Array] Array of strings for operations for which the operands will not be unitized
183
174
  DIMENSIONLESS_NON_UNITIZED_OPERATIONS = %w[* /].freeze
184
175
 
185
176
  # Dimensionless numbers should only be unitzed for addition and subtraction
186
177
 
178
+ #
179
+ # Convert one or more Quantity obects to the underlying quantitytypes
180
+ #
181
+ # @param [Array] quanities Array of either Quantity or QuantityType objects
182
+ #
183
+ # @return [Array] Array of QuantityType objects
184
+ #
185
+ def to_qt(*quanities)
186
+ [quanities].flatten.compact.map { |item| item.is_a?(Quantity) ? item.quantity : item }
187
+ end
188
+
187
189
  #
188
190
  # Checks if an item should be unitized
189
191
  #
@@ -193,11 +195,7 @@ module OpenHAB
193
195
  # @return [Boolean] True if the quantity should be unitzed based on the unit and operation, false otherwise
194
196
  #
195
197
  def unitize?(quantity, operation)
196
- if quantity.unit == AbstractUnit::ONE && DIMENSIONLESS_NON_UNITIZED_OPERATIONS.include?(operation)
197
- false
198
- else
199
- true
200
- end
198
+ !(quantity.unit == AbstractUnit::ONE && DIMENSIONLESS_NON_UNITIZED_OPERATIONS.include?(operation))
201
199
  end
202
200
 
203
201
  #
@@ -208,36 +206,65 @@ module OpenHAB
208
206
  # @return [Quantity] Quantity coverted to unit set by unit block
209
207
  #
210
208
  def convert_unit(quantity)
211
- if unit
212
- case quantity.unit
213
- when AbstractUnit::ONE
214
- logger.trace("Converting dimensionless #{quantity} to #{unit}")
215
- QuantityType.new(quantity.to_big_decimal, unit)
216
- when unit
217
- quantity
218
- else
219
- logger.trace("Converting dimensioned item #{inspect} to #{unit}")
220
- converted = quantity.to_unit(unit)
221
- raise "Conversion from #{quantity.unit} to #{unit} failed" if converted.nil?
222
-
223
- converted
224
- end
225
- else
209
+ return quantity unless unit?
210
+
211
+ case quantity.unit
212
+ when unit
226
213
  quantity
214
+ when AbstractUnit::ONE
215
+ convert_unit_from_dimensionless(quantity, unit)
216
+ else
217
+ convert_unit_from_dimensioned(quantity, unit)
227
218
  end
228
219
  end
229
220
 
221
+ #
222
+ # Converts a dimensioned quantity to a specific unit
223
+ #
224
+ # @param [Quantity] quantity to convert
225
+ # @param [Unit] unit to convert to
226
+ #
227
+ # @return [Java::org::openhab::core::library::types::QuantityType] converted quantity
228
+ #
229
+ def convert_unit_from_dimensioned(quantity, unit)
230
+ logger.trace("Converting dimensioned item #{inspect} to #{unit}")
231
+ quantity.to_unit(unit).tap do |converted|
232
+ raise "Conversion from #{quantity.unit} to #{unit} failed" unless converted
233
+ end
234
+ end
235
+
236
+ #
237
+ # Converts a dimensionless quantity to a unit
238
+ #
239
+ # @param [Quantity] quantity to convert
240
+ # @param [Unit] unit to convert to
241
+ #
242
+ # @return [Java::org::openhab::core::library::types::QuantityType] converted quantity
243
+ #
244
+ def convert_unit_from_dimensionless(quantity, unit)
245
+ logger.trace("Converting dimensionless #{quantity} to #{unit}")
246
+ QuantityType.new(quantity.to_big_decimal, unit)
247
+ end
248
+
230
249
  #
231
250
  # Convert quantities to appropriate units
232
251
  #
233
252
  # @param [Quantity] quantity_a Quantity on left side of operation
234
253
  # @param [Quantity] quantity_b Quantity on right side of operation
235
254
  # @param [String] operation Math operation
255
+ # @yield [quantity_a, quantity_b] yields unitized versions of supplied quantities
236
256
  #
237
- # @return [Array] of quantites in correct units for the supplied operation and set unit
257
+ # @return [Array, Object] of quantites in correct units for the supplied operation and the unit
258
+ # or the result of the block if a block is given
238
259
  #
239
- def unitize(quantity_a, quantity_b, operation)
240
- [quantity_a, quantity_b].map { |qt| unitize?(qt, operation) ? convert_unit(qt) : qt }
260
+ def unitize(quantity_a, quantity_b, operation = nil)
261
+ logger.trace("Unitizing (#{quantity_a}) and (#{quantity_b})")
262
+ quantity_a, quantity_b = [quantity_a, quantity_b].map do |qt|
263
+ unitize?(qt, operation) ? convert_unit(qt) : qt
264
+ end
265
+ return yield quantity_a, quantity_b if block_given?
266
+
267
+ [quantity_a, quantity_b]
241
268
  end
242
269
 
243
270
  #
@@ -248,8 +275,18 @@ module OpenHAB
248
275
  def unit
249
276
  Thread.current.thread_variable_get(:unit)
250
277
  end
278
+
279
+ #
280
+ # Is a unit set for this thread
281
+ #
282
+ # @return [boolean] true if a unit is set by this thread, false otherwise
283
+ #
284
+ def unit?
285
+ unit != nil
286
+ end
251
287
  end
252
288
  end
253
289
  end
254
290
  end
255
291
  end
292
+ # rubocop: enable Metrics/ClassLength
@@ -44,7 +44,8 @@ module Logging
44
44
  # Log a message to the OpenHAB Logger
45
45
  #
46
46
  # @param [Symbol] severity Severity to log message at
47
- # @param [Object] msg to log, if no msg supplied and a block is provided, the msg is taken from the result of the block
47
+ # @param [Object] msg to log, if no msg supplied and a block is provided,
48
+ # the msg is taken from the result of the block
48
49
  #
49
50
  def log(severity:, msg: nil)
50
51
  severity = severity.to_sym
@@ -55,13 +56,7 @@ module Logging
55
56
  return unless @sl4fj_logger.send("is_#{severity.to_s.downcase}_enabled")
56
57
 
57
58
  # Process block if no message provided
58
- if msg.nil?
59
- if block_given?
60
- msg = yield
61
- else
62
- return
63
- end
64
- end
59
+ msg = yield if msg.nil? && block_given?
65
60
 
66
61
  msg = message_to_string(msg: msg)
67
62
 
@@ -8,6 +8,7 @@ require 'core/log'
8
8
  module StartupDelay
9
9
  include Logging
10
10
 
11
+ # @return [Integer] Number of seconds to wait between checks for automation manager
11
12
  CHECK_DELAY = 10
12
13
  private_constant :CHECK_DELAY
13
14
 
data/lib/openhab/osgi.rb CHANGED
@@ -38,6 +38,11 @@ module OpenHAB
38
38
  end
39
39
  end
40
40
 
41
+ #
42
+ # Get the bundle context
43
+ #
44
+ # @return [java::org::osgi::framework::BundleContext] OSGI bundle context
45
+ #
41
46
  def self.bundle_context
42
47
  @bundle_context ||= bundle.getBundleContext
43
48
  end
@@ -45,7 +50,9 @@ module OpenHAB
45
50
 
46
51
  # Get the OSGI Bundle for ScriptExtension Class
47
52
  def self.bundle
53
+ # rubocop: disable Style/GlobalVars
48
54
  @bundle ||= FrameworkUtil.getBundle($scriptExtension.class)
55
+ # rubocop: enable Style/GlobalVars
49
56
  end
50
57
  private_class_method :bundle
51
58
  end
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '2.14.1'
8
+ VERSION = '2.16.1'
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.1
4
+ version: 2.16.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-05 00:00:00.000000000 Z
11
+ date: 2021-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -54,22 +54,30 @@ files:
54
54
  - lib/openhab/core/dsl/monkey_patch/items/group_item.rb
55
55
  - lib/openhab/core/dsl/monkey_patch/items/items.rb
56
56
  - lib/openhab/core/dsl/monkey_patch/items/metadata.rb
57
+ - lib/openhab/core/dsl/monkey_patch/items/persistence.rb
57
58
  - lib/openhab/core/dsl/monkey_patch/items/switch_item.rb
58
59
  - lib/openhab/core/dsl/monkey_patch/ruby/number.rb
59
60
  - lib/openhab/core/dsl/monkey_patch/ruby/range.rb
60
61
  - lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb
62
+ - lib/openhab/core/dsl/monkey_patch/ruby/string.rb
61
63
  - lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb
62
64
  - lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb
63
65
  - lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb
64
66
  - lib/openhab/core/dsl/monkey_patch/types/percent_type.rb
67
+ - lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb
65
68
  - lib/openhab/core/dsl/monkey_patch/types/types.rb
69
+ - lib/openhab/core/dsl/persistence.rb
66
70
  - lib/openhab/core/dsl/property.rb
67
- - lib/openhab/core/dsl/rule/channel.rb
68
- - lib/openhab/core/dsl/rule/cron.rb
71
+ - lib/openhab/core/dsl/rule/automation_rule.rb
69
72
  - lib/openhab/core/dsl/rule/guard.rb
70
- - lib/openhab/core/dsl/rule/item.rb
71
73
  - lib/openhab/core/dsl/rule/rule.rb
72
- - lib/openhab/core/dsl/rule/triggers.rb
74
+ - lib/openhab/core/dsl/rule/rule_config.rb
75
+ - lib/openhab/core/dsl/rule/triggers/changed.rb
76
+ - lib/openhab/core/dsl/rule/triggers/channel.rb
77
+ - lib/openhab/core/dsl/rule/triggers/command.rb
78
+ - lib/openhab/core/dsl/rule/triggers/cron.rb
79
+ - lib/openhab/core/dsl/rule/triggers/trigger.rb
80
+ - lib/openhab/core/dsl/rule/triggers/updated.rb
73
81
  - lib/openhab/core/dsl/states.rb
74
82
  - lib/openhab/core/dsl/things.rb
75
83
  - lib/openhab/core/dsl/time_of_day.rb
@@ -1,203 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'core/log'
4
- require 'core/dsl/group'
5
- require 'core/dsl/things'
6
- require 'core/dsl/rule/triggers'
7
- require 'openhab/core/dsl/rule/triggers'
8
-
9
- module OpenHAB
10
- module Core
11
- module DSL
12
- module Rule
13
- #
14
- # Triggers for items in rules
15
- #
16
- module Item
17
- include Logging
18
- include OpenHAB::Core::DSL::Rule
19
- include OpenHAB::Core::DSL::Groups
20
- include OpenHAB::Core::DSL::Things
21
-
22
- #
23
- # Struct capturing data necessary for a conditional trigger
24
- #
25
- TriggerDelay = Struct.new(:to, :from, :duration, :timer, :tracking_to, keyword_init: true)
26
-
27
- #
28
- # Create a TriggerDelay for for an item or group that is changed for a specific duration
29
- #
30
- # @param [Object] item to create trigger delay for
31
- # @param [OpenHAB::Core::Duration] duration to delay trigger for until condition is met
32
- # @param [Item State] to OpenHAB Item State item or group needs to change to
33
- # @param [Item State] from OpenHAB Item State item or group needs to be coming from
34
- #
35
- # @return [Array] Array of current TriggerDelay objects
36
- #
37
- def changed_wait(item, duration:, to: nil, from: nil)
38
- # If GroupItems specified, use the group state trigger instead
39
- if item.is_a? GroupItems
40
- config = { 'groupName' => item.group.name }
41
- trigger = Trigger::GROUP_STATE_CHANGE
42
- else
43
- config = { 'itemName' => item.name }
44
- trigger = Trigger::ITEM_STATE_CHANGE
45
- end
46
- logger.trace("Creating Changed Wait Change Trigger for #{config}")
47
- trigger = append_trigger(trigger, config)
48
- @trigger_delays = { trigger.id => TriggerDelay.new(to: to, from: from, duration: duration) }
49
- end
50
-
51
- #
52
- # Create a trigger for when an item or group receives a command
53
- #
54
- # The commands/commands parameters are replicated for DSL fluency
55
- #
56
- # @param [Array] items Array of items to create trigger for
57
- # @param [Array] command commands to match for trigger
58
- # @param [Array] commands commands to match for trigger
59
- #
60
- #
61
- def received_command(*items, command: nil, commands: nil)
62
- items.flatten.each do |item|
63
- logger.trace("Creating received command trigger for item(#{item}) command(#{command}) commands(#{commands})")
64
-
65
- # Combine command and commands, doing union so only a single nil will be in the combined array.
66
- combined_commands = ([command] | [commands]).flatten
67
-
68
- # If either command or commands has a value and one is nil, we need to remove nil from the array.
69
- # If it is only now a single nil value, we leave the nil in place, so that we create a trigger
70
- # That isn't looking for a specific command.
71
- combined_commands = combined_commands.compact unless combined_commands.all?(&:nil?)
72
-
73
- combined_commands.each do |cmd|
74
- if item.is_a? GroupItems
75
- config = { 'groupName' => item.group.name }
76
- trigger = Trigger::GROUP_COMMAND
77
- else
78
- config = { 'itemName' => item.name }
79
- trigger = Trigger::ITEM_COMMAND
80
- end
81
- config['command'] = cmd.to_s unless cmd.nil?
82
- append_trigger(trigger, config)
83
- end
84
- end
85
- end
86
-
87
- #
88
- # Create a trigger when item, group or thing is updated
89
- #
90
- # @param [Array] items array to trigger on updated
91
- # @param [State] to to match for tigger
92
- #
93
- # @return [Trigger] Trigger for updated entity
94
- #
95
- def updated(*items, to: nil)
96
- items.flatten.each do |item|
97
- logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
98
- [to].flatten.each do |to_state|
99
- case item
100
- when GroupItems
101
- config = { 'groupName' => item.group.name }
102
- config['state'] = to_state.to_s unless to_state.nil?
103
- trigger = Trigger::GROUP_STATE_UPDATE
104
- when Thing
105
- trigger, config = trigger_for_thing(item, Trigger::THING_UPDATE, to_state)
106
- else
107
- config = { 'itemName' => item.name }
108
- config['state'] = to_state.to_s unless to_state.nil?
109
- trigger = Trigger::ITEM_STATE_UPDATE
110
- end
111
- append_trigger(trigger, config)
112
- end
113
- end
114
- end
115
-
116
- #
117
- # Creates a trigger item, group and thing changed
118
- #
119
- # @param [Object] items array of objects to create trigger for
120
- # @param [to] to state for object to change for
121
- # @param [from] from <description>
122
- # @param [OpenHAB::Core::Duration] for Duration to delay trigger until to state is met
123
- #
124
- # @return [Trigger] OpenHAB trigger
125
- #
126
- def changed(*items, to: nil, from: nil, for: nil)
127
- items.flatten.each do |item|
128
- logger.trace("Creating changed trigger for entity(#{item}), to(#{to}), from(#{from})")
129
- # for is a reserved word in ruby, so use local_variable_get :for
130
- if (wait_duration = binding.local_variable_get(:for))
131
- changed_wait(item, to: to, from: from, duration: wait_duration)
132
- else
133
- # Place in array and flatten to support multiple to elements or single or nil
134
- [to].flatten.each do |to_state|
135
- case item
136
- when GroupItems
137
- config = { 'groupName' => item.group.name }
138
- config['state'] = to_state.to_s if to_state
139
- config['previousState'] = from.to_s if from
140
- trigger = Trigger::GROUP_STATE_CHANGE
141
- when Thing
142
- trigger, config = trigger_for_thing(item, Trigger::THING_CHANGE, to_state, from)
143
- else
144
- config = { 'itemName' => item.name }
145
- config['state'] = to_state.to_s if to_state
146
- config['previousState'] = from.to_s if from
147
- trigger = Trigger::ITEM_STATE_CHANGE
148
- end
149
- append_trigger(trigger, config)
150
- end
151
- end
152
- end
153
- end
154
-
155
- private
156
-
157
- #
158
- # Append a trigger to the list of triggeres
159
- #
160
- # @param [String] type of trigger to create
161
- # @param [Map] config map describing trigger configuration
162
- #
163
- # @return [Trigger] OpenHAB trigger
164
- #
165
- def append_trigger(type, config)
166
- logger.trace("Creating trigger of type #{type} for #{config}")
167
- trigger = Trigger.trigger(type: type, config: config)
168
- @triggers << trigger
169
- trigger
170
- end
171
-
172
- #
173
- # Create a trigger for a thing
174
- #
175
- # @param [Thing] thing to create trigger for
176
- # @param [Trigger] trigger to map with thing
177
- # @param [State] to for thing
178
- # @param [State] from state of thing
179
- #
180
- # @return [Array] Trigger and config for thing
181
- #
182
- def trigger_for_thing(thing, trigger, to = nil, from = nil)
183
- config = { 'thingUID' => thing.uid.to_s }
184
- config['status'] = trigger_state_from_symbol(to).to_s if to
185
- config['previousStatus'] = trigger_state_from_symbol(from).to_s if from
186
- [trigger, config]
187
- end
188
-
189
- #
190
- # converts object to upcase string if its a symbol
191
- #
192
- # @param [sym] sym potential symbol to convert
193
- #
194
- # @return [String] Upcased symbol as string
195
- #
196
- def trigger_state_from_symbol(sym)
197
- sym.to_s.upcase if (sym.is_a? Symbol) || sym
198
- end
199
- end
200
- end
201
- end
202
- end
203
- end