openhab-scripting 5.4.2 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/configuration.rb +70 -0
  3. data/lib/openhab/core/emulate_hash.rb +241 -0
  4. data/lib/openhab/core/events/abstract_event.rb +11 -0
  5. data/lib/openhab/core/events/timer_event.rb +48 -0
  6. data/lib/openhab/core/items/group_function.rb +37 -0
  7. data/lib/openhab/core/items/group_item.rb +10 -4
  8. data/lib/openhab/core/items/item.rb +31 -0
  9. data/lib/openhab/core/items/metadata/hash.rb +9 -179
  10. data/lib/openhab/core/items/metadata/namespace_hash.rb +38 -141
  11. data/lib/openhab/core/items/persistence.rb +45 -12
  12. data/lib/openhab/core/items/semantics/semantic_tag.rb +5 -0
  13. data/lib/openhab/core/items/semantics/tag_class_methods.rb +9 -0
  14. data/lib/openhab/core/items/semantics.rb +3 -1
  15. data/lib/openhab/core/rules/rule.rb +17 -4
  16. data/lib/openhab/core/things/links/provider.rb +1 -1
  17. data/lib/openhab/core/things/thing.rb +23 -0
  18. data/lib/openhab/core/value_cache.rb +1 -1
  19. data/lib/openhab/dsl/items/builder.rb +10 -5
  20. data/lib/openhab/dsl/rules/automation_rule.rb +29 -5
  21. data/lib/openhab/dsl/rules/builder.rb +0 -3
  22. data/lib/openhab/dsl/rules/rule_triggers.rb +1 -1
  23. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +2 -1
  24. data/lib/openhab/dsl/rules/triggers/conditions/generic.rb +7 -0
  25. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +10 -2
  26. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +101 -96
  27. data/lib/openhab/dsl/things/builder.rb +4 -4
  28. data/lib/openhab/dsl/thread_local.rb +1 -0
  29. data/lib/openhab/dsl/timer_manager.rb +4 -4
  30. data/lib/openhab/dsl/version.rb +1 -1
  31. data/lib/openhab/dsl.rb +23 -4
  32. data/lib/openhab/log.rb +2 -2
  33. data/lib/openhab/rspec/helpers.rb +10 -1
  34. data/lib/openhab/rspec/karaf.rb +2 -2
  35. data/lib/openhab/rspec.rb +1 -1
  36. metadata +6 -2
@@ -22,53 +22,18 @@ module OpenHAB
22
22
  java_import org.openhab.core.items.Metadata
23
23
  private_constant :Metadata
24
24
 
25
- include Enumerable
26
-
25
+ # Mutators are manually implemented below.
26
+ include EmulateHash
27
27
  extend Forwardable
28
- def_delegators :@metadata, :configuration, :hash, :to_s, :uid, :value
29
- private :configuration
30
28
 
31
- # @!method to_hash
32
- # Implicit conversion to {::Hash}.
33
- # @return [::Hash]
34
-
35
- # Make it act like a Hash; some methods can be handled by
36
- # java.util.Map, others we have to convert to a Ruby Hash first, and
37
- # still others (mutators) must be manually implemented below.
38
- def_delegators :configuration,
39
- :any?,
40
- :compact,
41
- :compare_by_identity?,
42
- :deconstruct_keys,
43
- :default,
44
- :default_proc,
45
- :each,
46
- :each_key,
47
- :each_pair,
48
- :each_value,
49
- :empty?,
50
- :filter,
51
- :flatten,
52
- :has_value?,
53
- :invert,
54
- :key,
55
- :keys,
56
- :length,
57
- :rassoc,
58
- :reject,
59
- :select,
60
- :shift,
61
- :size,
62
- :to_a,
63
- :to_h,
64
- :to_hash,
65
- :transform_keys,
66
- :transform_values,
67
- :values,
68
- :value?
29
+ def_delegators :@metadata, :configuration, :hash, :uid, :value
30
+ private :configuration
69
31
 
70
32
  def_delegator :uid, :namespace
71
33
 
34
+ alias_method :to_map, :configuration
35
+ private :to_map
36
+
72
37
  class << self
73
38
  # @!visibility private
74
39
  def from_item(item_name, namespace, value)
