openhab-scripting 5.13.0 → 5.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfe5a24aad596dbbc699c68d39ffec4417b9199a75738a54292386d80e725525
4
- data.tar.gz: 7aa7877384c2df3ee41588660e3db596f807fd5b2b7b781921528f14b0f9fdeb
3
+ metadata.gz: 11409728d3f0ecb384da9099355fea4728020aa1de1d494d3085dddea518e16c
4
+ data.tar.gz: d4daa321f0b779b0c9f47ccc405cdafd3a71f55666e173cb29315a7f948b2029
5
5
  SHA512:
6
- metadata.gz: 756ab20dcfdfce97ba6dfdcbf76d1f40c544607312622e0e013ddd38f7a0d201ae0fec69c13017300fba938d7081eb89f5be5d65ad59abcadf17380ae580dad8
7
- data.tar.gz: d9facdcb106fe9fa3e2e51574fa2e52168b9c07eb9c1fad1498a6380e9bc783c8a63535c2a715956a894eb39a2b741ff6f9284fb1de71f9e083262b9f4ed42d0
6
+ metadata.gz: b8eee772f02cf086af4db419ecaa5752b21393302533f6fea628a6e9bc50d7e986b1815e03c71de7acba63a13088f46d3e73e96d416a1869a7e2b9fe627764ea
7
+ data.tar.gz: 4ebdb8fb5d81c4429188163e4ced5aabf2ee8a33797b540a32e0e81024a67ac7143728b7679181ca26a4856f8e7e6ed291b5f4bb9427c1df2a744eb6fcb75dd1
@@ -252,10 +252,10 @@ module OpenHAB
252
252
  end
253
253
 
254
254
  # @!attribute thing [r]
255
- # Return the item's thing if this item is linked with a thing. If an item is linked to more than one thing,
255
+ # Return the item's thing if this item is linked with a thing. If an item is linked to more than one channel,
256
256
  # this method only returns the first thing.
257
257
  #
258
- # @return [Thing] The thing associated with this item or nil
258
+ # @return [Things::Thing, nil]
259
259
  def thing
260
260
  all_linked_things.first
261
261
  end
@@ -264,12 +264,46 @@ module OpenHAB
264
264
  # @!attribute things [r]
265
265
  # Returns all of the item's linked things.
266
266
  #
267
- # @return [Array<Thing>] An array of things or an empty array
267
+ # @return [Array<Things::Thing>] An array of things or an empty array
268
268
  def things
269
269
  Things::Links::Provider.registry.get_bound_things(name).map { |thing| Things::Proxy.new(thing) }
270
270
  end
271
271
  alias_method :all_linked_things, :things
272
272
 
273
+ # @!attribute channel_uid [r]
274
+ # Return the UID of the channel this item is linked to. If an item is linked to more than one channel,
275
+ # this method only returns the first channel.
276
+ #
277
+ # @return [Things::ChannelUID, nil]
278
+ def channel_uid
279
+ channel_uids.first
280
+ end
281
+
282
+ # @!attribute channel_uids [r]
283
+ # Return the UIDs of all of the channels this item is linked to.
284
+ #
285
+ # @return [Array<Things::ChannelUID>]
286
+ def channel_uids
287
+ Things::Links::Provider.registry.get_bound_channels(name)
288
+ end
289
+
290
+ # @!attribute channel [r]
291
+ # Return the the channel this item is linked to. If an item is linked to more than one channel,
292
+ # this method only returns the first channel.
293
+ #
294
+ # @return [Things::Channel, nil]
295
+ def channel
296
+ channel_uids.first&.channel
297
+ end
298
+
299
+ # @!attribute channels [r]
300
+ # Return all of the channels this item is linked to.
301
+ #
302
+ # @return [Array<Things::Channel>]
303
+ def channels
304
+ channel_uids.map(&:channel)
305
+ end
306
+
273
307
  #
274
308
  # @!attribute links [r]
275
309
  # Returns all of the item's links (channels and link configurations).
@@ -290,30 +324,43 @@ module OpenHAB
290
324
  end
291
325
 
292
326
  #
293
- # Links the item to a channel.
327
+ # @return [Things::ItemChannelLink, nil]
294
328
  #
295
- # @param [String, Things::Channel, Things::ChannelUID] channel The channel to link to.
296
- # @param [Hash] config The configuration for the link.
329
+ # @overload link
330
+ # Returns the item's link. If an item is linked to more than one channel,
331
+ # this method only returns the first link.
297
332
  #
