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
@@ -0,0 +1,275 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'numeric_type'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Types
8
+ java_import org.openhab.core.library.types.QuantityType
9
+
10
+ # global alias
11
+ ::QuantityType = QuantityType
12
+
13
+ # @deprecated
14
+ # Backwards-compatible alias
15
+ Quantity = QuantityType
16
+
17
+ # Adds methods to core OpenHAB QuantityType to make it more natural in Ruby
18
+ class QuantityType # rubocop:disable Metrics/ClassLength
19
+ # @!parse include Type
20
+ include NumericType
21
+
22
+ # private alias
23
+ ONE = org.openhab.core.library.unit.Units::ONE
24
+ private_constant :ONE
25
+
26
+ #
27
+ # Convert this quantity into a another unit
28
+ #
29
+ # @param [Object] other String or Unit to convert to
30
+ #
31
+ # @return [QuantityType] This quantity converted to another unit
32
+ #
33
+ def |(other)
34
+ other = org.openhab.core.types.util.UnitUtils.parse_unit(other) if other.is_a?(String)
35
+
36
+ to_unit(other)
37
+ end
38
+
39
+ #
40
+ # Comparison
41
+ #
42
+ # @param [NumericType, Items::NumericItem, Numeric, String]
43
+ # other object to compare to
44
+ #
45
+ # @return [Integer, nil] -1, 0, +1 depending on whether +other+ is
46
+ # less than, equal to, or greater than self
47
+ #
48
+ # nil is returned if the two values are incomparable
49
+ #
50
+ def <=>(other) # rubocop:disable Metrics
51
+ logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
52
+ if other.is_a?(self.class)
53
+ compare_to(other)
54
+ elsif other.is_a?(Items::NumericItem) ||
55
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(NumericItem))
56
+ return nil unless other.state?
57
+
58
+ self <=> other.state
59
+ elsif other.respond_to?(:to_str)
60
+ compare_to(QuantityType.new(other.to_str))
61
+ elsif other.respond_to?(:to_d)
62
+ compare_to(QuantityType.new(other.to_d.to_java, Units.unit || unit))
63
+ elsif other.respond_to?(:coerce)
64
+ lhs, rhs = other.coerce(self)
65
+ lhs <=> rhs
66
+ end
67
+ end
68
+
69
+ #
70
+ # Type Coercion
71
+ #
72
+ # Coerce object to a QuantityType
73
+ #
74
+ # @param [Items::NumericItem, Numeric, Type, String] other object to
75
+ # coerce to a {QuantityType}
76
+ #
77
+ # if +other+ is a {Type}, +self+ will instead be coerced
78
+ # to that type to accomodate comparison with things such as {OnOffType}
79
+ #
80
+ # @return [[QuantityType, QuantityType]]
81
+ def coerce(other) # rubocop:disable Metrics
82
+ logger.trace("Coercing #{self} as a request from #{other.class}")
83
+ if other.is_a?(Items::NumericItem) ||
84
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
85
+ raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
86
+
87
+ [other.state, self]
88
+ elsif other.is_a?(Type)
89
+ [other, as(other.class)]
90
+ elsif other.respond_to?(:to_d)
91
+ [QuantityType.new(other.to_d.to_java, ONE), self]
92
+ elsif other.is_a?(String)
93
+ [QuantityType.new(other), self]
94
+ else
95
+ raise TypeError, "can't convert #{other.class} into #{self.class}"
96
+ end
97
+ end
98
+
99
+ # arithmetic operators
100
+ alias -@ negate
101
+
102
+ {
103
+ :add => :+,
104
+ :subtract => :-
105
+ }.each do |java_op, ruby_op|
106
+ convert = 'self.class.new(other, Units.unit || unit)'
107
+
108
+ class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
109
+ # def +(other)
110
+ # logger.trace("#{self} + #{other} (#{other.class})")
111
+ # if other.is_a?(Items::NumericItem) ||
112
+ # (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
113
+ # self + other.state
114
+ # elsif other.is_a?(QuantityType)
115
+ # add_quantity(other)
116
+ # elsif other.is_a?(DecimalType)
117
+ # other = other.to_big_decimal
118
+ # add_quantity(self.class.new(other, Units.unit || unit))
119
+ # elsif other.is_a?(java.math.BigDecimal)
120
+ # add_quantity(self.class.new(other, Units.unit || unit))
121
+ # elsif other.respond_to?(:to_str)
122
+ # self + self.class.new(other)
123
+ # elsif other.respond_to?(:to_d)
124
+ # other = other.to_d.to_java
125
+ # add_quantity(self.class.new(other, Units.unit || unit))
126
+ # elsif other.respond_to?(:coerce)
127
+ # lhs, rhs = other.coerce(to_d)
128
+ # lhs = rhs
129
+ # else
130
+ # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
131
+ # end
132
+ # end
133
+ <<~RUBY, __FILE__, __LINE__ + 1
134
+ def #{ruby_op}(other)
135
+ logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
136
+ if other.is_a?(Items::NumericItem) ||
137
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
138
+ self #{ruby_op} other.state
139
+ elsif other.is_a?(QuantityType)
140
+ #{java_op}_quantity(other)
141
+ elsif other.is_a?(DecimalType)
142
+ other = other.to_big_decimal
143
+ #{java_op}_quantity(#{convert})
144
+ elsif other.is_a?(java.math.BigDecimal)
145
+ #{java_op}_quantity(#{convert})
146
+ elsif other.respond_to?(:to_str)
147
+ self #{ruby_op} self.class.new(other)
148
+ elsif other.respond_to?(:to_d)
149
+ other = other.to_d.to_java
150
+ #{java_op}_quantity(#{convert})
151
+ elsif other.respond_to?(:coerce)
152
+ lhs, rhs = other.coerce(to_d)
153
+ lhs #{ruby_op} rhs
154
+ else
155
+ raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
156
+ end
157
+ end
158
+ RUBY
159
+ )
160
+ end
161
+
162
+ {
163
+ :multiply => :*,
164
+ :divide => :/
165
+ }.each do |java_op, ruby_op|
166
+ class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
167
+ # def *(other)
168
+ # logger.trace("#{self} * #{other} (#{other.class})")
169
+ # if other.is_a?(Items::NumericItem) ||
170
+ # (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
171
+ # self * other.state
172
+ # elsif other.is_a?(QuantityType)
173
+ # multiply_quantity(other)
174
+ # elsif other.is_a?(DecimalType)
175
+ # multiply(other.to_big_decimal)
176
+ # elsif other.is_a?(java.math.BigDecimal)
177
+ # multiply(other)
178
+ # elsif other.respond_to?(:to_str)
179
+ # self * self.class.new(other)
180
+ # elsif other.respond_to?(:to_d)
181
+ # multiply(other.to_d.to_java)
182
+ # elsif other.respond_to?(:coerce)
183
+ # lhs, rhs = other.coerce(to_d)
184
+ # lhs * rhs
185
+ # else
186
+ # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
187
+ # end
188
+ # end
189
+ <<~RUBY, __FILE__, __LINE__ + 1
190
+ def #{ruby_op}(other)
191
+ logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
192
+ if other.is_a?(Items::NumericItem) ||
193
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
194
+ self #{ruby_op} other.state
195
+ elsif other.is_a?(QuantityType)
196
+ #{java_op}_quantity(other)
197
+ elsif other.is_a?(DecimalType)
198
+ #{java_op}(other.to_big_decimal)
199
+ elsif other.is_a?(java.math.BigDecimal)
200
+ #{java_op}(other)
201
+ elsif other.respond_to?(:to_str)
202
+ self #{ruby_op} self.class.new(other)
203
+ elsif other.respond_to?(:to_d)
204
+ #{java_op}(other.to_d.to_java)
205
+ elsif other.respond_to?(:coerce)
206
+ lhs, rhs = other.coerce(to_d)
207
+ lhs #{ruby_op} rhs
208
+ else
209
+ raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
210
+ end
211
+ end
212
+ RUBY
213
+ )
214
+ end
215
+
216
+ # if it's a dimensionless quantity, change the unit to match other_unit
217
+ # @!visibility private
218
+ def unitize(other_unit = unit)
219
+ # prefer converting to the thread-specified unit if there is one
220
+ other_unit = Units.unit || other_unit
221
+ logger.trace("Converting #{self} to #{other_unit}")
222
+
223
+ case unit
224
+ when ONE
225
+ QuantityType.new(to_big_decimal, other_unit)
226
+ when other_unit
227
+ self
228
+ else
229
+ to_unit(other_unit)
230
+ end
231
+ end
232
+
233
+ # if unit is +ONE+, return a plain Java BigDecimal
234
+ # @!visibility private
235
+ def deunitize
236
+ return to_big_decimal if unit == ONE
237
+
238
+ self
239
+ end
240
+
241
+ private
242
+
243
+ # do addition directly against a QuantityType while ensuring we unitize
244
+ # both sides
245
+ def add_quantity(other)
246
+ unitize(other.unit).add(other.unitize(unit))
247
+ end
248
+
249
+ # do subtraction directly against a QuantityType while ensuring we
250
+ # unitize both sides
251
+ def subtract_quantity(other)
252
+ unitize(other.unit).subtract(other.unitize(unit))
253
+ end
254
+
255
+ # do multiplication directly against a QuantityType while ensuring
256
+ # we deunitize both sides, and also invert the operation if one side
257
+ # isn't actually a unit
258
+ def multiply_quantity(other)
259
+ lhs = deunitize
260
+ rhs = other.deunitize
261
+ # reverse the arguments if it's multiplication and the LHS isn't a QuantityType
262
+ lhs, rhs = rhs, lhs if lhs.is_a?(java.math.BigDecimal)
263
+ # what a waste... using a QuantityType to multiply two dimensionless quantities
264
+ # have to make sure lhs is still a QuantityType in order to return a new
265
+ # QuantityType that's still dimensionless
266
+ lhs = other if lhs.is_a?(java.math.BigDecimal)
267
+
268
+ lhs.multiply(rhs)
269
+ end
270
+
271
+ alias divide_quantity divide
272
+ end
273
+ end
274
+ end
275
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.types.RefreshType
7
+
8
+ # Adds methods to core OpenHAB RefreshType to make it more natural in Ruby
9
+ class RefreshType # rubocop:disable Lint/EmptyClass
10
+ # @!parse include Type
11
+
12
+ # @!method refresh?
13
+ # Check if == +REFRESH+
14
+ # @return [Boolean]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.library.types.RewindFastforwardType
7
+
8
+ # Adds methods to core OpenHAB RewindFastforwardType to make it more
9
+ # natural in Ruby
10
+ class RewindFastforwardType # rubocop:disable Lint/EmptyClass
11
+ # @!parse include Type
12
+
13
+ # @!method rewinding?
14
+ # Check if == +REWIND+
15
+ # @return [Boolean]
16
+
17
+ # @!parse alias rewind? rewinding?
18
+
19
+ # @!method fast_forwarding?
20
+ # Check if == +FASTFORWARD+
21
+ # @return [Boolean]
22
+
23
+ # @!parse alias fast_forward? fast_forwarding?
24
+
25
+ # @deprecated
26
+ # @!parse alias fastforward? fast_forwarding?
27
+
28
+ # @deprecated
29
+ # @!parse alias fastforwarding? fast_forwarding?
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.library.types.StopMoveType
7
+
8
+ # Adds methods to core OpenHAB StopMoveType to make it more
9
+ # natural in Ruby
10
+ class StopMoveType # rubocop:disable Lint/EmptyClass
11
+ # @!parse include Type
12
+
13
+ # @!method stop?
14
+ # Check if == +STOP+
15
+ # @return [Boolean]
16
+
17
+ # @!method move?
18
+ # Check if == +MOVE+
19
+ # @return [Boolean]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ require_relative 'comparable_type'
6
+
7
+ module OpenHAB
8
+ module DSL
9
+ module Types
10
+ java_import org.openhab.core.library.types.StringType
11
+
12
+ #
13
+ # Add methods to core OpenHAB StringType to make it behave as a Ruby
14
+ # String object
15
+ #
16
+ class StringType
17
+ # @!parse include Type
18
+
19
+ extend Forwardable
20
+ include Comparable
21
+ include ComparableType
22
+
23
+ #
24
+ # Check equality without type conversion
25
+ #
26
+ # @return [Boolean] if the same value is represented, without type
27
+ # conversion
28
+ def eql?(other)
29
+ return false unless other.instance_of?(self.class)
30
+
31
+ to_s.compare_to(other.to_s).zero?
32
+ end
33
+
34
+ #
35
+ # Comparison
36
+ #
37
+ # @param [StringType, Items::StringItem, String]
38
+ # other object to compare to
39
+ #
40
+ # @return [Integer, nil] -1, 0, +1 depending on whether +other+ is
41
+ # less than, equal to, or greater than self
42
+ #
43
+ # nil is returned if the two values are incomparable
44
+ #
45
+ def <=>(other) # rubocop:disable Metrics
46
+ logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
47
+ if other.is_a?(Items::StringItem) ||
48
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(StringItem))
49
+ return nil unless other.state?
50
+
51
+ self <=> other.state
52
+ elsif other.respond_to?(:to_str)
53
+ to_str <=> other.to_str
54
+ elsif other.respond_to?(:coerce)
55
+ lhs, rhs = other.coerce(self)
56
+ lhs <=> rhs
57
+ end
58
+ end
59
+
60
+ #
61
+ # Type Coercion
62
+ #
63
+ # Coerce object to a StringType
64
+ #
65
+ # @param [Items::StringItem, String] other object to coerce to a
66
+ # DateTimeType
67
+ #
68
+ # @return [[StringType, StringType]]
69
+ #
70
+ def coerce(other)
71
+ logger.trace("Coercing #{self} as a request from #{other.class}")
72
+ if other.is_a?(Items::StringItem)
73
+ raise TypeError, "can't convert #{other.raw_state} into #{self.class}" unless other.state?
74
+
75
+ [other.state, self]
76
+ elsif other.respond_to?(:to_str)
77
+ [String.new(other.to_str), self]
78
+ else
79
+ raise TypeError, "can't convert #{other.class} into #{self.class}"
80
+ end
81
+ end
82
+
83
+ # any method that exists on String gets forwarded to to_s
84
+ delegate (String.instance_methods - instance_methods) => :to_s
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.types.Type
7
+
8
+ #
9
+ # Add basic type conversion and comparison to all core OpenHAB types
10
+ #
11
+ module Type
12
+ # can't alias because to_s doesn't exist on Type
13
+ # @!visibility private
14
+ def inspect
15
+ to_s
16
+ end
17
+
18
+ #
19
+ # Type Coercion
20
+ #
21
+ # Coerce object to the same Type
22
+ #
23
+ # @param [Type] other object to coerce to the same
24
+ # Type as this one
25
+ #
26
+ # @return [[Type, Type]]
27
+ #
28
+ def coerce(other)
29
+ logger.trace("Coercing #{self} (#{self.class}) as a request from #{other.class}")
30
+ return [other.as(self.class), self] if other.is_a?(Type)
31
+
32
+ raise TypeError, "can't convert #{other.class} into #{self.class}"
33
+ end
34
+
35
+ #
36
+ # Check equality without type conversion
37
+ #
38
+ # @return [Boolean] if the same value is represented, without type
39
+ # conversion
40
+ def eql?(other)
41
+ return false unless other.instance_of?(self.class)
42
+
43
+ equals(other)
44
+ end
45
+
46
+ #
47
+ # Check equality, including type conversion
48
+ #
49
+ # @return [Boolean] if the same value is represented, including
50
+ # type conversions
51
+ #
52
+ def ==(other)
53
+ return true if equal?(other)
54
+
55
+ # i.e. ON == OFF, REFRESH == ON, ON == REFRESH
56
+ # (RefreshType isn't really coercible)
57
+ return equals(other) if other.instance_of?(self.class) || is_a?(RefreshType) || other.is_a?(RefreshType)
58
+
59
+ # i.e. ON == DimmerItem (also case statements)
60
+ return self == other.raw_state if other.is_a?(Items::GenericItem)
61
+
62
+ if other.respond_to?(:coerce)
63
+ lhs, rhs = other.coerce(self)
64
+ return lhs == rhs
65
+ end
66
+
67
+ super
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'type'
4
+
5
+ require_relative 'date_time_type'
6
+ require_relative 'decimal_type'
7
+ require_relative 'hsb_type'
8
+ require_relative 'increase_decrease_type'
9
+ require_relative 'next_previous_type'
10
+ require_relative 'open_closed_type'
11
+ require_relative 'on_off_type'
12
+ require_relative 'percent_type'
13
+ require_relative 'play_pause_type'
14
+ require_relative 'quantity_type'
15
+ require_relative 'refresh_type'
16
+ require_relative 'rewind_fastforward_type'
17
+ require_relative 'stop_move_type'
18
+ require_relative 'string_type'
19
+ require_relative 'up_down_type'
20
+ require_relative 'un_def_type'
21
+
22
+ module OpenHAB
23
+ module DSL
24
+ #
25
+ # Contains all OpenHAB *Type classes, as well as associated support
26
+ # modules
27
+ #
28
+ module Types
29
+ # Hash taking a Enum value, and returning two symbols of
30
+ # predicates to be defined for it. the first is the "command" form,
31
+ # which should be defined on ItemCommandEvent, and on the Type itself.
32
+ # the second is "state" form, which should be defined on the applicable
33
+ # Item, and on the Type itself.
34
+ # @!visibility private
35
+ PREDICATE_ALIASES = Hash.new { |_h, k| [:"#{k.downcase}?"] * 2 }
36
+ .merge({
37
+ 'PLAY' => %i[play? playing?],
38
+ 'PAUSE' => %i[pause? paused?],
39
+ 'REWIND' => %i[rewind? rewinding?],
40
+ 'FASTFORWARD' => %i[fast_forward? fast_forwarding?]
41
+ }).freeze
42
+
43
+ # Hash taking a Enum value, and returning an array of symbols
44
+ # of the command to define for it
45
+ # @!visibility private
46
+ COMMAND_ALIASES = Hash.new { |_h, k| k.downcase.to_sym }
47
+ .merge({
48
+ 'FASTFORWARD' => :fast_forward
49
+ }).freeze
50
+
51
+ constants.map { |c| const_get(c) }
52
+ .grep(Module)
53
+ .select { |k| k < java.lang.Enum }
54
+ .each do |klass|
55
+ # make sure == from Type is inherited
56
+ klass.remove_method(:==)
57
+
58
+ # dynamically define predicate methods
59
+ klass.values.each do |value| # rubocop:disable Style/HashEachMethods this isn't a Ruby hash
60
+ # include all the aliases that we define for items both command and
61
+ # state aliases (since types can be interrogated as an incoming
62
+ # command, or as the state of an item)
63
+ command = :"#{COMMAND_ALIASES[value.to_s]}?"
64
+ states = PREDICATE_ALIASES[value.to_s]
65
+
66
+ ([command] | states).each do |method|
67
+ OpenHAB::Core.logger.trace("Defining #{klass}##{method} for #{value}")
68
+ klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
69
+ def #{method} # def on?
70
+ self == #{value} # self == ON
71
+ end # end
72
+ RUBY
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.types.UnDefType
7
+
8
+ # Adds methods to core OpenHAB UnDefType to make it more natural in Ruby
9
+ class UnDefType # rubocop:disable Lint/EmptyClass
10
+ # @!parse include Type
11
+
12
+ # @!method null?
13
+ # Check if == +NULL+
14
+ # @return [Boolean]
15
+
16
+ # @!method undef?
17
+ # Check if == +UNDEF+
18
+ # @return [Boolean]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.library.types.UpDownType
7
+
8
+ # Adds methods to core OpenHAB UpDownType to make it more natural in Ruby
9
+ class UpDownType
10
+ # @!parse include Type
11
+
12
+ # @!method up?
13
+ # Check if == +UP+
14
+ # @return [Boolean]
15
+
16
+ # @!method down?
17
+ # Check if == +DOWN+
18
+ # @return [Boolean]
19
+
20
+ #
21
+ # Invert the type
22
+ #
23
+ # @return [UpDownType] +UP+ if +DOWN+, +DOWN+ if +UP+
24
+ #
25
+ def !
26
+ return UP if down?
27
+ return DOWN if up?
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -10,7 +10,6 @@ end
10
10
 
