openhab-scripting 4.1.4 → 4.2.0

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/entity_lookup.rb +1 -57
  3. data/lib/openhab/dsl/dsl.rb +6 -12
  4. data/lib/openhab/dsl/group.rb +1 -5
  5. data/lib/openhab/dsl/items/comparable_item.rb +49 -0
  6. data/lib/openhab/dsl/items/contact_item.rb +41 -0
  7. data/lib/openhab/dsl/items/date_time_item.rb +64 -0
  8. data/lib/openhab/dsl/items/dimmer_item.rb +59 -0
  9. data/lib/openhab/dsl/items/generic_item.rb +197 -0
  10. data/lib/openhab/dsl/items/group_item.rb +56 -92
  11. data/lib/openhab/dsl/items/image_item.rb +5 -41
  12. data/lib/openhab/dsl/items/item_registry.rb +49 -0
  13. data/lib/openhab/dsl/items/items.rb +71 -35
  14. data/lib/openhab/dsl/items/metadata.rb +325 -0
  15. data/lib/openhab/dsl/items/number_item.rb +6 -312
  16. data/lib/openhab/dsl/items/numeric_item.rb +66 -0
  17. data/lib/openhab/dsl/items/persistence.rb +122 -0
  18. data/lib/openhab/dsl/items/player_item.rb +49 -40
  19. data/lib/openhab/dsl/items/rollershutter_item.rb +25 -77
  20. data/lib/openhab/dsl/items/string_item.rb +16 -58
  21. data/lib/openhab/dsl/items/switch_item.rb +62 -0
  22. data/lib/openhab/dsl/lazy_array.rb +8 -6
  23. data/lib/openhab/dsl/monkey_patch/events/events.rb +2 -2
  24. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +67 -24
  25. data/lib/openhab/dsl/monkey_patch/events/item_event.rb +5 -5
  26. data/lib/openhab/dsl/monkey_patch/events/item_state.rb +10 -11
  27. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +10 -11
  28. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +25 -2
  29. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -3
  30. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +24 -24
  31. data/lib/openhab/dsl/states.rb +1 -1
  32. data/lib/openhab/dsl/time_of_day.rb +3 -5
  33. data/lib/openhab/dsl/types/comparable_type.rb +21 -0
  34. data/lib/openhab/dsl/types/date_time_type.rb +334 -0
  35. data/lib/openhab/dsl/types/decimal_type.rb +187 -0
  36. data/lib/openhab/dsl/types/increase_decrease_type.rb +23 -0
  37. data/lib/openhab/dsl/types/next_previous_type.rb +23 -0
  38. data/lib/openhab/dsl/types/numeric_type.rb +39 -0
  39. data/lib/openhab/dsl/types/on_off_type.rb +29 -0
  40. data/lib/openhab/dsl/types/open_closed_type.rb +29 -0
  41. data/lib/openhab/dsl/types/percent_type.rb +68 -0
  42. data/lib/openhab/dsl/types/play_pause_type.rb +27 -0
  43. data/lib/openhab/dsl/types/quantity_type.rb +275 -0
  44. data/lib/openhab/dsl/types/refresh_type.rb +18 -0
  45. data/lib/openhab/dsl/types/rewind_fastforward_type.rb +33 -0
  46. data/lib/openhab/dsl/types/stop_move_type.rb +23 -0
  47. data/lib/openhab/dsl/types/string_type.rb +88 -0
  48. data/lib/openhab/dsl/types/type.rb +72 -0
  49. data/lib/openhab/dsl/types/types.rb +77 -0
  50. data/lib/openhab/dsl/types/un_def_type.rb +22 -0
  51. data/lib/openhab/dsl/types/up_down_type.rb +32 -0
  52. data/lib/openhab/dsl/units.rb +11 -6
  53. data/lib/openhab/version.rb +1 -1
  54. data/lib/openhab.rb +0 -1
  55. metadata +31 -28
  56. data/lib/openhab/dsl/items/datetime_item.rb +0 -75
  57. data/lib/openhab/dsl/items/item_command.rb +0 -90
  58. data/lib/openhab/dsl/items/item_delegate.rb +0 -125
  59. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +0 -51
  60. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +0 -140
  61. data/lib/openhab/dsl/monkey_patch/items/items.rb +0 -142
  62. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +0 -328
  63. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +0 -123
  64. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +0 -71
  65. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +0 -47
  66. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -32
  67. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +0 -97
  68. data/lib/openhab/dsl/monkey_patch/types/increase_decrease_type.rb +0 -23
  69. data/lib/openhab/dsl/monkey_patch/types/next_previous_type.rb +0 -23
  70. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +0 -79
  71. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +0 -71
  72. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +0 -77
  73. data/lib/openhab/dsl/monkey_patch/types/play_pause_type.rb +0 -23
  74. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +0 -69
  75. data/lib/openhab/dsl/monkey_patch/types/refresh_type.rb +0 -23
  76. data/lib/openhab/dsl/monkey_patch/types/rewind_fastforward_type.rb +0 -23
  77. data/lib/openhab/dsl/monkey_patch/types/stop_move_type.rb +0 -23
  78. data/lib/openhab/dsl/monkey_patch/types/types.rb +0 -15
  79. data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +0 -72
  80. data/lib/openhab/dsl/types/datetime.rb +0 -338
  81. data/lib/openhab/dsl/types/quantity.rb +0 -300