298
- # @return [Things::ItemChannelLink] The created link.
333
+ # @return [Things::ItemChannelLink, nil]
299
334
  #
300
- # @example Link an item to a channel
301
- # LivingRoom_Light_Power.link("mqtt:topic:livingroom-light:power")
335
+ # @overload link(channel, config = {})
302
336
  #
303
- # @example Link to a Thing's channel
304
- # LivingRoom_Light_Power.link(things["mqtt:topic:livingroom-light"].channels["power"])
337
+ # Links the item to a channel.
305
338
  #
306
- # @example Specify a link configuration
307
- # High_Temperature_Alert.link(
308
- # "mqtt:topic:outdoor-thermometer:temperature",
309
- # profile: "system:hysteresis",
310
- # lower: "29 °C",
311
- # upper: "30 °C")
339
+ # @param [String, Things::Channel, Things::ChannelUID] channel The channel to link to.
340
+ # @param [Hash] config The configuration for the link.
312
341
  #
313
- # @see links
314
- # @see unlink
342
+ # @return [Things::ItemChannelLink] The created link.
343
+ #
344
+ # @example Link an item to a channel
345
+ # LivingRoom_Light_Power.link("mqtt:topic:livingroom-light:power")
315
346
  #
316
- def link(channel, config = {})
347
+ # @example Link to a Thing's channel
348
+ # LivingRoom_Light_Power.link(things["mqtt:topic:livingroom-light"].channels["power"])
349
+ #
350
+ # @example Specify a link configuration
351
+ # High_Temperature_Alert.link(
352
+ # "mqtt:topic:outdoor-thermometer:temperature",
353
+ # profile: "system:hysteresis",
354
+ # lower: "29 °C",
355
+ # upper: "30 °C")
356
+ #
357
+ # @see links
358
+ # @see unlink
359
+ #
360
+ def link(channel = nil, config = nil)
361
+ return Things::Links::Provider.registry.get_links(name).first if channel.nil? && config.nil?
362
+
363
+ config ||= {}
317
364
  Core::Things::Links::Provider.create_link(self, channel, config).tap do |new_link|
318
365
  provider = Core::Things::Links::Provider.current
319
366
  if !(current_link = provider.get(new_link.uid))
@@ -193,4 +193,12 @@ module Enumerable
193
193
  def ensure
194
194
  OpenHAB::DSL::Items::Ensure::ItemDelegate.new(self)
195
195
  end
196
+
197
+ #
198
+ # Send a toggle command to every item in the collection
199
+ # @return [self]
200
+ #
201
+ def toggle
202
+ each(&:toggle)
203
+ end
196
204
  end
@@ -63,7 +63,7 @@ module OpenHAB
63
63
  #
64
64
  # @example
65
65
  # sitemaps.build do
66
- # sitemap "default", "My Residence" do
66
+ # sitemap "default", label: "My Residence" do
67
67
  # frame label: "Control" do
68
68
  # text label: "Climate", icon: "if:mdi:home-thermometer-outline" do
69
69
  # frame label: "Main Floor" do
@@ -112,8 +112,30 @@ module OpenHAB
112
112
  # end
113
113
  # end
114
114
  #
115
+ # @example
116
+ # def add_tv(builder, tv)
117
+ # builder.frame label: tv.location.label do
118
+ # builder.switch item: tv.points(Semantics::Switch), label: "Power"
119
+ # end
120
+ # end
121
+ #
122
+ # sitemaps.build do |builder|
123
+ # builder.sitemap "tvs", label: "TVs" do
124
+ # items.equipments(Semantics::TV).each do |tv|
125
+ # add_tv(builder, tv)
126
+ # end
127
+ # end
128
+ # end
129
+ #
115
130
  def build(update: true, &block)
116
- DSL::Sitemaps::Builder.new(self, update: update).instance_eval(&block)
131
+ builder_proxy = SimpleDelegator.new(nil) if block.arity == 1
132
+ builder = DSL::Sitemaps::Builder.new(self, builder_proxy, update: update)
133
+ if block.arity == 1
134
+ builder_proxy.__setobj__(builder)
135
+ yield builder_proxy
136
+ else
137
+ builder.instance_eval(&block)
138
+ end
117
139
  end
118
140
 
119
141
  # For use in specs
@@ -33,6 +33,13 @@ module OpenHAB
33
33
  end
34
34
 
35
35
  alias_method :channel_uid, :linked_uid