@@ -209,48 +174,12 @@ module OpenHAB
209
174
  end
210
175
 
211
176
  # @!visibility private
212
- def [](key)
213
- configuration[key.to_s]
214
- end
215
-
216
- # @!visibility private
217
- def []=(key, value)
177
+ def store(key, value)
218
178
  key = key.to_s
219
179
  new_config = to_h
220
180
  new_config[key] = value
221
181
  replace(new_config)
222
- value # rubocop:disable Lint/Void
223
- end
224
- alias_method :store, :[]=
225
-
226
- # @!visibility private
227
- def assoc(key)
228
- configuration.assoc(key.to_s)
229
- end
230
-
231
- # @!visibility private
232
- def clear
233
- replace({})
234
- end
235
-
236
- # @!visibility private
237
- def compact!
238
- replace(compact)
239
- end
240
-
241
- # @!visibility private
242
- def compare_by_identity
243
- raise NotImplementedError
244
- end
245
-
246
- # @!visibility private
247
- def default=(*)
248
- raise NotImplementedError
249
- end
250
-
251
- # @!visibility private
252
- def default_proc=(*)
253
- raise NotImplementedError
182
+ value
254
183
  end
255
184
 
256
185
  # @!visibility private
@@ -264,67 +193,6 @@ module OpenHAB
264
193
  old_value
265
194
  end
266
195
 
267
- # @!visibility private
268
- def delete_if(&block)
269
- raise NotImplementedError unless block
270
-
271
- replace(to_h.delete_if(block))
272
- end
273
-
274
- # @!visibility private
275
- def dig(key, *keys)
276
- configuration.dig(key.to_s, *keys)
277
- end
278
-
279
- # @!visibility private
280
- def except(*keys)
281
- to_h.except(*keys.map(&:to_s))
282
- end
283
-
284
- # @!visibility private
285
- def fetch(key, &block)
286
- configuration.fetch(key.to_s, &block)
287
- end
288
-
289
- # @!visibility private
290
- def fetch_values(*keys, &block)
291
- configuration.fetch_values(*keys.map(&:to_s), &block)
292
- end
293
-
294
- # @!visibility private
295
- def keep_if(&block)
296
- select!(&block)
297
- self
298
- end
299
-
300
- # @!visibility private
301
- def key?(key)
302
- configuration.key?(key.to_s)
303
- end
304
- alias_method :include?, :key?
305
- alias_method :has_key?, :key?
306
- alias_method :member?, :key?
307
-
308
- # @!visibility private
309
- def merge!(*others, &block)
310
- return self if others.empty?
311
-
312
- new_config = to_h
313
- others.each do |h|
314
- new_config.merge!(h.transform_keys(&:to_s), &block)
315
- end
316
- replace(new_config)
317
- end
318
- alias_method :update, :merge!
319
-
320
- # @!visibility private
321
- def reject!(&block)
322
- raise NotImplementedError unless block
323
-
324
- r = to_h.reject!(&block)
325
- replace(r) if r
326
- end
327
-
328
196
  #
329
197
  # Replace the configuration with a new {::Hash}.
330
198
  #
@@ -337,42 +205,6 @@ module OpenHAB
337
205
  self
338
206
  end
339
207
 
340
- # @!visibility private
341
- def select!(&block)
342
- raise NotImplementedError unless block?
343
-
344
- r = to_h.select!(&block)
345
- replace(r) if r
346
- end
347
- alias_method :filter!, :select!
348
-
349
- # @!visibility private
350
- def slice(*keys)
351
- configuration.slice(*keys.map(&:to_s))
352
- end
353
-
354
- # @!visibility private
355
- def to_proc
356
- ->(k) { self[k] }
357
- end
358
-
359
- # @!visibility private
360
- def transform_keys!(*args, &block)
361
- replace(transform_keys(*args, &block))
362
- end
363
-
364
- # @!visibility private
365
- def transform_values!(&block)
366
- raise NotImplementedError unless block
367
-
368
- replace(transform_values(&block))
369
- end
370
-
371
- # @!visibility private
372
- def values_at(*keys)
373
- configuration.values_at(*keys.map(&:to_s))
374
- end
375
-
376
208
  # @!visibility private