11
11
  Object.send(:remove_const, :QuantityType)
12
12
  java_import org.openhab.core.library.types.QuantityType
13
- java_import org.openhab.core.types.util.UnitUtils
14
13
 
15
14
  module OpenHAB
16
15
  module DSL
@@ -18,6 +17,13 @@ module OpenHAB
18
17
  # Provides support for interacting with OpenHAB Units of Measurement
19
18
  #
20
19
  module Units
20
+ # @return The default unit for the current thread
21
+ def unit(unit = nil, &block)
22
+ return with_unit(unit, &block) if unit || block # back-compat
23
+
24
+ Thread.current[:unit]
25
+ end
26
+
21
27
  #
22
28
  # Sets a thread local variable to the supplied unit such that classes operating inside the block
23
29
  # can perform automatic conversions to the supplied unit for NumberItems
@@ -25,13 +31,12 @@ module OpenHAB
25
31
  # @param [Object] unit OpenHAB Unit or String representing unit
26
32
  # @yield [] Block executed in context of the supplied unit
27
33
  #
28
- #
29
- def unit(unit)
30
- unit = UnitUtils.parse_unit(unit) if unit.is_a? String
31
- Thread.current.thread_variable_set(:unit, unit)
34
+ def with_unit(unit)
35
+ unit = org.openhab.core.types.util.UnitUtils.parse_unit(unit) if unit.is_a? String
36
+ Thread.current[:unit] = unit
32
37
  yield
33
38
  ensure
34
- Thread.current.thread_variable_set(:unit, nil)
39
+ Thread.current[:unit] = nil
35
40
  end
36
41
  end
37
42
  end
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.1.4'
8
+ VERSION = '4.5.0'
9
9
  end