36
+
37
+ # @return [String]
38
+ def inspect
39
+ r = "#<OpenHAB::Core::Things::ItemChannelLink item_name=#{item_name} channel_uid=#{channel_uid}"
40
+ r += " configuration=#{configuration.properties.to_h}" unless configuration.properties.empty?
41
+ "#{r}>"
42
+ end
36
43
  end
37
44
  end
38
45
  end
@@ -12,18 +12,19 @@ module OpenHAB
12
12
  # Base sitemap builder DSL
13
13
  class Builder
14
14
  # @!visibility private
15
- def initialize(provider, update:)
15
+ def initialize(provider, builder_proxy, update:)
16
16
  @provider = provider
17
+ @builder_proxy = builder_proxy
17
18
  @update = update
18
19
  end
19
20
 
20
21
  # (see SitemapBuilder#initialize)
22
+ # @!method sitemap(name, label: nil, icon: nil, &block)
21
23
  # @yield Block executed in the context of a {SitemapBuilder}
22
24
  # @return [SitemapBuilder]
23
25
  # @!visibility public
24
- def sitemap(name, label = nil, icon: nil, &block)
25
- sitemap = SitemapBuilder.new(name, label, icon: icon)
26
- sitemap.instance_eval_with_dummy_items(&block) if block
26
+ def sitemap(name, label: nil, icon: nil, &block)
27
+ sitemap = SitemapBuilder.new(name, @builder_proxy, label: label, icon: icon, &block)
27
28
  sitemap = sitemap.build
28
29
  if @update && @provider.get(sitemap.uid)
29
30
  @provider.update(sitemap)
@@ -105,6 +106,7 @@ module OpenHAB
105
106
  # One or more visibility rules (see {#visibility})
106
107
  # @!visibility private
107
108
  def initialize(type,
109
+ builder_proxy,
108
110
  item: nil,
109
111
  label: nil,
110
112
  icon: nil,
@@ -112,13 +114,15 @@ module OpenHAB
112
114
  label_color: nil,
113
115
  value_color: nil,
114
116
  icon_color: nil,
115
- visibility: nil)
117
+ visibility: nil,
118
+ &block)
116
119
  unless SitemapBuilder.factory.respond_to?("create_#{type}")
117
120
  raise ArgumentError,
118
121
  "#{type} is not a valid widget type"
119
122
  end
120
123
 
121
124
  @type = type
125
+ @builder_proxy = builder_proxy
122
126
  @item = item
123
127
  @label = label
124
128
  @icon = icon
@@ -132,6 +136,20 @@ module OpenHAB
132
136
  self.value_color(value_color) if value_color
133
137
  self.icon_color(icon_color) if icon_color
134
138
  self.visibility(*visibility) if visibility
139
+
140
+ return unless block
141
+
142
+ @builder_proxy ||= SimpleDelegator.new(nil) if block.arity == 1
143
+
144
+ if @builder_proxy
145
+ old_obj = @builder_proxy.__getobj__
146
+ @builder_proxy.__setobj__(self)
147
+ yield @builder_proxy
148
+ else
149
+ instance_eval_with_dummy_items(&block)
150
+ end
151
+ ensure
152
+ @builder_proxy&.__setobj__(old_obj)
135
153
  end
136
154
 
137
155
  # Adds one or more new rules for setting the label color
@@ -271,8 +289,8 @@ module OpenHAB
271
289
  # @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, mappings: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
272
290
  # @param mappings [Hash, Array, nil] Mappings from command to label (see {SwitchBuilder#mappings})
273
291
  # @!visibility private
274
- def initialize(type, mappings: nil, **kwargs)
275
- super(type, **kwargs)
292
+ def initialize(type, builder_proxy, mappings: nil, **kwargs, &block)
293
+ super(type, builder_proxy, **kwargs, &block)
276
294
 
277
295
  @mappings = mappings
278
296
  end
@@ -312,8 +330,8 @@ module OpenHAB
312
330
  # @param range [Range, nil] Allowed range of the value (see {SetpointBuilder#range})
313
331
  # @param step [Numeric,nil] How far the value will change with each button press (see {SetpointBuilder#step})
314
332
  # @!visibility private
315
- def initialize(type, range: nil, step: nil, **kwargs)
316
- super(type, **kwargs)
333
+ def initialize(type, builder_proxy, range: nil, step: nil, **kwargs, &block)
334
+ super(type, builder_proxy, **kwargs, &block)
317
335
 
318
336
  @range = range
319
337
  @step = step