377
209
  def inspect
378
210
  return to_h.inspect if value.empty?
@@ -380,8 +212,6 @@ module OpenHAB
380
212
 
381
213
  [value, to_h].inspect
382
214
  end
383
- remove_method :to_s
384
- alias_method :to_s, :inspect
385
215
 
386
216
  #
387
217
  # @raise [FrozenError] if the provider is not a
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
4
+
3
5
  module OpenHAB
4
6
  module Core
5
7
  module Items
@@ -16,6 +18,9 @@ module OpenHAB
16
18
  # All keys are converted to strings.
17
19
  #
18
20
  class NamespaceHash
21
+ include EmulateHash
22
+ extend Forwardable
23
+
19
24
  class << self
20
25
  #
21
26
  # @return [org.openhab.core.items.MetadataRegistry]
@@ -29,27 +34,6 @@ module OpenHAB
29
34
  java_import org.openhab.core.items.MetadataKey
30
35
  private_constant :MetadataKey
31
36
 
32
- include Enumerable
33
- extend Forwardable
34
-
35
- def_delegators :to_hash,
36
- :<,
37
- :<=,
38
- :==,
39
- :>,
40
- :>=,
41
- :filter,
42
- :flatten,
43
- :invert,
44
- :key,
45
- :merge,
46
- :rassoc,
47
- :reject,
48
- :select,
49
- :to_a,
50
- :transform_keys,
51
- :transform_values
52
-
53
37
  def_delegators :keys,
54
38
  :length,
55
39
  :size
@@ -76,12 +60,29 @@ module OpenHAB
76
60
  def to_hash
77
61
  each.to_h { |namespace, meta| [namespace, meta] }
78
62
  end
63
+ alias_method :to_h, :to_hash
64
+ alias_method :to_map, :to_hash
65
+ private :to_map
79
66
 
80
- # @return [Hash, nil]
81
- #
82
67
  # @!visibility private
83
- def [](namespace)
84
- fetch(namespace, nil)
68
+ def fetch(key, *default_value, &block)
69
+ key = key.to_s
70
+ return @hash.fetch(key, *default_value, &block) unless attached?
71
+
72
+ if default_value.length > 1
73
+ raise ArgumentError, "Wrong number of arguments (given #{default_value.length + 1}, expected 1..2)"
74
+ end
75
+
76
+ logger.trace("Getting metadata for item: #{@item_name}, namespace '#{key}'")
77
+ if (m = Provider.registry.get(MetadataKey.new(key, @item_name)))
78
+ Hash.new(m)
79
+ elsif block
80
+ yield key
81
+ elsif !default_value.empty?
82
+ default_value.first
83
+ else
84
+ raise KeyError, "Key not found #{key.inspect}"
85
+ end
85
86
  end
86
87
 
87
88
  #
@@ -92,18 +93,12 @@ module OpenHAB
92
93
  # @return [Hash]
93
94
  #
94
95
  # @!visibility private
95
- def []=(namespace, value)
96
+ def store(namespace, value)
96
97
  metadata = Hash.from_item(@item_name, namespace, value)
97
- return @hash[metadata.uid.namespace] = metadata unless attached? # rubocop:disable Lint/ReturnInVoidContext
98
+ return @hash[metadata.uid.namespace] = metadata unless attached?
98
99
 
99
100
  metadata.create_or_update
100
- metadata # rubocop:disable Lint/Void
101
- end
102
- alias_method :store, :[]=
103
-
104
- # @!visibility private
105
- def assoc(key)
106
- to_hash.assoc(key.to_s)
101
+ metadata
107
102
  end
108
103
 
109
104
  #
@@ -133,41 +128,11 @@ module OpenHAB
133
128
  self
134
129
  end
135
130
 
136
- # @!visibility private
137
- def compare_by_identity
138
- raise NotImplementedError
139
- end
140
-
141
- # @!visibility private
142
- def compare_by_identity?
143
- false
144
- end
145
-
146
131
  # @!visibility private
147
132
  def deconstruct_keys
148
133
  self
149
134
  end
150
135
 
