openhab-scripting 4.1.4 → 4.5.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/entity_lookup.rb +1 -57
  3. data/lib/openhab/dsl/actions.rb +2 -3
  4. data/lib/openhab/dsl/dsl.rb +8 -12
  5. data/lib/openhab/dsl/group.rb +1 -5
  6. data/lib/openhab/dsl/items/color_item.rb +60 -0
  7. data/lib/openhab/dsl/items/comparable_item.rb +49 -0
  8. data/lib/openhab/dsl/items/contact_item.rb +41 -0
  9. data/lib/openhab/dsl/items/date_time_item.rb +64 -0
  10. data/lib/openhab/dsl/items/dimmer_item.rb +59 -0
  11. data/lib/openhab/dsl/items/ensure.rb +93 -0
  12. data/lib/openhab/dsl/items/generic_item.rb +174 -0
  13. data/lib/openhab/dsl/items/group_item.rb +121 -89
  14. data/lib/openhab/dsl/items/image_item.rb +5 -41
  15. data/lib/openhab/dsl/items/item_equality.rb +36 -0
  16. data/lib/openhab/dsl/items/item_registry.rb +49 -0
  17. data/lib/openhab/dsl/items/items.rb +81 -35
  18. data/lib/openhab/dsl/items/metadata.rb +325 -0
  19. data/lib/openhab/dsl/items/number_item.rb +6 -312
  20. data/lib/openhab/dsl/items/numeric_item.rb +68 -0
  21. data/lib/openhab/dsl/items/persistence.rb +122 -0
  22. data/lib/openhab/dsl/items/player_item.rb +49 -40
  23. data/lib/openhab/dsl/items/rollershutter_item.rb +25 -77
  24. data/lib/openhab/dsl/items/string_item.rb +16 -58
  25. data/lib/openhab/dsl/items/switch_item.rb +62 -0
  26. data/lib/openhab/dsl/lazy_array.rb +8 -6
  27. data/lib/openhab/dsl/monkey_patch/events/events.rb +2 -2
  28. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +67 -24
  29. data/lib/openhab/dsl/monkey_patch/events/item_event.rb +5 -5
  30. data/lib/openhab/dsl/monkey_patch/events/item_state.rb +10 -11
  31. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +10 -11
  32. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +25 -2
  33. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -3
  34. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +24 -24
  35. data/lib/openhab/dsl/rules/terse.rb +24 -0
  36. data/lib/openhab/dsl/states.rb +1 -1
  37. data/lib/openhab/dsl/time_of_day.rb +3 -5
  38. data/lib/openhab/dsl/types/comparable_type.rb +21 -0
  39. data/lib/openhab/dsl/types/date_time_type.rb +334 -0
  40. data/lib/openhab/dsl/types/decimal_type.rb +187 -0
  41. data/lib/openhab/dsl/types/hsb_type.rb +201 -0
  42. data/lib/openhab/dsl/types/increase_decrease_type.rb +23 -0
  43. data/lib/openhab/dsl/types/next_previous_type.rb +23 -0
  44. data/lib/openhab/dsl/types/numeric_type.rb +39 -0
  45. data/lib/openhab/dsl/types/on_off_type.rb +29 -0
  46. data/lib/openhab/dsl/types/open_closed_type.rb +29 -0
  47. data/lib/openhab/dsl/types/percent_type.rb +70 -0
  48. data/lib/openhab/dsl/types/play_pause_type.rb +27 -0
  49. data/lib/openhab/dsl/types/quantity_type.rb +275 -0
  50. data/lib/openhab/dsl/types/refresh_type.rb +18 -0
  51. data/lib/openhab/dsl/types/rewind_fastforward_type.rb +33 -0
  52. data/lib/openhab/dsl/types/stop_move_type.rb +23 -0
  53. data/lib/openhab/dsl/types/string_type.rb +88 -0
  54. data/lib/openhab/dsl/types/type.rb +72 -0
  55. data/lib/openhab/dsl/types/types.rb +78 -0
  56. data/lib/openhab/dsl/types/un_def_type.rb +22 -0
  57. data/lib/openhab/dsl/types/up_down_type.rb +32 -0
  58. data/lib/openhab/dsl/units.rb +11 -6
  59. data/lib/openhab/version.rb +1 -1
  60. data/lib/openhab.rb +0 -1
  61. metadata +36 -28
  62. data/lib/openhab/dsl/items/datetime_item.rb +0 -75
  63. data/lib/openhab/dsl/items/item_command.rb +0 -90
  64. data/lib/openhab/dsl/items/item_delegate.rb +0 -125
  65. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +0 -51
  66. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +0 -140
  67. data/lib/openhab/dsl/monkey_patch/items/items.rb +0 -142
  68. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +0 -328
  69. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +0 -123
  70. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +0 -71
  71. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +0 -47
  72. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -32
  73. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +0 -97
  74. data/lib/openhab/dsl/monkey_patch/types/increase_decrease_type.rb +0 -23
  75. data/lib/openhab/dsl/monkey_patch/types/next_previous_type.rb +0 -23
  76. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +0 -79
  77. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +0 -71
  78. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +0 -77
  79. data/lib/openhab/dsl/monkey_patch/types/play_pause_type.rb +0 -23
  80. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +0 -69
  81. data/lib/openhab/dsl/monkey_patch/types/refresh_type.rb +0 -23
  82. data/lib/openhab/dsl/monkey_patch/types/rewind_fastforward_type.rb +0 -23
  83. data/lib/openhab/dsl/monkey_patch/types/stop_move_type.rb +0 -23
  84. data/lib/openhab/dsl/monkey_patch/types/types.rb +0 -15
  85. data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +0 -72
  86. data/lib/openhab/dsl/types/datetime.rb +0 -338
  87. data/lib/openhab/dsl/types/quantity.rb +0 -300