@@ -348,8 +366,8 @@ module OpenHAB
348
366
  # @param frequency [Numeric, nil]
349
367
  # How often to send requests (in seconds) (see {SliderBuilder#frequency})
350
368
  # @!visibility private
351
- def initialize(type, switch: nil, frequency: nil, **kwargs)
352
- super(type, **kwargs)
369
+ def initialize(type, builder_proxy, switch: nil, frequency: nil, **kwargs, &block)
370
+ super(type, builder_proxy, **kwargs, &block)
353
371
 
354
372
  @switch = switch
355
373
  @frequency = frequency
@@ -387,8 +405,8 @@ module OpenHAB
387
405
  # @param [String, nil] url (see {VideoBuilder#url})
388
406
  # @param [:mjpeg, :hls, nil] encoding (see {VideoBuilder#encoding})
389
407
  # @!visibility private
390
- def initialize(type, url: nil, encoding: nil, **kwargs)
391
- super(type, **kwargs)
408
+ def initialize(type, builder_proxy, url: nil, encoding: nil, **kwargs, &block)
409
+ super(type, builder_proxy, **kwargs, &block)
392
410
 
393
411
  @url = url
394
412
  self.encoding = encoding
@@ -456,14 +474,16 @@ module OpenHAB
456
474
  # Formatting string for values on the y axis (see {ChartBuilder#y_axis_pattern})
457
475
  # @!visibility private
458
476
  def initialize(type,
477
+ builder_proxy,
459
478
  service: nil,
460
479
  refresh: nil,
461
480
  period: nil,
462
481
  legend: nil,
463
482
  group: nil,
464
483
  y_axis_pattern: nil,
465
- **kwargs)
466
- super(type, **kwargs)
484
+ **kwargs,
485
+ &block)
486
+ super(type, builder_proxy, **kwargs, &block)
467
487
 
468
488
  @service = service
469
489
  self.refresh = refresh
@@ -513,8 +533,8 @@ module OpenHAB
513
533
  # @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, height: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
514
534
  # @param height [Integer] The number of element rows to fill (see {DefaultBuilder#height})
515
535
  # @!visibility private
516
- def initialize(type, height: nil, **kwargs)
517
- super(type, **kwargs)
536
+ def initialize(type, builder_proxy, height: nil, **kwargs, &block)
537
+ super(type, builder_proxy, **kwargs, &block)
518
538
 
519
539
  @height = height
520
540
  end
@@ -538,8 +558,8 @@ module OpenHAB
538
558
  # @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, url: nil, height: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
539
559
  # @param url [String, nil] (see {WebviewBuilder#url})
540
560
  # @!visibility private
541
- def initialize(type, url: nil, **kwargs)
542
- super(type, **kwargs)
561
+ def initialize(type, builder_proxy, url: nil, **kwargs, &block)
562
+ super(type, builder_proxy, **kwargs, &block)
543
563
 
544
564
  @url = url
545
565
  end
@@ -564,8 +584,8 @@ module OpenHAB
564
584
  # @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, frequency: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
565
585
  # @param frequency [Numeric, nil] How often to send requests (see {ColorpickerBuilder#frequency})
566
586
  # @!visibility private
567
- def initialize(type, frequency: nil, **kwargs)
568
- super(type, **kwargs)
587
+ def initialize(type, builder_proxy, frequency: nil, **kwargs, &block)
588
+ super(type, builder_proxy, **kwargs, &block)
569
589
 
570
590
  @frequency = frequency
571
591
  end
@@ -600,8 +620,8 @@ module OpenHAB
600
620
  # @param [:text, :number, :date, :time, :datetime, nil] hint
601
621
  # Gives a hint to the user interface to use a widget adapted to a specific use (see {InputBuilder#hint})
602
622
  # @!visibility private
603
- def initialize(type, hint: nil, **kwargs)
604
- super(type, **kwargs)
623
+ def initialize(type, builder_proxy, hint: nil, **kwargs, &block)
624
+ super(type, builder_proxy, **kwargs, &block)
605
625
 
606
626
  self.hint = hint
607
627
  end
@@ -657,10 +677,10 @@ module OpenHAB
657
677
  #
658
678
  # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-buttongrid
659
679
  # @!visibility private
660
- def initialize(type, buttons: [], **kwargs)
661
- super(type, **kwargs)
662
- buttons.each { |button| validate_button(button) }
680
+ def initialize(type, builder_proxy, buttons: [], **kwargs, &block)
663
681
  @buttons = buttons