@@ -0,0 +1,325 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+ require 'pp'
5
+ require 'forwardable'
6
+ require 'openhab/core/osgi'
7
+ require 'openhab/log/logger'
8
+
9
+ module OpenHAB
10
+ module DSL
11
+ module Items
12
+ #
13
+ # Metadata extension for Items
14
+ #
15
+ module Metadata
16
+ include OpenHAB::Log
17
+
18
+ java_import Java::OrgOpenhabCoreItems::Metadata
19
+ java_import Java::OrgOpenhabCoreItems::MetadataKey
20
+
21
+ #
22
+ # Provide the interface to access namespace's value and configuration
23
+ #
24
+ class MetadataItem < SimpleDelegator
25
+ extend Forwardable
26
+
27
+ def_delegator :@metadata, :value
28
+
29
+ def initialize(metadata: nil, key: nil, value: nil, config: nil)
30
+ @metadata = metadata || Metadata.new(key || MetadataKey.new('', ''), value&.to_s, config)
31
+ super(to_ruby(@metadata&.configuration))
32
+ end
33
+
34
+ #
35
+ # Updates the metadata configuration associated with the key
36
+ #
37
+ def []=(key, value)
38
+ configuration = {}.merge(@metadata&.configuration || {}).merge({ key => value })
39
+ metadata = Metadata.new(@metadata&.uID, @metadata&.value, configuration)
40
+ NamespaceAccessor.registry.update(metadata) if @metadata&.uID
41
+ end
42
+
43
+ #
44
+ # Delete the configuration with the given key
45
+ #
46
+ # @return [Java::Org::openhab::core::items::Metadata] the old metadata
47
+ #
48
+ def delete(key)
49
+ configuration = {}.merge(@metadata&.configuration || {})
50
+ configuration.delete(key)
51
+ metadata = Metadata.new(@metadata&.uID, @metadata&.value, configuration)
52
+ NamespaceAccessor.registry.update(metadata) if @metadata&.uID
53
+ end
54
+
55
+ #
56
+ # Set the metadata value
57
+ #
58
+ # @return [Java::Org::openhab::core::items::Metadata] the old metadata
59
+ #
60
+ def value=(value)
61
+ metadata = Metadata.new(@metadata&.uID, value&.to_s, @metadata&.configuration)
62
+ NamespaceAccessor.registry.update(metadata) if @metadata&.uID
63
+ end
64
+
65
+ #
66
+ # Set the entire configuration to a hash
67
+ #
68
+ # @return [Java::Org::openhab::core::items::Metadata] the old metadata
69
+ #
70
+ def config=(config)
71
+ raise ArgumentError, 'Configuration must be a hash' unless config.is_a? Hash
72
+
73
+ metadata = Metadata.new(@metadata&.uID, @metadata&.value, config)
74
+ NamespaceAccessor.registry.update(metadata) if @metadata&.uID
75
+ end
76
+ alias configuration= config=
77
+
78
+ #
79
+ # Convert the metadata to an array
80
+ #
81
+ # @return [Array[2]] An array of [value, configuration]
82
+ #
83
+ def to_a
84
+ [@metadata&.value, @metadata&.configuration || {}]
85
+ end
86
+
87
+ private
88
+
89
+ #
90
+ # Recursively convert the supplied Hash object into a Ruby Hash and recreate the keys and values
91
+ #
92
+ # @param [Hash] Hash to convert
93
+ #
94
+ # @return [Hash] The converted hash
95
+ #
96
+ def to_ruby_hash(hash)
97
+ return unless hash.respond_to? :each_with_object
98
+
99
+ hash.each_with_object({}) { |(key, value), ruby_hash| ruby_hash[to_ruby(key)] = to_ruby(value) }
100
+ end
101
+
102
+ #
103
+ # Recursively convert the supplied array to a Ruby array and recreate all String values
104
+ #
105
+ # @param [Object] array to convert
106
+ #
107
+ # @return [Array] The converted array
108
+ #
109
+ def to_ruby_array(array)
110
+ return unless array.respond_to? :each_with_object
111
+
112
+ array.each_with_object([]) { |value, ruby_array| ruby_array << to_ruby(value) }
113
+ end
114
+
115
+ # Convert the given object to Ruby equivalent
116
+ def to_ruby(value)
117
+ case value
118
+ when Hash, Java::JavaUtil::Map then to_ruby_hash(value)
119
+ when Array, Java::JavaUtil::List then to_ruby_array(value)
120
+ when String then String.new(value)
121
+ else value
122
+ end
123
+ end
124
+ end
125
+
126
+ #
127
+ # Provide the interface to access item metadata
128
+ #
129
+ class NamespaceAccessor
130
+ include Enumerable
131
+
132
+ def initialize(item_name:)
133
+ @item_name = item_name
134
+ end
135
+
136
+ #
137
+ # Return the metadata namespace
138
+ #
139
+ # @return [OpenHAB::DSL::Items::MetadataItem], or nil if the namespace doesn't exist
140
+ #
141
+ def [](namespace)
142
+ logger.trace("Getting metadata for item: #{@item_name}, namespace '#{namespace}'")
143
+ metadata = NamespaceAccessor.registry.get(MetadataKey.new(namespace, @item_name))
144
+ MetadataItem.new(metadata: metadata) if metadata
145
+ end
146
+
147
+ #
148
+ # Set the metadata namespace. If the namespace does not exist, it will be created
149
+ #
150
+ # @param value [Object] The assigned value can be a OpenHAB::DSL::Items::MetadataItem,
151
+ # Java::Org::openhab::core::items::Metadata, Array[2] of [value, configuration],
152
+ # A String to set the value and clear the configuration,
153
+ # or a Hash to set the configuration and set the value to nil
154
+ #
155
+ # @return [OpenHAB::DSL::Items::MetadataItem]
156
+ #
157
+ def []=(namespace, value)
158
+ meta_value, configuration = update_from_value(value)
159
+
160
+ key = MetadataKey.new(namespace, @item_name)
161
+ metadata = Metadata.new(key, meta_value&.to_s, configuration)
162
+ # registry.get can be omitted, but registry.update will log a warning for nonexistent metadata
163
+ if NamespaceAccessor.registry.get(key)
164
+ NamespaceAccessor.registry.update(metadata)
165
+ else
166
+ NamespaceAccessor.registry.add(metadata)
167
+ end
168
+ end
169
+
170
+ #
171
+ # Implements Hash#dig-like functionaity to metadata
172
+ #
173
+ # @param [String] key The first key
174
+ # @param [Array<String, Symbol>] keys More keys to dig deeper
175
+ #
176
+ # @return [OpenHAB::DSL::Items::MetadataItem], or nil if the namespace doesn't exist
177
+ #
178
+ def dig(key, *keys)
179
+ keys.empty? ? self[key]&.value : self[key]&.dig(*keys)
180
+ end
181
+
182
+ #
183
+ # Enumerates through all the namespaces
184
+ #
185
+ def each
186
+ return unless block_given?
187
+
188
+ NamespaceAccessor.registry.getAll.each do |meta|
189
+ yield meta.uID.namespace, meta.value, meta.configuration if meta.uID.itemName == @item_name
190
+ end
191
+ end
192
+
193
+ #
194
+ # Remove all the namespaces
195
+ #
196
+ def clear
197
+ NamespaceAccessor.registry.removeItemMetadata @item_name
198
+ end
199
+
200
+ #
201
+ # Delete a specific namespace
202
+ #
203
+ # @param namespace [String] The namespace to delete
204
+ #
205
+ def delete(namespace)
206
+ NamespaceAccessor.registry.remove(MetadataKey.new(namespace, @item_name))
207
+ end
208
+
209
+ alias delete_all clear
210
+
211
+ #
212
+ # @return [Boolean] True if the given namespace exists, false otherwise
213
+ #
214
+ def key?(namespace)
215
+ !NamespaceAccessor.registry.get(MetadataKey.new(namespace, @item_name)).nil?
216
+ end
217
+
218
+ alias has_key? key?
219
+ alias include? key?
220
+
221
+ #
222
+ # Merge the given hash with the current metadata. Existing namespace that matches the name
223
+ # of the new namespace will be overwritten. Others will be added.
224
+ #
225
+ def merge!(*others)
226
+ return self if others.empty?
227
+
228
+ others.each do |other|
229
+ case other
230
+ when Hash then merge_hash!(other)
231
+ when self.class then merge_metadata!(other)
232
+ else raise ArgumentError, "merge only supports Hash, or another item's metadata"
233
+ end
234
+ end
235
+ self
236
+ end
237
+
238
+ #
239
+ # @return [String] the string representation of all the namespaces with their value and config
240
+ #
241
+ def to_s
242
+ namespaces = []
243
+ each { |ns, value, config| namespaces << "\"#{ns}\"=>[\"#{value}\",#{config}]" }
244
+ "{#{namespaces.join(',')}}"
245
+ end
246
+
247
+ #
248
+ # @return [Java::org::openhab::core::items::MetadataRegistry]
249
+ #
250
+ def self.registry
251
+ @registry ||= OpenHAB::Core::OSGI.service('org.openhab.core.items.MetadataRegistry')
252
+ end
253
+
254
+ private
255
+
256
+ #
257
+ # perform an updated based on the supplied value
258
+ #
259
+ # @param [MetadataItem,Metadata,Array,Hash] value to perform update from
260
+ #
261
+ # @return [Array<Object,Hash>] Array containing the value and configuration based on the
262
+ # the supplied object
263
+ #
264
+ def update_from_value(value)
265
+ case value
266
+ when MetadataItem then [value.value, value.__getobj__]
267
+ when Metadata then [value.value, value.configuration]
268
+ when Array
269
+ raise ArgumentError, 'Array must contain 2 elements: value, config' if value.length != 2
270
+
271
+ value
272
+ when Hash then [nil, value]
273
+ else [value, nil]
274
+ end
275
+ end
276
+
277
+ #
278
+ # Merge the metadata from the supplied other metadata object
279
+ #
280
+ # @param [Hash] other metadata object to merge
281
+ # @yield [key, current_metadata, new_meta] to process merge
282
+ #
283
+ #
284
+ def merge_metadata!(other)
285
+ other.each do |key, new_value, new_config|
286
+ new_meta = new_value, new_config
287
+ if block_given?
288
+ current_meta = self[key]&.to_a
289
+ new_meta = yield key, current_meta, new_meta unless current_meta.nil?
290
+ end
291
+ self[key] = new_meta
292
+ end
293
+ end
294
+
295
+ #
296
+ # Merge a hash into the metadata
297
+ #
298
+ # @param [Hash] other to merge into metadata
299
+ # @yield [key, current_metadata, new_meta] to process merge
300
+ #
301
+ #
302
+ def merge_hash!(other)
303
+ other.each do |key, new_meta|
304
+ if block_given?
305
+ current_meta = self[key]&.to_a
306
+ new_meta = yield key, current_meta, new_meta unless current_meta.nil?
307
+ end
308
+ self[key] = new_meta
309
+ end
310
+ end
311
+ end
312
+
313
+ #
314
+ # Accessor to the item's metadata
315
+ #
316
+ # @return [NamespaceAccessor] an Enumerable object to access item's namespaces
317
+ #
318
+ def meta
319
+ @meta ||= NamespaceAccessor.new(item_name: name)
320
+ end
321
+ alias metadata meta
322
+ end
323
+ end
324
+ end
325
+ end
@@ -1,323 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bigdecimal'
4
- require 'forwardable'
5
- require 'java'
6
- require 'openhab/dsl/types/quantity'
7
- require 'openhab/dsl/items/item_delegate'
3
+ require 'openhab/dsl/items/numeric_item'
8
4
 