@@ -1,338 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'forwardable'
5
- require 'time'
6
-
7
- module OpenHAB
8
- module DSL
9
- module Types
10
- #
11
- # Ruby implementation for OpenHAB DateTimeType
12
- #
13
- # @author Anders Alfredsson
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 DateTime
19
- extend Forwardable
20
- include Comparable
21
- include OpenHAB::Log
22
-
23
- def_delegator :datetime, :to_s
24
- def_delegator :zoned_date_time, :month_value, :month
25
- def_delegator :zoned_date_time, :day_of_month, :mday
26
- def_delegator :zoned_date_time, :day_of_year, :yday
27
- def_delegator :zoned_date_time, :minute, :min
28
- def_delegator :zoned_date_time, :second, :sec
29
- def_delegator :zoned_date_time, :nano, :nsec
30
- def_delegator :zoned_date_time, :to_epoch_second, :to_i
31
- alias inspect to_s
32
- alias day mday
33
-
34
- java_import Java::OrgOpenhabCoreLibraryTypes::DateTimeType
35
- java_import java.time.ZonedDateTime
36
- java_import java.time.Instant
37
- java_import java.time.ZoneId
38
- java_import java.time.ZoneOffset
39
- java_import java.time.Duration
40
-
41
- #
42
- # Regex expression to identify strings defining a time in hours, minutes and optionally seconds
43
- #
44
- TIME_ONLY_REGEX = /\A\d\d:\d\d(:\d\d)?\Z/.freeze
45
-
46
- #
47
- # Regex expression to identify strings defining a time in hours, minutes and optionally seconds
48
- #
49
- DATE_ONLY_REGEX = /\A\d{4}-\d\d-\d\d\Z/.freeze
50
-
51
- attr_reader :datetime
52
-
53
- #
54
- # Create a new DateTime instance wrapping an OpenHAB DateTimeType
55
- #
56
- # @param [Java::org::openhab::core::library::types::DateTimeType] datetime The DateTimeType instance to
57
- # delegate to, or an object that can be converted to a DateTimeType
58
- #
59
- def initialize(datetime)
60
- @datetime = case datetime
61
- when DateTimeType
62
- datetime
63
- when ZonedDateTime
64
- DateTimeType.new(datetime)
65
- else
66
- raise "Unexpected type #{datetime.class} provided to DateTime initializer"
67
- end
68
- end
69
-
70
- #
71
- # Compare thes DateTime object to another
72
- #
73
- # @param [Object] other Other object to compare against
74
- #
75
- # @return [Integer] -1, 0 or 1 depending on the outcome
76
- #
77
- def <=>(other)
78
- if other.respond_to?(:zoned_date_time)
79
- return zoned_date_time.to_instant.compare_to(other.zoned_date_time.to_instant)
80
- end
81
-
82
- case other
83
- when TimeOfDay::TimeOfDay, TimeOfDay::TimeOfDayRangeElement then to_tod <=> other
84
- when String then self <=> DateTime.parse(DATE_ONLY_REGEX.match?(other) ? "#{other}'T'00:00:00#{zone}" : other)
85
- else
86
- self <=> DateTime.from(other)
87
- end
88
- end
89
-
90
- #
91
- # Adds another object to this DateTime
92
- #
93
- # @param [Object] other Object to add to this. Can be a Numeric, another DateTime/Time/DateTimeType, a
94
- # Duration or a String that can be parsed into a DateTimeType or Time object
95
- #
96
- # @return [DateTime] A new DateTime object representing the result of the calculation
97
- #
98
- def +(other)
99
- logger.trace("Adding #{other} (#{other.class}) to #{self}")
100
- case other
101
- when Numeric then DateTime.from(to_time + other)
102
- when DateTime, Time then self + other.to_f
103
- when DateTimeType, String then self + DateTime.from(other).to_f
104
- when Duration then DateTime.new(zoned_date_time.plus(other))
105
- end
106
- end
107
-
108
- #
109
- # Subtracts another object from this DateTime
110
- #
111
- # @param [Object] other Object to subtract fom this. Can be a Numeric, another DateTime/Time/DateTimeType, a
112
- # Duration or a String that can be parsed into a DateTimeType or Time object
113
- #
114
- # @return [DateTime, Float] A new DateTime object representing the result of the calculation, or a Float
115
- # representing the time difference in seconds if the subtraction is between two time objects
116
- #
117
- def -(other)
118
- logger.trace("Subtracting #{other} (#{other.class}) from self")
119
- case other
120
- when Numeric then DateTime.from(to_time - other)
121
- when String
122
- dt = DateTime.parse(other)
123
- TIME_ONLY_REGEX.match?(other) ? self - dt.to_f : time_diff(dt)
124
- when Duration then DateTime.new(zoned_date_time.minus(other))
125
- when Time, DateTime, DateTimeType, DateTimeItem then time_diff(other)
126
- end
127
- end
128
-
129
- #
130
- # Convert this DateTime to a ruby Time object
131
- #
132
- # @return [Time] A Time object representing the same instant and timezone
133
- #
134
- def to_time
135
- Time.at(to_i, nsec, :nsec).localtime(utc_offset)
136
- end
137
-
138
- #
139
- # Convert the time part of this DateTime to a TimeOfDay object
140
- #
141
- # @return [TimeOfDay] A TimeOfDay object representing the time
142
- #
143
- def to_time_of_day
144
- TimeOfDay::TimeOfDay.new(h: hour, m: minute, s: second)
145
- end
146
-
147
- alias to_tod to_time_of_day
148
-
149
- #
150
- # Returns the value of time as a floating point number of seconds since the Epoch
151
- #
152
- # @return [Float] Number of seconds since the Epoch, with nanosecond presicion
153
- #
154
- def to_f
155
- zoned_date_time.to_epoch_second + (zoned_date_time.nano / 1_000_000_000)
156
- end
157
-
158
- #
159
- # The ZonedDateTime representing the state
160
- #
161
- # @return [Java::java::time::ZonedDateTime] ZonedDateTime representing the state
162
- #
163
- def zoned_date_time
164
- @datetime.zonedDateTime
165
- end
166
-
167
- alias to_zdt zoned_date_time
168
-
169
- #
170
- # The offset in seconds from UTC
171
- #
172
- # @return [Integer] The offset from UTC, in seconds
173
- #
174
- def utc_offset
175
- zoned_date_time.offset.total_seconds
176
- end
177
-
178
- #
179
- # Returns true if time represents a time in UTC (GMT)
180
- #
181
- # @return [Boolean] true if utc_offset == 0, false otherwise
182
- #
183
- def utc?
184
- utc_offset.zero?
185
- end
186
-
187
- #
188
- # Returns an integer representing the day of the week, 0..6, with Sunday == 0.
189
- #
190
- # @return [Integer] The day of week
191
- #
192
- def wday
193
- zoned_date_time.day_of_week.value % 7
194
- end
195
-
196
- #
197
- # The timezone
198
- #
199
- # @return [String] The timezone in `[+-]hh:mm(:ss)` format ('Z' for UTC) or nil if the Item has no state
200
- #
201
- def zone
202
- zoned_date_time.zone.id
203
- end
204
-
205
- #
206
- # Check if missing method can be delegated to other contained objects
207
- #
208
- # @param [String, Symbol] meth the method name to check for
209
- #
210
- # @return [Boolean] true if DateTimeType, ZonedDateTime or Time responds to the method, false otherwise
211
- #
212
- def respond_to_missing?(meth, *)
213
- @datetime.respond_to?(meth) ||
214
- zoned_date_time.respond_to?(meth) ||
215
- Time.instance_methods.include?(meth.to_sym)
216
- end
217
-
218
- #
219
- # Forward missing methods to the OpenHAB DateTimeType, its ZonedDateTime object or a ruby Time
220
- # object representing the same instant
221
- #
222
- # @param [String] meth method name
223
- # @param [Array] args arguments for method
224
- # @param [Proc] block <description>
225
- #
226
- # @return [Object] Value from delegated method in OpenHAB NumberItem
227
- #
228
- def method_missing(meth, *args, &block)
229
- if @datetime.respond_to?(meth)
230
- @datetime.__send__(meth, *args, &block)
231
- elsif zoned_date_time.respond_to?(meth)
232
- zoned_date_time.__send__(meth, *args, &block)
233
- elsif Time.instance_methods.include?(meth.to_sym)
234
- to_time.send(meth, *args, &block)
235
- else
236
- raise NoMethodError, "undefined method `#{meth}' for #{self.class}"
237
- end
238
- end
239
-
240
- #
241
- # Converts other objects to a DateTimeType
242
- #
243
- # @param [String, Numeric, Time] datetime an object that can be parsed or converted into
244
- # a DateTimeType
245
- #
246
- # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
247
- #
248
- def self.from(datetime)
249
- case datetime
250
- when String
251
- parse(datetime)
252
- when Numeric
253
- from_numeric(datetime)
254
- when Time
255
- from_time(datetime)
256
- else
257
- raise "Cannot convert #{datetime.class} to DateTime"
258
- end
259
- end
260
-
261
- #
262
- # Converts a Numeric into a DateTimeType
263
- #
264
- # @param [Numeric] numeric A Integer or Float representing the number of seconds since the epoch
265
- #
266
- # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
267
- #
268
- def self.from_numeric(numeric)
269
- case numeric
270
- when Integer
271
- DateTime.new(ZonedDateTime.ofInstant(Instant.ofEpochSecond(datetime), ZoneId.systemDefault))
272
- else
273
- DateTime.new(ZonedDateTime.ofInstant(Instant.ofEpochSecond(datetime.to_i,
274
- ((datetime % 1) * 1_000_000_000).to_i),
275
- ZoneId.systemDefault))
276
- end
277
- end
278
-
279
- #
280
- # Converts a ruby Time object to an OpenHAB DateTimeType
281
- #
282
- # @param [Time] time The Time object to be converted
283
- #
284
- # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
285
- #
286
- def self.from_time(time)
287
- instant = Instant.ofEpochSecond(time.to_i, time.nsec)
288
- zone_id = ZoneId.of_offset('UTC', ZoneOffset.of_total_seconds(time.utc_offset))
289
- DateTime.new(ZonedDateTime.ofInstant(instant, zone_id))
290
- end
291
-
292
- #
293
- # Parses a string representing a time into an OpenHAB DateTimeType. First tries to parse it
294
- # using the DateTimeType's parser, then falls back to the ruby Time.parse
295
- #
296
- # @param [String] time_string The string to be parsed
297
- #
298
- # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
299
- #
300
- def self.parse(time_string)
301
- time_string += 'Z' if TIME_ONLY_REGEX.match?(time_string)
302
- DateTime.new(DateTimeType.new(time_string))
303
- rescue Java::JavaLang::StringIndexOutOfBoundsException, Java::JavaLang::IllegalArgumentException
304
- # Try ruby's Time.parse if OpenHAB's DateTimeType parser fails
305
- begin
306
- time = Time.parse(time_string)
307
- DateTime.from(time)
308
- rescue ArgumentError
309
- raise "Unable to parse #{time_string} into a DateTime"
310
- end
311
- end
312
-
313
- private
314
-
315
- #
316
- # Calculates the difference in time between this instance and another time object
317
- #
318
- # @param [Time, DateTime, DateTimeItem, Java::org::openhab::core::library::types::DateTimeType] time_obj
319
- # The other time object to subtract from self
320
- #
321
- # @return [Float] The time difference between the two objects, in seconds
322
- #
323
- def time_diff(time_obj)
324
- logger.trace("Calculate time difference between #{self} and #{time_obj}")
325
- case time_obj
326
- when Time
327
- to_time - time_obj
328
- when DateTime, DateTimeItem
329
- self - time_obj.to_time
330
- when DateTimeType
331
- self - DateTime.new(time_obj).to_time
332
- end
333
- end
334
- end
335
- end
336
- end
337
- end
338
- # rubocop: enable Metrics/ClassLength
@@ -1,300 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'forwardable'
5
-
6
- module OpenHAB
7
- module DSL
8
- #
9
- # Ruby implementation of OpenHAB Types
10
- #
11
- module Types
12
- #
13
- # Ruby implementation for OpenHAB quantities
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 Quantity < Numeric
19
- extend Forwardable
20
- include OpenHAB::Log
21
-
22
- def_delegator :@quantity, :to_s
23
- def_delegators '@quantity.double_value', :positive?, :negative?, :zero?
24
-
25
- java_import org.openhab.core.library.types.QuantityType
26
- java_import org.openhab.core.library.types.DecimalType
27
- java_import org.openhab.core.types.util.UnitUtils
28
- java_import org.openhab.core.library.unit.Units
29
-
30
- # @return [Hash] Mapping of operation symbols to BigDecimal methods
31
- OPERATIONS = {
32
- '+' => 'add',
33
- '-' => 'subtract',
34
- '*' => 'multiply',
35
- '/' => 'divide'
36
- }.freeze
37
-
38
- private_constant :OPERATIONS
39
-
40
- attr_reader :quantity
41
-
42
- #
43
- # Create a new Quantity
44
- #
45
- # @param [object] quantity String,QuantityType or Numeric to be this quantity
46
- #
47
- # Cop disabled, case statement is compact and idiomatic
48
- def initialize(quantity)
49
- @quantity = case quantity
50
- when String then QuantityType.new(quantity)
51
- when QuantityType then quantity
52
- when NumberItem, Numeric then QuantityType.new(quantity.to_d.to_java, Units::ONE)
53
- else raise ArgumentError, "Unexpected type #{quantity.class} provided to Quantity initializer"
54
- end
55
- super()
56
- end
57
-
58
- #
59
- # Convert this quantity into a another unit
60
- #
61
- # @param [Object] other String or Unit to convert to
62
- #
63
- # @return [Quantity] This quantity converted to another unit
64
- #
65
- def |(other)
66
- other = UnitUtils.parse_unit(other) if other.is_a? String
67
-
68
- Quantity.new(quantity.to_unit(other))
69
- end
70
-
71
- #
72
- # Compare this quantity
73
- #
74
- # @param [Object] other object to compare to
75
- #
76
- # @return [Integer] -1,0,1 if this object is less than, equal to, or greater than the supplied object,
77
- # nil if it cannot be compared
78
- #
79
- def <=>(other)
80
- logger.trace("Comparing #{self} to #{other}")
81
- my_qt, other_qt = unitize(*to_qt(coerce(other).reverse))
82
- my_qt.compare_to(other_qt)
83
- end
84
-
85
- #
86
- # Coerce other object into a Quantity
87
- #
88
- # @param [Object] other object to convert to Quantity
89
- #
90
- # @return [Array] of self and other object as Quantity types, nil if object cannot be coerced
91
- #
92
- def coerce(other)
93
- logger.trace("Coercing #{self} as a request from #{other.class}")
94
- case other
95
- when Quantity then [other.quantity, quantity]
96
- when QuantityType then [other, quantity]
97
- when DecimalType then [Quantity.new(other.to_big_decimal.to_d), quantity]
98
- when NumberItem then [other.to_qt.quantity, quantity]
99
- when Numeric, String then [Quantity.new(other), self]
100
- end
101
- end
102
-
103
- #
104
- # Forward missing methods to Openhab Quantity Item if they are defined
105
- #
106
- # @param [String] meth name of method invoked
107
- # @param [Array] args arguments to invoked method
108
- # @param [Proc] block block passed ot method
109
- #
110
- # @return [Object] result of delegation
111
- #
112
- def method_missing(meth, *args, &block)
113
- logger.trace("Method missing, performing dynamic lookup for: #{meth}")
114
- if quantity.respond_to?(meth)
115
- quantity.__send__(meth, *args, &block)
116
- elsif ::Kernel.method_defined?(meth) || ::Kernel.private_method_defined?(meth)
117
- ::Kernel.instance_method(meth).bind_call(self, *args, &block)
118
- else
119
- super(meth, *args, &block)
120
- end
121
- end
122
-
123
- #
124
- # Checks if this method responds to the missing method
125
- #
126
- # @param [String] method_name Name of the method to check
127
- # @param [Boolean] _include_private boolean if private methods should be checked
128
- #
129
- # @return [Boolean] true if this object will respond to the supplied method, false otherwise
130
- #
131
- def respond_to_missing?(method_name, _include_private = false)
132
- quantity.respond_to?(method_name) ||
133
- ::Kernel.method_defined?(method_name) ||
134
- ::Kernel.private_method_defined?(method_name)
135
- end
136
-
137
- #
138
- # Negate the quantity
139
- #
140
- # @return [Quantity] This quantity negated
141
- #
142
- def -@
143
- Quantity.new(quantity.negate)
144
- end
145
-
146
- OPERATIONS.each do |operation, method|
147
- define_method(operation) do |other|
148
- logger.trace do
149
- "Executing math operation '#{operation}' on quantity #{inspect} "\
150
- "with other type #{other.class} and value #{other.inspect}"
151
- end
152
-
153
- a, b = to_qt(coerce(other).reverse)
154
- logger.trace("Coerced a='#{a}' with b='#{b}'")
155
- a, b = unitize(a, b, operation)
156
- logger.trace("Unitized a='#{a}' b='#{b}'")
157
- logger.trace("Performing operation '#{operation}' with method '#{method}' on a='#{a}' with b='#{b}'")
158
- Quantity.new(a.public_send(method, b))
159
- end
160
- end
161
-
162
- #
163
- # Provide details about quantity object
164
- #
165
- # @return [String] Representing details about the quantity object
166
- #
167
- def inspect
168
- if @quantity.unit == Units::ONE
169
- "unit=#{@quantity.unit}, value=#{@quantity.to_string}"
170
- else
171
- @quantity.to_string
172
- end
173
- end
174
-
175
- private
176
-
177
- # @return [Array] Array of strings for operations for which the operands will not be unitized
178
- DIMENSIONLESS_NON_UNITIZED_OPERATIONS = %w[* /].freeze
179
-
180
- # Dimensionless numbers should only be unitzed for addition and subtraction
181
-
182
- #
183
- # Convert one or more Quantity obects to the underlying quantitytypes
184
- #
185
- # @param [Array] quanities Array of either Quantity or QuantityType objects
186
- #
187
- # @return [Array] Array of QuantityType objects
188
- #
189
- def to_qt(*quantities)
190
- [quantities].flatten.compact.map { |item| item.is_a?(Quantity) ? item.quantity : item }
191
- end
192
-
193
- #
194
- # Checks if an item should be unitized
195
- #
196
- # @param [Quantity] quantity to check
197
- # @param [String] operation quantity is being used with
198
- #
199
- # @return [Boolean] True if the quantity should be unitzed based on the unit and operation, false otherwise
200
- #
201
- def unitize?(quantity, operation)
202
- !(quantity.unit == Units::ONE && DIMENSIONLESS_NON_UNITIZED_OPERATIONS.include?(operation))
203
- end
204
-
205
- #
206
- # Convert the unit for the quantity
207
- #
208
- # @param [Quantity] quantity being converted
209
- #
210
- # @return [Quantity] Quantity coverted to unit set by unit block
211
- #
212
- def convert_unit(quantity)
213
- return quantity unless unit?
214
-
215
- case quantity.unit
216
- when unit
217
- quantity
218
- when Units::ONE
219
- convert_unit_from_dimensionless(quantity, unit)
220
- else
221
- convert_unit_from_dimensioned(quantity, unit)
222
- end
223
- end
224
-
225
- #
226
- # Converts a dimensioned quantity to a specific unit
227
- #
228
- # @param [Quantity] quantity to convert
229
- # @param [Unit] unit to convert to
230
- #
231
- # @return [Java::org::openhab::core::library::types::QuantityType] converted quantity
232
- #
233
- def convert_unit_from_dimensioned(quantity, unit)
234
- logger.trace("Converting dimensioned item #{inspect} to #{unit}")
235
- quantity.to_unit(unit).tap do |converted|
236
- raise "Conversion from #{quantity.unit} to #{unit} failed" unless converted
237
- end
238
- end
239
-
240
- #
241
- # Converts a dimensionless quantity to a unit
242
- #
243
- # @param [Quantity] quantity to convert
244
- # @param [Unit] unit to convert to
245
- #
246
- # @return [Java::org::openhab::core::library::types::QuantityType] converted quantity
247
- #
248
- def convert_unit_from_dimensionless(quantity, unit)
249
- logger.trace("Converting dimensionless #{quantity} to #{unit}")
250
- QuantityType.new(quantity.to_big_decimal, unit)
251
- end
252
-
253
- #
254
- # Convert quantities to appropriate units
255
- #
256
- # @param [Quantity] quantity_a Quantity on left side of operation
257
- # @param [Quantity] quantity_b Quantity on right side of operation
258
- # @param [String] operation Math operation
259
- # @yield [quantity_a, quantity_b] yields unitized versions of supplied quantities
260
- #
261
- # @return [Array, Object] of quantites in correct units for the supplied operation and the unit
262
- # or the result of the block if a block is given
263
- #
264
- def unitize(quantity_a, quantity_b, operation = nil)
265
- logger.trace("Unitizing (#{quantity_a}) and (#{quantity_b})")
266
- quantity_a, quantity_b = [quantity_a, quantity_b].map do |qt|
267
- unitize?(qt, operation) ? convert_unit(qt) : qt.to_big_decimal
268
- end
269
-
270
- # Make sure the operation is called on the QuantityType
271
- if quantity_a.is_a?(Java::JavaMath::BigDecimal) && quantity_b.is_a?(QuantityType) && operation == '*'
272
- quantity_a, quantity_b = [quantity_b, quantity_a]
273
- end
274
- return yield quantity_a, quantity_b if block_given?
275
-
276
- [quantity_a, quantity_b]
277
- end
278
-
279
- #
280
- # Get the unit from the current thread local variable
281
- #
282
- # @return [Object] Unit or string representation of Unit, or nil if not set
283
- #
284
- def unit
285
- Thread.current.thread_variable_get(:unit)
286
- end
287
-
288
- #
289
- # Is a unit set for this thread
290
- #
291
- # @return [boolean] true if a unit is set by this thread, false otherwise
292
- #
293
- def unit?
294
- unit != nil
295
- end
296
- end
297
- end
298
- end
299
- end
300
- # rubocop: enable Metrics/ClassLength