682
+ super(type, builder_proxy, **kwargs, &block)
683
+ buttons.each { |button| validate_button(button) }
664
684
  end
665
685
 
666
686
  #
@@ -997,9 +1017,10 @@ module OpenHAB
997
1017
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
998
1018
  def #{method}(*args, **kwargs, &block) # def frame(*args, **kwargs, &block)
999
1019
  widget = #{method.capitalize}Builder.new(#{method.inspect}, # widget = FrameBuilder.new(:frame,
1020
+ @builder_proxy, # @builder_proxy,
1000
1021
  *args, # *args,
1001
- **kwargs) # **kwargs)
1002
- widget.instance_eval_with_dummy_items(&block) if block # widget.instance_eval_with_dummy_items(&block) if block
1022
+ **kwargs, # **kwargs,
1023
+ &block) # &block)
1003
1024
  children << widget # children << widget
1004
1025
  widget # widget
1005
1026
  end # end
@@ -1010,9 +1031,9 @@ module OpenHAB
1010
1031
  # @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
1011
1032
  # @!visibility private
1012
1033
  def initialize(*, **)
1013
- super
1014
-
1015
1034
  @children = []
1035
+
1036
+ super
1016
1037
  end
1017
1038
 
1018
1039
  # @!visibility private
@@ -1061,8 +1082,8 @@ module OpenHAB
1061
1082
  # @param url [String, nil] The URL for the image (see {ImageBuilder#url})
1062
1083
  # @param refresh [Numeric, nil] How often to refresh the image (see {ImageBuilder#refresh})
1063
1084
  # @!visibility private
1064
- def initialize(type, url: nil, refresh: nil, **kwargs)
1065
- super(type, **kwargs)
1085
+ def initialize(type, builder_proxy, url: nil, refresh: nil, **kwargs, &block)
1086
+ super(type, builder_proxy, **kwargs, &block)
1066
1087
 
1067
1088
  @url = url
1068
1089
  @refresh = refresh
@@ -1110,8 +1131,8 @@ module OpenHAB
1110
1131
  # @param label [String, nil]
1111
1132
  # @param icon [String, nil]
1112
1133
  # @!visibility private
1113
- def initialize(name, label = nil, icon: nil)
1114
- super(:sitemap, label: label, icon: icon)
1134
+ def initialize(name, builder_proxy, label: nil, icon: nil)
1135
+ super(:sitemap, builder_proxy, label: label, icon: icon)
1115
1136
 
1116
1137
  @name = name
1117
1138
  end
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.13.0"
7
+ VERSION = "5.15.0"
8
8
  end
9
9
  end
data/lib/openhab/osgi.rb CHANGED
@@ -33,20 +33,25 @@ module OpenHAB
33
33
  # Register a new service instance with OSGi
34
34
  #
35
35
  # @param [Object] instance The service instance
36
- # @param [Module] interfaces The interfaces to register this service for.
36
+ # @param [Module, String] interfaces The interfaces to register this service for.
37
37
  # If not provided, it will default to all Java interfaces the instance
38
38
  # implements.
39
+ # @param [org.osgi.framework.Bundle, nil] bundle The bundle to register
40
+ # the service from. If not provided, it will default to the bundle of the first
41
+ # interface.
39
42
  # @param [Hash] properties The service registration properties.
40
43
  # @return [org.osgi.framework.ServiceRegistration]
41
44
  #
42
- def register_service(instance, *interfaces, **properties)
45
+ def register_service(instance, *interfaces, bundle: nil, **properties)
43
46
  if interfaces.empty?
44
47
  interfaces = instance.class.ancestors.select { |k| k.respond_to?(:java_class) && k.java_class&.interface? }
45
48
  end
46
49
 
47
- bundle = org.osgi.framework.FrameworkUtil.get_bundle(interfaces.first.java_class)
50
+ bundle_class = interfaces.first.is_a?(Module) ? interfaces.first : instance
51
+ bundle ||= org.osgi.framework.FrameworkUtil.get_bundle(bundle_class.java_class)
52
+ interfaces.map! { |i| i.is_a?(String) ? i : i.java_class.name }
48
53
  bundle.bundle_context.register_service(
49
- interfaces.map { |i| i.java_class.name }.to_java(java.lang.String),
54
+ interfaces.to_java(java.lang.String),
50
55
  instance,
51
56
  java.util.Hashtable.new(properties)
52
57
  )
