openhab-scripting 4.1.4 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
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