9
5
  module OpenHAB
10
6
  module DSL
11
7
  module Items
12
- #
13
- # Delegation to OpenHAB Number Item
14
- #
15
- # rubocop: disable Metrics/ClassLength
16
- # Disabled because this class has a single responsibility, there does not appear a logical
17
- # way of breaking it up into multiple classes
18
- class NumberItem < Numeric
19
- extend OpenHAB::DSL::Items::ItemDelegate
20
- extend OpenHAB::DSL::Items::ItemCommand
8
+ java_import org.openhab.core.library.items.NumberItem
21
9
 
22
- def_item_delegator :@number_item
23
-
24
- java_import org.openhab.core.library.types.DecimalType
25
- java_import org.openhab.core.library.types.QuantityType
26
- java_import org.openhab.core.types.util.UnitUtils
27
- java_import org.openhab.core.library.unit.Units
28
-
29
- item_type Java::OrgOpenhabCoreLibraryItems::NumberItem
30
-
31
- #
32
- # Create a new NumberItem
33
- #
34
- # @param [Java::Org::openhab::core::library::items::NumberItem] number_item OpenHAB number item to delegate to
35
- #
36
- def initialize(number_item)
37
- @number_item = number_item
38
- item_missing_delegate { @number_item }
39
- super()
40
- end
41
-
42
- #
43
- # Check if NumberItem is truthy? as per defined by library
44
- #
45
- # @return [Boolean] True if item is not in state UNDEF or NULL and value is not zero.
46
- #
47
- def truthy?
48
- @number_item.state? && @number_item.state != DecimalType::ZERO
49
- end
50
-
51
- #
52
- # Coerce objects into a NumberItem
53
- #
54
- # @param [Object] other object to coerce to a NumberItem if possible
55
- #
56
- # @return [Object] NumberItem, QuantityTypes, BigDecimal or nil depending on NumberItem configuration
57
- # and/or supplied object
58
- #
59
- def coerce(other)
60
- logger.trace("Coercing #{self} as a request from #{other.class}")
61
- case other
62
- when Quantity then coerce_from_quantity(other)
63
- when Numeric then coerce_from_numeric(other)
64
- else
65
- logger.trace("#{self} cannot be coerced to #{other.class}")
66
- nil
67
- end
68
- end
69
-
70
- #
71
- # Compare NumberItem to supplied object
72
- #
73
- # @param [Object] other object to compare to
74
- #
75
- # @return [Integer] -1,0,1 or nil depending on value supplied,
76
- # nil comparison to supplied object is not possible.
77
- #
78
- def <=>(other)
79
- logger.trace("NumberItem #{self} <=> #{other} (#{other.class})")
80
- case other
81
- when NumberItem then number_item_compare(other)
82
- when Numeric then numeric_compare(other)
83
- when String then string_compare(other)
84
- else state_compare(other)
85
- end
86
- end
87
-
88
- #
89
- # Convert NumberItem to a Quantity
90
- #
91
- # @param [Object] other String or Unit representing an OpenHAB Unit
92
- #
93
- # @return [OpenHAB::DSL::Types::Quantity] NumberItem converted to supplied Unit
94
- #
95
- def |(other)
96
- other = UnitUtils.parse_unit(other) if other.is_a? String
97
-
98
- if dimension
99
- to_qt | other
100
- else
101
- Quantity.new(QuantityType.new(to_d.to_java, other))
102
- end
103
- end
104
-
105
- #
106
- # Convert NumberItem to a Quantity
107
- #
108
- # @return [OpenHAB::DSL::Types::Quantity] NumberItem converted to a QuantityUnit
109
- #
110
- def to_qt
111
- if dimension
112
- Quantity.new(@number_item.get_state_as(QuantityType))
113
- else
114
- Quantity.new(QuantityType.new(to_d.to_java, Units::ONE))
115
- end
116
- end
117
-
118
- #
119
- # Converts the NumberItem to an Integer
120
- #
121
- # @return [Integer] NumberItem as an integer
122
- #
123
- def to_i
124
- to_d&.to_i
125
- end
126
-
127
- #
128
- # Converts the NumberItem to a float
129
- #
130
- # @return [Float] NumberItem as a float
131
- #
132
- def to_f
133
- to_d&.to_f
134
- end
135
-
136
- #
137
- # Converts the NumberItem to a BigDecimal
138
- #
139
- # @return [BigDecimal] NumberItem as a BigDecimal
140
- #
141
- def to_d
142
- @number_item.state.to_big_decimal.to_d if @number_item.state.respond_to? :to_big_decimal
143
- end
144
-
145
- #
146
- # Get the Dimension attached to the NumberItem
147
- #
148
- # @return [Java::org::openhab::core::library::types::QuantityType] dimension
149
- #
150
- def dimension
151
- @number_item.dimension
152
- end
153
-
154
- %w[+ - * /].each do |operation|
155
- define_method(operation) do |other|
156
- logger.trace("Execution math operation '#{operation}' on #{inspect} with #{other.inspect}")
157
- left_operand, right_operand = operands_for_operation(other)
158
- left_operand.public_send(operation, right_operand)
159
- end
160
- end
161
-
162
- private
163
-
164
- #
165
- # Compare if other responds to state
166
- #
167
- # @param [Object] other object to compare to
168
- #
169
- # @return [Integer] -1,0,1 depending on less than, equal to or greater than other
170
- #
171
- def state_compare(other)
172
- other = other.state if other.respond_to? :state
173
- @number_item.state <=> other
174
- end
175
-
176
- #
177
- # Compare if other is a String
178
- #
179
- # @param [String] other object to compare to
180
- #
181
- # @return [Integer] -1,0,1,nil depending on less than, equal to or greater than other
182
- # nil if this number item does not have a dimension
183
- #
184
- def string_compare(other)
185
- @number_item.state <=> QuantityType.new(other) if dimension
186
- end
187
-
188
- #
189
- # Compare if other is a Numeric
190
- #
191
- # @param [String] other to compare to
192
- #
193
- # @return [Integer] -1,0,1 depending on less than, equal to or greater than other
194
- #
195
- def numeric_compare(other)
196
- @number_item.state.to_big_decimal.to_d <=> other.to_d
197
- end
198
-
199
- #
200
- # Get the operands for any operation
201
- #
202
- # @param [Object] other object to convert to a compatible operand
203
- #
204
- # @return [Array[Object,Object]] of operands where the first value is the left operand
205
- # and the second value is the right operand
206
- #
207
- def operands_for_operation(other)
208
- case other
209
- when NumberItem then number_item_operands(other)
210
- when Numeric then [to_d, other.to_d]
211
- when String then string_operands(other)
212
- else
213
- return other.coerce(to_d) if other.respond_to? :coerce
214
-
215
- raise ArgumentError, "#{other.class} can't be coerced into a NumberItem"
216
- end
217
- end
218
-
219
- #
220
- # Get operands for an operation when the right operand is provided as a string
221
- #
222
- # @param [String] other right operand
223
- #
224
- # @return [Array[QuantityType,QuantiyType]] of operands where the first value is the left operand
225
- # and the second value is the right operand
226
- #
227
- def string_operands(other)
228
- return [to_qt, Quantity.new(other)] if dimension
229
-
230
- raise ArgumentError, 'Strings are only valid operands if NumberItem is dimensions=ed.'
231
- end
232
-
233
- #
234
- # Get operands for an operation when the right operand is provided is another number item
235
- #
236
- # @param [NumberItem] other right operand
237
- #
238
- # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>] of operands depending on
239
- # if the left or right operand has a dimensions
240
- #
241
- def number_item_operands(other)
242
- if dimension || other.dimension
243
- dimensioned_operands(other)
244
- else
245
- logger.trace("Both objects lack dimension, self='#{self}' other='#{other}'")
246
- # If nothing has a dimension, just use BigDecimals
247
- [to_d, other.to_d]
248
- end
249
- end
250
-
251
- #
252
- # Get operands for an operation when the left or right operand has a dimension
253
- #
254
- # @param [NumberItem] other right operand
255
- #
256
- # @return [Array<QuantityType,QuantityType>] of operands
257
- #
258
- def dimensioned_operands(other)
259
- logger.trace("Dimensions self='#{dimension}' other='#{other.dimension}'")
260
- if dimension
261
- if other.dimension
262
- # If both numbers have dimensions, do the math on the quantity types.
263
- [to_qt, other.to_qt]
264
- else
265
- # If this number has dimension and the other does not,
266
- # do math with this quantity type and the other as a big decimal
267
- [to_qt, other]
268
- end
269
- else
270
- # If this number has no dimension and the other does, convert this into a dimensionless quantity
271
- [to_qt, other]
272
- end
273
- end
274
-
275
- #
276
- # Compare two number items, taking into account any dimensions
277
- #
278
- # @param [NumberItem] other number item
279
- #
280
- # @return [-1,0,1] depending on if other object is less than, equal to or greater than self
281
- #
282
- def number_item_compare(other)
283
- if other.dimension
284
- logger.trace('Other is dimensioned, converting self and other to QuantityTypes to compare')
285
- to_qt <=> other.to_qt
286
- else
287
- @number_item.state <=> other.state
288
- end
289
- end
290
-
291
- #
292
- # Coerce from a numberic object depnding on dimension and state
293
- #
294
- # @param [Numeric] other numeric object to convert
295
- #
296
- # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>,nil] depending on
297
- # if this object has a dimension or state
298
- #
299
- def coerce_from_numeric(other)
300
- if dimension
301
- [Quantity.new(other), to_qt]
302
- elsif @number_item.state?
303
- [other.to_d, @number_item.state.to_big_decimal.to_d]
304
- end
305
- end
306
-
307
- #
308
- # Coerce when other is a quantity
309
- #
310
- # @param [QuantityType] other
311
- #
312
- # @return [Array<QuanityType,QuantityType] other and self as a quantity type
313
- #
314
- def coerce_from_quantity(other)
315
- as_qt = to_qt
316
- logger.trace("Converted #{self} to a Quantity #{as_qt}")
317
- [other, as_qt]
318
- end
10
+ # Adds methods to core OpenHAB NumberItem type to make it more natural in
11
+ # Ruby
12
+ class NumberItem < GenericItem
13
+ include NumericItem
319
14
  end
320
15
  end
321
16
  end
322
17
  end
323
- # rubocop: enable Metrics/ClassLength