@@ -63,6 +68,32 @@ module OpenHAB
63
68
  def bundle
64
69
  @bundle ||= org.osgi.framework.FrameworkUtil.getBundle($scriptExtension.java_class)
65
70
  end
71
+
72
+ # @!visibility private
73
+ SCR_NAMESPACE = "http://www.osgi.org/xmlns/scr/v1.4.0"
74
+ private_constant :SCR_NAMESPACE
75
+
76
+ # @!visibility private
77
+ def service_component_classes(bundle)
78
+ require "nokogiri"
79
+
80
+ component_paths = bundle.headers.get(
81
+ org.osgi.service.component.ComponentConstants::SERVICE_COMPONENT
82
+ )&.split(",") || []
83
+ component_paths.filter_map do |path|
84
+ stream = bundle.get_entry(path).open_stream
85
+ xml = Nokogiri::XML(String.from_java_bytes(stream.read_all_bytes))
86
+
87
+ class_name = xml.at_xpath("scr:component/implementation", scr: SCR_NAMESPACE)&.[]("class")
88
+ next unless class_name
89
+
90
+ services = xml.xpath("scr:component/service/provide", scr: SCR_NAMESPACE).map { |p| p["interface"] }
91
+
92
+ [bundle.load_class(class_name), services]
93
+ ensure
94
+ stream&.close
95
+ end.to_h
96
+ end
66
97
  end
67
98
  end
68
99
  end
@@ -77,23 +77,37 @@ module OpenHAB
77
77
  #
78
78
  # @return [void]
79
79
  #
80
+ # @deprecated
80
81
  def autoupdate_all_items
81
- if instance_variable_defined?(:@autoupdated_items)
82
- raise RuntimeError "You should only call `autoupdate_all_items` once per spec"
83
- end
84
-
85
- @autoupdated_items = []
86
- @spec_metadata_provider = Core::Items::Metadata::Provider.current
82
+ # no-op
83
+ end
87
84
 
88
- $ir.for_each do |_provider, item|
89
- if (hash = item.metadata["autoupdate"])
90
- provider = Core::Items::Metadata::Provider.registry.provider_for(hash.uid)
91
- provider.remove(hash.uid)
92
- @autoupdated_items << [provider, hash]
93
- provider(@spec_metadata_provider) do
94
- item.metadata["autoupdate"] = "true"
95
- end
85
+ #
86
+ # Force things to come online that are missing their thing type
87
+ #
88
+ # As of openHAB 4.0, things that are missing their thing type will not
89
+ # come online immediately. This especially impacts bindings that
90
+ # dynamically generate their thing types, but don't persist those
91
+ # thing types. You can use this method to force them to come online
92
+ # immediately.
93
+ #
94
+ # @return [void]
95
+ #
96
+ def initialize_missing_thing_types
97
+ thing_manager = OpenHAB::OSGi.service("org.openhab.core.thing.ThingManager")
98
+ thing_manager.class.field_reader :missingPrerequisites
99
+ first = true
100
+ thing_manager.missingPrerequisites.each_value do |prereq|
101
+ if first
102
+ prereq.class.field_accessor :timesChecked
103
+ first = false
96
104
  end
105
+ prereq.timesChecked = 60
106
+ end
107
+ m = thing_manager.class.java_class.get_declared_method(:checkMissingPrerequisites)
108
+ m.accessible = true
109
+ suspend_rules do
110
+ m.invoke(thing_manager)
97
111
  end
98
112
  end
99
113
 
@@ -226,8 +240,11 @@ module OpenHAB
226
240
  require_relative "openhab/core/actions"
227
241
 
228
242
  ps = Mocks::PersistenceService.instance
229
- bundle = org.osgi.framework.FrameworkUtil.get_bundle(org.openhab.core.persistence.PersistenceService.java_class)
230
- bundle.bundle_context.register_service(org.openhab.core.persistence.PersistenceService.java_class, ps, nil)
243
+ persistence_bundle = org.osgi.framework.FrameworkUtil
244
+ .get_bundle(org.openhab.core.persistence.PersistenceService.java_class)
245
+ persistence_bundle.bundle_context.register_service(org.openhab.core.persistence.PersistenceService.java_class,
246
+ ps,
247
+ nil)
231
248
 
232
249
  rs = OSGi.service("org.openhab.core.service.ReadyService")
233
250
 
@@ -240,6 +257,33 @@ module OpenHAB
240
257
  rs.register_tracker(org.openhab.core.service.ReadyService::ReadyTracker.impl { continue.call }, filter)