151
- # @!visibility private
152
- def default(*)
153
- nil
154
- end
155
-
156
- # @!visibility private
157
- def default=(*)
158
- raise NotImplementedError
159
- end
160
-
161
- # @!visibility private
162
- def default_proc
163
- nil
164
- end
165
-
166
- # @!visibility private
167
- def default_proc=(*)
168
- raise NotImplementedError
169
- end
170
-
171
136
  # @!visibility private
172
137
  def delete(namespace, &block)
173
138
  return @hash.delete(namespace.to_s, &block) unless attached?
@@ -249,33 +214,6 @@ module OpenHAB
249
214
  true
250
215
  end
251
216
 
252
- # @!visibility private
253
- def except(*keys)
254
- to_hash.except(*keys.map(&:to_s))
255
- end
256
-
257
- # @!visibility private
258
- def fetch(key, *default_value, &block)
259
- key = key.to_s
260
- return @hash.fetch(key, *default_value, &block) unless attached?
261
-
262
- if default_value.length > 1
263
- raise "wrong number of arguments (given #{default_value.length + 1}, expected 1..2)",
264
- ArgumentError
265
- end
266
-
267
- logger.trace("Getting metadata for item: #{@item_name}, namespace '#{key}'")
268
- if (m = Provider.registry.get(MetadataKey.new(key, @item_name)))
269
- Hash.new(m)
270
- elsif block
271
- yield key
272
- elsif !default_value.empty?
273
- default_value.first
274
- else
275
- raise "key not found #{key.inspect}", KeyError
276
- end
277
- end
278
-
279
217
  # @!visibility private
280
218
  def fetch_values(*keys)
281
219
  return @hash.fetch_values(keys.map(&:to_s)) if attached?
@@ -295,12 +233,6 @@ module OpenHAB
295
233
  ["metadata_namespace_hash", @item_name.hash]
296
234
  end
297
235
 
298
- # @!visibility private
299
- def keep_if(&block)
300
- select!(&block)
301
- self
302
- end
303
-
304
236
  #
305
237
  # @return [true,false] True if the given namespace exists, false otherwise
306
238
  #
@@ -311,9 +243,7 @@ module OpenHAB
311
243
 
312
244
  !Provider.registry.get(MetadataKey.new(key, @item_name)).nil?
313
245
  end
314
- alias_method :has_key?, :key?
315
246
  alias_method :member?, :key?
316
- alias_method :include?, :key?
317
247
 
318
248
  # @!visibility private
319
249
  def keys
@@ -324,28 +254,16 @@ module OpenHAB
324
254
  each_key.to_a
325
255
  end
326
256
 
327
- #
328
- # Merge the given hash with the current metadata. Existing namespace that matches the name
329
- # of the new namespace will be overwritten. Others will be added.
330
- #
331
257
  # @!visibility private
332
- def merge!(*others)
333
- return self if others.empty?
334
-
335
- others.each do |other|
336
- case other
337
- when ::Hash, NamespaceHash
338
- other.each do |namespace, new_meta|
339
- self[namespace] = new_meta
340
- next unless block_given?
341
-
342
- current_meta = self[namespace]
343
- new_meta = yield key, current_meta, new_meta unless current_meta.nil?
344
- self[namespace] = new_meta unless new_meta.equal?(current_meta)
345
- end
346
- else
347
- raise ArgumentError, "merge only supports Hash, or another item's metadata"
258
+ def replace(other)
259
+ clear
260
+ case other
261
+ when ::Hash, NamespaceHash
262
+ other.each do |namespace, new_meta|
263
+ self[namespace] = new_meta
348
264
  end
265
+ else
266
+ raise ArgumentError, "Only supports Hash, or another item's metadata. '#{other.class}' was given."
349
267
  end
350
268
  self
351
269
  end
@@ -381,8 +299,7 @@ module OpenHAB
381
299
  r = {}
382
300
  Provider.registry.all.each do |meta|
383
301
  if meta.uid.item_name == @item_name && keys.include?(meta.uid.namespace)
384
- r[meta.uid.namespace] =
385
- Hash.new(meta)
302
+ r[meta.uid.namespace] = Hash.new(meta)
386
303
  end
387
304
  end
388
305
  r
@@ -404,17 +321,6 @@ module OpenHAB
404
321
  self
405
322
  end
