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.
- checksums.yaml +4 -4
- data/lib/openhab/core/entity_lookup.rb +1 -57
- data/lib/openhab/dsl/dsl.rb +6 -12
- data/lib/openhab/dsl/group.rb +1 -5
- data/lib/openhab/dsl/items/comparable_item.rb +49 -0
- data/lib/openhab/dsl/items/contact_item.rb +41 -0
- data/lib/openhab/dsl/items/date_time_item.rb +64 -0
- data/lib/openhab/dsl/items/dimmer_item.rb +59 -0
- data/lib/openhab/dsl/items/generic_item.rb +197 -0
- data/lib/openhab/dsl/items/group_item.rb +56 -92
- data/lib/openhab/dsl/items/image_item.rb +5 -41
- data/lib/openhab/dsl/items/item_registry.rb +49 -0
- data/lib/openhab/dsl/items/items.rb +71 -35
- data/lib/openhab/dsl/items/metadata.rb +325 -0
- data/lib/openhab/dsl/items/number_item.rb +6 -312
- data/lib/openhab/dsl/items/numeric_item.rb +66 -0
- data/lib/openhab/dsl/items/persistence.rb +122 -0
- data/lib/openhab/dsl/items/player_item.rb +49 -40
- data/lib/openhab/dsl/items/rollershutter_item.rb +25 -77
- data/lib/openhab/dsl/items/string_item.rb +16 -58
- data/lib/openhab/dsl/items/switch_item.rb +62 -0
- data/lib/openhab/dsl/lazy_array.rb +8 -6
- data/lib/openhab/dsl/monkey_patch/events/events.rb +2 -2
- data/lib/openhab/dsl/monkey_patch/events/item_command.rb +67 -24
- data/lib/openhab/dsl/monkey_patch/events/item_event.rb +5 -5
- data/lib/openhab/dsl/monkey_patch/events/item_state.rb +10 -11
- data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +10 -11
- data/lib/openhab/dsl/monkey_patch/ruby/number.rb +25 -2
- data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -3
- data/lib/openhab/dsl/monkey_patch/ruby/string.rb +24 -24
- data/lib/openhab/dsl/states.rb +1 -1
- data/lib/openhab/dsl/time_of_day.rb +3 -5
- data/lib/openhab/dsl/types/comparable_type.rb +21 -0
- data/lib/openhab/dsl/types/date_time_type.rb +334 -0
- data/lib/openhab/dsl/types/decimal_type.rb +187 -0
- data/lib/openhab/dsl/types/increase_decrease_type.rb +23 -0
- data/lib/openhab/dsl/types/next_previous_type.rb +23 -0
- data/lib/openhab/dsl/types/numeric_type.rb +39 -0
- data/lib/openhab/dsl/types/on_off_type.rb +29 -0
- data/lib/openhab/dsl/types/open_closed_type.rb +29 -0
- data/lib/openhab/dsl/types/percent_type.rb +68 -0
- data/lib/openhab/dsl/types/play_pause_type.rb +27 -0
- data/lib/openhab/dsl/types/quantity_type.rb +275 -0
- data/lib/openhab/dsl/types/refresh_type.rb +18 -0
- data/lib/openhab/dsl/types/rewind_fastforward_type.rb +33 -0
- data/lib/openhab/dsl/types/stop_move_type.rb +23 -0
- data/lib/openhab/dsl/types/string_type.rb +88 -0
- data/lib/openhab/dsl/types/type.rb +72 -0
- data/lib/openhab/dsl/types/types.rb +77 -0
- data/lib/openhab/dsl/types/un_def_type.rb +22 -0
- data/lib/openhab/dsl/types/up_down_type.rb +32 -0
- data/lib/openhab/dsl/units.rb +11 -6
- data/lib/openhab/version.rb +1 -1
- data/lib/openhab.rb +0 -1
- metadata +31 -28
- data/lib/openhab/dsl/items/datetime_item.rb +0 -75
- data/lib/openhab/dsl/items/item_command.rb +0 -90
- data/lib/openhab/dsl/items/item_delegate.rb +0 -125
- data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +0 -51
- data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +0 -140
- data/lib/openhab/dsl/monkey_patch/items/items.rb +0 -142
- data/lib/openhab/dsl/monkey_patch/items/metadata.rb +0 -328
- data/lib/openhab/dsl/monkey_patch/items/persistence.rb +0 -123
- data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +0 -71
- data/lib/openhab/dsl/monkey_patch/ruby/range.rb +0 -47
- data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -32
- data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +0 -97
- data/lib/openhab/dsl/monkey_patch/types/increase_decrease_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/next_previous_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +0 -79
- data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +0 -71
- data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +0 -77
- data/lib/openhab/dsl/monkey_patch/types/play_pause_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +0 -69
- data/lib/openhab/dsl/monkey_patch/types/refresh_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/rewind_fastforward_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/stop_move_type.rb +0 -23
- data/lib/openhab/dsl/monkey_patch/types/types.rb +0 -15
- data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +0 -72
- data/lib/openhab/dsl/types/datetime.rb +0 -338
- 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 '
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|