241
258
  end
242
259
 
260
+ begin
261
+ # load storage based type providers
262
+ ast = org.openhab.core.thing.binding.AbstractStorageBasedTypeProvider
263
+ ast_bundle = org.osgi.framework.FrameworkUtil.get_bundle(ast.java_class)
264
+ storage_service = OSGi.service("org.openhab.core.storage.StorageService")
265
+ require_relative "mocks/abstract_storage_based_type_provider_wrapped_storage_service"
266
+
267
+ OSGi.bundle_context.bundles.each do |bundle|
268
+ OSGi.service_component_classes(bundle)
269
+ .select { |klass, _services| klass.ancestors.include?(ast.java_class) }
270
+ .each do |klass, services|
271
+ new_ast_klass = Class.new(ast)
272
+ new_ast_klass.become_java!
273
+ wrapped_storage_service = Mocks::AbstractStorageBasedTypeProviderWrappedStorageService
274
+ .new(storage_service,
275
+ new_ast_klass.java_class,
276
+ klass)
277
+ new_ast = new_ast_klass.new(wrapped_storage_service)
278
+
279
+ services -= [klass.name]
280
+ OSGi.register_service(new_ast, *services, bundle: ast_bundle)
281
+ end
282
+ end
283
+ rescue NameError
284
+ # @deprecated OH 4.0
285
+ end
286
+
243
287
  # RSpec additions
244
288
  require_relative "suspend_rules"
245
289
 
@@ -422,32 +466,6 @@ module OpenHAB
422
466
  .gsub(%r{(?:_|(/))([a-z\d]*)}) { "#{$1}#{$2.capitalize}" }
423
467
  .split("/")
424
468
  end
425
-
426
- # need to transfer autoupdate metadata from GenericMetadataProvider to ManagedMetadataProvider
427
- # so that we can mutate it in the future
428
- def set_up_autoupdates
429
- registry = Core::Items::Metadata::Provider.registry
430
- registry.class.field_reader :identifierToElement
431
-
432
- autoupdate_provider = Core::Items::Metadata::Provider.send(:new)
433
- registry.all.each do |metadata|
434
- next unless metadata.uid.namespace == "autoupdate"
435
-
436
- # tweak the registry to allow us to overwrite this element
437
- registry.identifierToElement.delete(metadata.uid)
438
- autoupdate_provider.add(metadata)
439
- end
440
- end
441
-
442
- def restore_autoupdate_items
443
- return unless instance_variable_defined?(:@autoupdated_items)
444
-
445
- @autoupdated_items.each do |(provider, hash)|
446
- @spec_metadata_provider.remove(hash.uid)
447
- provider.add(hash.instance_variable_get(:@metadata))
448
- end
449
- @autoupdated_items = nil
450
- end
451
469
  end
452
470
 
453
471
  if defined?(::RSpec)
@@ -38,7 +38,6 @@ module OpenHAB
38
38
  end
39
39
 
40
40
  Helpers.autorequires unless Configuration.private_confdir
41
- Helpers.send(:set_up_autoupdates)
42
41
  Helpers.load_transforms
43
42
  Helpers.load_rules
44
43
 
@@ -52,6 +51,10 @@ module OpenHAB
52
51
  end
53
52
  end
54
53
 
54
+ config.around do |example|
55
+ Mocks::Timer.mock_timers(self.class.mock_timers?, &example)
56
+ end
57
+
55
58
  config.before do
56
59
  suspend_rules do
57
60
  $ir.for_each do |_provider, item|
@@ -88,8 +91,6 @@ module OpenHAB
88
91
  @profile_factory = Core::ProfileFactory.send(:new)
89
92
  allow(Core::ProfileFactory).to receive(:instance).and_return(@profile_factory)
90
93
 
91
- stub_const("OpenHAB::Core::Timer", Mocks::Timer) if self.class.mock_timers?
92
-
93
94
  log_line = "rspec #{example.location} # #{example.full_description}"
94
95
  logger.info(log_line)
95
96
  Logger.events.info(log_line)
@@ -103,7 +104,6 @@ module OpenHAB
103
104
  # wipe this
104
105
  DSL::Items::TimedCommand.timed_commands.clear
105
106
  Timecop.return
106
- restore_autoupdate_items
107
107
  Mocks::PersistenceService.instance.reset
108
108
  Hooks.cache_script_extension.sharedCache.clear if DSL.shared_cache
109
109
  DSL.persistence!(nil)