406
323
 
407
- # @!visibility private
408
- def replace(other)
409
- clear
410
- merge!(other)
411
- end
412
-
413
- # @!visibility private
414
- def to_proc
415
- ->(k) { self[k] }
416
- end
417
-
418
324
  # @!visibility private
419
325
  def transform_keys!(hash2 = nil)
420
326
  hash2 = hash2&.transform_keys(&:to_s)
@@ -459,15 +365,6 @@ module OpenHAB
459
365
  def values_at(*keys)
460
366
  keys.map(&self)
461
367
  end
462
-
463
- #
464
- # @return [String]
465
- #
466
- # @!visibility private
467
- def inspect
468
- to_hash.inspect
469
- end
470
- alias_method :to_s, :inspect
471
368
  end
472
369
  end
473
370
  end
@@ -74,13 +74,20 @@ module OpenHAB
74
74
  # All persistence methods that require a timestamp
75
75
  # Note the _between methods are automatically created from the _since methods
76
76
  PERSISTENCE_METHODS = (QUANTITY_METHODS +
77
- %i[changed_since?
78
- count_since
79
- count_state_changes_since
80
- historic_state
81
- maximum_since
82
- minimum_since
83
- updated_since?]).freeze
77
+ %i[ changed_since?
78
+ count_since
79
+ count_state_changes_since
80
+ historic_state
81
+ maximum_since
82
+ minimum_since
83
+ updated_since?])
84
+
85
+ # @deprecated OH3.4 - in openHAB 4, just add :get_all_states_since and freeze the list above
86
+ if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
87
+ PERSISTENCE_METHODS << :get_all_states_since
88
+ end
89
+ PERSISTENCE_METHODS.freeze
90
+
84
91
  private_constant :QUANTITY_METHODS, :PERSISTENCE_METHODS
85
92
 
86
93
  # @!method persist(service = nil)
@@ -275,6 +282,21 @@ module OpenHAB
275
282
  # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
276
283
  # @return [Integer] The number of values persisted for this item.
277
284
 
285
+ # @!method all_states_since(timestamp, service = nil)
286
+ # @since openHAB 4.0
287
+ # Returns all the states from a point in time until now.
288
+ # @param [#to_zoned_date_time] timestamp The point in time from which to search
289
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
290
+ # @return [Array<HistoricState>] An array of {HistoricState} persisted for this item.
291
+
292
+ # @!method all_states_between(start, finish, service = nil)
293
+ # @since openHAB 4.0
294
+ # Returns all the states between two points in time.
295
+ # @param [#to_zoned_date_time] start The point in time from which to search
296
+ # @param [#to_zoned_date_time] finish The point in time to which to search
297
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
298
+ # @return [Array<HistoricState>] An array of {HistoricState} persisted for this item.
299
+
278
300
  %i[persist last_update].each do |method|
279
301
  define_method(method) do |service = nil|
280
302
  service ||= persistence_service
@@ -363,6 +385,11 @@ module OpenHAB
363
385
 
364
386
  alias_method :state_changes_since, :count_state_changes_since
365
387
  alias_method :state_changes_between, :count_state_changes_between
388
+ # @deprecated OH 3.4 - if guard is unnecessary in OH4
389
+ if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
390
+ alias_method :all_states_since, :get_all_states_since
391
+ alias_method :all_states_between, :get_all_states_between
392
+ end
366
393
 
367
394
  private
368
395
 
@@ -391,15 +418,21 @@ module OpenHAB
391
418
  # @return [HistoricState] a {HistoricState} object if the result was a HistoricItem
392
419
  # @return [QuantityType] a `QuantityType` object if the result was an average, delta, deviation,
393
420
  # sum, or variance.
421
+ # @return [Array<HistoricState>] an array of {HistoricState} objects if the result was an array
422
+ # of HistoricItem
394
423
  # @return [Object] the original result object otherwise.
395
424
  #
396
425
  def wrap_result(result, method)
