openhab-scripting 5.13.0 → 5.15.0

Sign up to get free protection for your applications and to get access to all the features.
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