@@ -537,6 +537,10 @@ module OpenHAB
537
537
 
538
538
  def add_class_loader(bundle)
539
539
  return if @class_loaders.include?(bundle.symbolic_name)
540
+ # this bundle sometimes has an invalid internal jar (geronimo-osgi-locator.jar) which will
541
+ # spam the logs with useless errors. it's doubtful we'll need to access a class from this
542
+ # bundle directly
543
+ return if bundle.symbolic_name == "org.apache.aries.javax.jax.rs-api"
540
544
 
541
545
  @class_loaders << bundle.symbolic_name
542
546
  ::JRuby.runtime.instance_config.add_loader(JRuby::OSGiBundleClassLoader.new(bundle))
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module OpenHAB
6
+ module RSpec
7
+ # @!visibility private
8
+ module Mocks
9
+ class AbstractStorageBasedTypeProviderWrappedStorageService < SimpleDelegator
10
+ include org.openhab.core.storage.StorageService
11
+
12
+ def initialize(parent, ruby_klass, java_klass)
13
+ super(parent)
14
+ @ruby_klass = ruby_klass
15
+ @java_klass = java_klass
16
+ end
17
+
18
+ def getStorage(name, _class_loader) # rubocop:disable Naming/MethodName
19
+ super(name.sub(@ruby_klass.name, @java_klass.name), @java_klass.class_loader)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -29,7 +29,13 @@ module OpenHAB
29
29
  @thing = thing
30
30
  end
31
31
 
32
- def handle_command(channel, command); end
32
+ def handle_command(channel_uid, command)
33
+ channel = thing.get_channel(channel_uid)
34
+ return unless channel
35
+ return if channel.auto_update_policy == org.openhab.core.thing.type.AutoUpdatePolicy::VETO
36
+
37
+ callback&.state_updated(channel_uid, command) if command.is_a?(Core::Types::State)
38
+ end
33
39
 
34
40
  def set_callback(callback)
35
41
  @callback = callback
@@ -72,6 +72,42 @@ module OpenHAB
72
72
  end
73
73
  Timecop::TimeStackItem.prepend(TimeCopStackItem)
74
74
 
75
+ class << self
76
+ # If timers are currently mocked
77
+ # @return [true, false]
78
+ def mock_timers?
79
+ @mock_timers
80
+ end
81
+
82
+ #
83
+ # Temporarily mock or unmock timers
84
+ #
85
+ # @param [true, false] mock_timers if timers should be mocked
86
+ # @yield
87
+ # @return [Object] the block's return value
88
+ def mock_timers(mock_timers)
89
+ old_mock_timers = @mock_timers
90
+ @mock_timers = mock_timers
91
+ yield
92
+ ensure
93
+ @mock_timers = old_mock_timers
94
+ end
95
+ end
96
+
97
+ @mock_timers = true
98
+
99
+ # @!visibility private
100
+ module ClassMethods
101
+ # @!visibility private
102
+ def new(*args, **kwargs)
103
+ return super if self == Timer
104
+ return Timer.new(*args, **kwargs) if Timer.mock_timers?
105
+
106
+ super
107
+ end
108
+ end
109
+ Core::Timer.singleton_class.prepend(ClassMethods)
110
+
75
111
  attr_reader :execution_time, :id, :block
76
112
 
77
113
  def initialize(time, id:, thread_locals:, block:) # rubocop:disable Lint/MissingSuper
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.13.0
4
+ version: 5.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-01-04 00:00:00.000000000 Z
13
+ date: 2024-01-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -546,6 +546,7 @@ files:
546
546
  - lib/openhab/rspec/hooks.rb
547
547
  - lib/openhab/rspec/jruby.rb
548
548
  - lib/openhab/rspec/karaf.rb
549
+ - lib/openhab/rspec/mocks/abstract_storage_based_type_provider_wrapped_storage_service.rb
549
550
  - lib/openhab/rspec/mocks/bundle_install_support.rb
550
551
  - lib/openhab/rspec/mocks/bundle_resolver.rb
551
552
  - lib/openhab/rspec/mocks/event_admin.rb
@@ -607,7 +608,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
607
608
  - !ruby/object:Gem::Version
608
609
  version: '0'
609
610
  requirements: []
610
- rubygems_version: 3.3.26
611
+ rubygems_version: 3.5.4
611
612
  signing_key:
612
613
  specification_version: 4
613
614
  summary: JRuby Helper Libraries for openHAB Scripting