397
- if result.is_a?(org.openhab.core.persistence.HistoricItem)
398
- return HistoricState.new(quantify(result.state), result)
399
- end
400
- return quantify(result) if QUANTITY_METHODS.include?(method)
426
+ case result
427
+ when org.openhab.core.persistence.HistoricItem
428
+ HistoricState.new(quantify(result.state), result)
429
+ when java.util.Collection, Array
430
+ result.to_a.map { |historic_item| wrap_result(historic_item, method) }
431
+ else
432
+ return quantify(result) if QUANTITY_METHODS.include?(method)
401
433
 
402
- result
434
+ result
435
+ end
403
436
  end
404
437
 
405
438
  #
@@ -93,6 +93,11 @@ module OpenHAB
93
93
  "synonyms=#{synonyms.to_a.inspect}>"
94
94
  end
95
95
 
96
+ # @return [String]
97
+ def to_s
98
+ name
99
+ end
100
+
96
101
  private
97
102
 
98
103
  def check_type(other)
@@ -13,6 +13,15 @@ module OpenHAB
13
13
  # @!visibility private
14
14
  java_import org.openhab.core.semantics.SemanticTags
15
15
 
16
+ #
17
+ # Returns the tag's string representation
18
+ #
19
+ # @return [String]
20
+ #
21
+ def to_s
22
+ java_class.simple_name
23
+ end
24
+
16
25
  #
17
26
  # Returns the tag's label
18
27
  #
@@ -176,6 +176,7 @@ module OpenHAB
176
176
  GenericItem.include(self)
177
177
  GroupItem.extend(Forwardable)
178
178
  GroupItem.def_delegators :members, :equipments, :locations
179
+
179
180
  # This is a marker interface for all semantic tag classes.
180
181
  # @interface
181
182
  # @deprecated Since openHAB 4.0, {SemanticTag} is the interface that all tags implement.
@@ -197,6 +198,7 @@ module OpenHAB
197
198
  # @return [Array<SemanticTag>] an array containing all the Semantic tags
198
199
  #
199
200
  def tags
201
+ # @deprecated OH3.4 missing registry
200
202
  if Provider.registry
201
203
  Provider.registry.all.to_a
202
204
  else
@@ -328,7 +330,7 @@ module OpenHAB
328
330
  end
329
331
  end.compact
330
332
  end
331
- end
333
+ end
332
334
  end
333
335
 
334
336
  # @!parse
@@ -163,11 +163,24 @@ module OpenHAB
163
163
  # Manually trigger the rule
164
164
  #
165
165
  # @param [Object, nil] event The event to pass to the rule's execution blocks.
166
- # @return [void]
167
- #
168
- def trigger(event = nil)
169
- Rules.manager.run_now(uid, false, { "event" => event })
166
+ # @param [Boolean] consider_conditions Whether to check the conditions of the called rules.
167
+ # @param [kwargs] context The context to pass to the conditions and the actions of the rule.
168
+ # @return [Hash] A copy of the rule context, including possible return values.
169
+ #
170
+ def trigger(event = nil, consider_conditions: false, **context)
171
+ begin
172
+ event ||= org.openhab.core.automation.events.AutomationEventFactory
173
+ .createExecutionEvent(uid, nil, "manual")
174
+ rescue NameError
175
+ # @deprecated OH3.4 doesn't have AutomationEventFactory
176
+ end
177
+ context.transform_keys!(&:to_s)
178
+ # Unwrap any proxies and pass raw objects (items, things)
179
+ context.transform_values! { |value| value.is_a?(Delegator) ? value.__getobj__ : value }
180
+ context["event"] = event if event # @deprecated OH3.4 - remove if guard. In OH4 `event` will never be nil
181
+ Rules.manager.run_now(uid, consider_conditions, context)
170
182
  end
183
+ alias_method :run, :trigger
171
184
  end
172
185
  end
173
186
  end
@@ -25,7 +25,7 @@ module OpenHAB
25
25
 
26
26
  # @!visibility private
27
27
  def link(item, channel, config = {})
28
- config = org.openhab.core.config.core.Configuration.new(config.transform_keys(&:to_s))
28
+ config = Configuration.new(config.transform_keys(&:to_s))
29
29
  channel = ChannelUID.new(channel) if channel.is_a?(String)
30
30
  channel = channel.uid if channel.is_a?(Channel)
31
31
  link = org.openhab.core.thing.link.ItemChannelLink.new(item.name, channel, config)