openhab-jrubyscripting 5.0.0.rc11 → 5.0.0.rc.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/exec.rb +41 -41
  3. data/lib/openhab/core/actions/transformation.rb +3 -3
  4. data/lib/openhab/core/actions.rb +1 -1
  5. data/lib/openhab/core/events/item_command_event.rb +31 -31
  6. data/lib/openhab/core/events/item_state_changed_event.rb +41 -18
  7. data/lib/openhab/core/events/item_state_event.rb +46 -18
  8. data/lib/openhab/core/items/date_time_item.rb +3 -2
  9. data/lib/openhab/core/items/generic_item.rb +119 -1
  10. data/lib/openhab/core/items/item.rb +63 -9
  11. data/lib/openhab/core/items/metadata/hash.rb +1 -1
  12. data/lib/openhab/core/items/metadata/namespace_hash.rb +10 -2
  13. data/lib/openhab/core/items/metadata/provider.rb +2 -2
  14. data/lib/openhab/core/items/persistence.rb +48 -4
  15. data/lib/openhab/core/items/provider.rb +4 -0
  16. data/lib/openhab/core/items/registry.rb +10 -1
  17. data/lib/openhab/core/items/semantics/enumerable.rb +29 -6
  18. data/lib/openhab/core/items/state_storage.rb +2 -2
  19. data/lib/openhab/core/items.rb +6 -13
  20. data/lib/openhab/core/provider.rb +2 -2
  21. data/lib/openhab/core/proxy.rb +5 -0
  22. data/lib/openhab/core/registry.rb +12 -2
  23. data/lib/openhab/core/rules/provider.rb +0 -15
  24. data/lib/openhab/core/rules.rb +1 -1
  25. data/lib/openhab/core/script_handling.rb +8 -8
  26. data/lib/openhab/core/things/links/provider.rb +38 -0
  27. data/lib/openhab/core/things/provider.rb +4 -0
  28. data/lib/openhab/core/things/registry.rb +4 -0
  29. data/lib/openhab/core/timer.rb +3 -19
  30. data/lib/openhab/core/types/date_time_type.rb +1 -1
  31. data/lib/openhab/core/types/decimal_type.rb +4 -9
  32. data/lib/openhab/core/types/hsb_type.rb +2 -2
  33. data/lib/openhab/core/types/quantity_type.rb +4 -9
  34. data/lib/openhab/core/types/string_type.rb +1 -1
  35. data/lib/openhab/core/types/type.rb +8 -28
  36. data/lib/openhab/core/types.rb +16 -3
  37. data/lib/openhab/core.rb +3 -3
  38. data/lib/openhab/core_ext/java/duration.rb +2 -0
  39. data/lib/openhab/core_ext/java/local_date.rb +15 -7
  40. data/lib/openhab/core_ext/java/local_time.rb +13 -3
  41. data/lib/openhab/core_ext/java/month.rb +1 -1
  42. data/lib/openhab/core_ext/java/month_day.rb +13 -3
  43. data/lib/openhab/core_ext/java/period.rb +1 -1
  44. data/lib/openhab/core_ext/java/temporal_amount.rb +1 -1
  45. data/lib/openhab/core_ext/java/time.rb +5 -1
  46. data/lib/openhab/core_ext/java/zoned_date_time.rb +15 -2
  47. data/lib/openhab/core_ext/ruby/date.rb +2 -2
  48. data/lib/openhab/core_ext/ruby/{class.rb → module.rb} +3 -3
  49. data/lib/openhab/core_ext/ruby/numeric.rb +6 -1
  50. data/lib/openhab/dsl/items/builder.rb +25 -12
  51. data/lib/openhab/dsl/items/ensure.rb +8 -6
  52. data/lib/openhab/dsl/rules/automation_rule.rb +2 -23
  53. data/lib/openhab/dsl/rules/builder.rb +47 -2
  54. data/lib/openhab/dsl/rules/terse.rb +15 -13
  55. data/lib/openhab/dsl/timer_manager.rb +1 -1
  56. data/lib/openhab/dsl/version.rb +1 -1
  57. data/lib/openhab/dsl.rb +38 -11
  58. data/lib/openhab/osgi.rb +1 -3
  59. data/lib/openhab/rspec/helpers.rb +3 -5
  60. data/lib/openhab/rspec/hooks.rb +1 -0
  61. data/lib/openhab/rspec/mocks/timer.rb +33 -0
  62. data/lib/openhab/rspec.rb +9 -0
  63. metadata +23 -9
@@ -24,10 +24,6 @@ module OpenHAB
24
24
  # The item's name.
25
25
  # @return [String]
26
26
 
27
- # @!attribute [r] label
28
- # The item's descriptive label.
29
- # @return [String, nil]
30
-
31
27
  # @!attribute [r] accepted_command_types
32
28
  # @return [Array<Class>] An array of {Command}s that can be sent as commands to this item
33
29
 
@@ -35,7 +31,7 @@ module OpenHAB
35
31
  # @return [Array<Class>] An array of {State}s that can be sent as commands to this item
36
32
 
37
33
  #
38
- # The item's {#label} if one is defined, otherwise it's {#name}.
34
+ # The item's {GenericItem#label label} if one is defined, otherwise its {#name}.
39
35
  #
40
36
  # @return [String]
41
37
  #
@@ -46,14 +42,51 @@ module OpenHAB
46
42
  #
47
43
  # @!attribute [r] groups
48
44
  #
49
- # Return all groups that this item is part of
45
+ # Returns all groups that this item is part of
50
46
  #
51
- # @return [Array<Group>] All groups that this item is part of
47
+ # @return [Array<GroupItem>] All groups that this item is part of
52
48
  #
53
49
  def groups
54
50
  group_names.map { |name| EntityLookup.lookup_item(name) }.compact
55
51
  end
56
52
 
53
+ #
54
+ # Checks if this item is a member of at least one of the given groups.
55
+ #
56
+ # @param groups [String, GroupItem] the group to check membership in
57
+ # @return [true, false]
58
+ #
59
+ # @example
60
+ # event.item.member_of?(gFullOn)
61
+ #
62
+ def member_of?(*groups)
63
+ groups = groups.map! do |group|
64
+ group.is_a?(GroupItem) ? group.name : group
65
+ end
66
+ !(group_names & groups).empty?
67
+ end
68
+
69
+ #
70
+ # @!attribute [r] all_groups
71
+ #
72
+ # Returns all groups that this item is a part of, as well as those groups' groups, recursively
73
+ #
74
+ # @return [Array<GroupItem>]
75
+ #
76
+ def all_groups
77
+ result = []
78
+ new_groups = Set.new(groups)
79
+
80
+ until new_groups.empty?
81
+ result.concat(new_groups.to_a)
82
+ new_groups.replace(new_groups.flat_map(&:groups))
83
+ # remove any groups we already have in the result to avoid loops
84
+ new_groups.subtract(result)
85
+ end
86
+
87
+ result
88
+ end
89
+
57
90
  # rubocop:disable Layout/LineLength
58
91
 
59
92
  # @!attribute [r] metadata
@@ -81,7 +114,7 @@ module OpenHAB
81
114
  # @example Access namespace1's configuration
82
115
  # Item1.metadata["namespace1"]["config1"]
83
116
  #
84
- # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn"t exist
117
+ # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn't exist
85
118
  # Item1.metadata.dig("namespace1", "config1") # => "foo"
86
119
  # Item1.metadata.dig("namespace2", "config1") # => nil
87
120
  #
@@ -176,6 +209,22 @@ module OpenHAB
176
209
  end
177
210
  # rubocop:enable Layout/LineLength
178
211
 
212
+ #
213
+ # Checks if this item has at least one of the given tags.
214
+ #
215
+ # @param tags [String, Module] the tag(s) to check
216
+ # @return [true, false]
217
+ #
218
+ # @example
219
+ # event.item.tagged?("Setpoint")
220
+ #
221
+ def tagged?(*tags)
222
+ tags = tags.map! do |tag|
223
+ tag.is_a?(Module) ? tag.simple_name : tag
224
+ end
225
+ !(self.tags.to_a & tags).empty?
226
+ end
227
+
179
228
  # Return the item's thing if this item is linked with a thing. If an item is linked to more than one thing,
180
229
  # this method only returns the first thing.
181
230
  #
@@ -189,7 +238,7 @@ module OpenHAB
189
238
  #
190
239
  # @return [Array<Thing>] An array of things or an empty array
191
240
  def things
192
- registry = OSGi.service("org.openhab.core.thing.link.ItemChannelLinkRegistry")
241
+ registry = Things::Links::Provider.registry
193
242
  channels = registry.get_bound_channels(name).to_a
194
243
  channels.map(&:thing_uid).uniq.map { |tuid| EntityLookup.lookup_thing(tuid) }.compact
195
244
  end
@@ -206,6 +255,11 @@ module OpenHAB
206
255
  "#{s}>"
207
256
  end
208
257
 
258
+ # @return [org.openhab.core.common.registry.Provider]
259
+ def provider
260
+ Provider.registry.provider_for(self)
261
+ end
262
+
209
263
  private
210
264
 
211
265
  # Allows sub-classes to append additional details to the type in an inspect string
@@ -384,7 +384,7 @@ module OpenHAB
384
384
  alias_method :to_s, :inspect
385
385
 
386
386
  #
387
- # @raise [RuntimeError] if the provider is not a
387
+ # @raise [FrozenError] if the provider is not a
388
388
  # {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that can be updated.
389
389
  # @return [org.openhab.core.common.registry.ManagedProvider]
390
390
  #
@@ -218,8 +218,12 @@ module OpenHAB
218
218
  return @hash.each_key(&block) unless attached?
219
219
  return to_enum(:each_key) unless block
220
220
 
221
- Provider.registry.all.each do |meta|
222
- yield meta.uid.namespace if meta.uid.item_name == @item_name
221
+ if Provider.registry.respond_to?(:get_all_namespaces)
222
+ keys.each(&block)
223
+ else
224
+ Provider.registry.all.each do |meta|
225
+ yield meta.uid.namespace if meta.uid.item_name == @item_name
226
+ end
223
227
  end
224
228
  self
225
229
  end
@@ -313,6 +317,10 @@ module OpenHAB
313
317
 
314
318
  # @!visibility private
315
319
  def keys
320
+ if Provider.registry.respond_to?(:get_all_namespaces)
321
+ return Provider.registry.get_all_namespaces(@item_name).to_a
322
+ end
323
+
316
324
  each_key.to_a
317
325
  end
318
326
 
@@ -32,8 +32,8 @@ module OpenHAB
32
32
  # @return [void]
33
33
  #
34
34
  def remove_item_metadata(item_name)
35
- @elements.delete_if do |k, v|
36
- next unless k.item_name == item_name
35
+ @elements.delete_if do |_k, v|
36
+ next unless v.uid.item_name == item_name
37
37
 
38
38
  notify_listeners_about_removed_element(v)
39
39
  true
@@ -77,7 +77,6 @@ module OpenHAB
77
77
  %i[changed_since?
78
78
  count_since
79
79
  count_state_changes_since
80
- evolution_rate
81
80
  historic_state
82
81
  maximum_since
83
82
  minimum_since
@@ -183,11 +182,22 @@ module OpenHAB
183
182
  # @return [true,false] True if the item's state changed between `start` and `finish`, False otherwise.
184
183
 
185
184
  # @!method evolution_rate(timestamp, service = nil)
186
- # Returns the evolution rate of the item's state since the given time
187
- # @param [#to_zoned_date_time] timestamp The point in time from which to search
188
- # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
185
+ # Returns the evolution rate of the item's state
189
186
  # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
190
187
  # or nil if no previous state could be found.
188
+ # @overload evolution_rate(timestamp, service = nil)
189
+ # Returns the evolution rate of the item's state since the given time
190
+ # @param [#to_zoned_date_time] timestamp The point in time from which to search
191
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
192
+ # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
193
+ # or nil if no previous state could be found.
194
+ # @overload evolution_rate(start, finish, service = nil)
195
+ # Returns the evolution rate of the item's state between two points in time
196
+ # @param [#to_zoned_date_time] start The point in time from which to search
197
+ # @param [#to_zoned_date_time] finish The point in time to which to search
198
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
199
+ # @return [DecimalType, QuantityType, nil] The evolution rate between `start` and `finish`,
200
+ # or nil if no previous state could be found.
191
201
 
192
202
  # @!method historic_state(timestamp, service = nil)
193
203
  # Returns the the item's state at the given time
@@ -317,6 +327,40 @@ module OpenHAB
317
327
  end
318
328
  end
319
329
 
330
+ # evolution_rate's "between" method is overloaded with the same name
331
+ method = :evolution_rate
332
+ define_method(method) do |start, finish_or_service = nil, service = nil|
333
+ if service.nil?
334
+ if finish_or_service.respond_to?(:to_zoned_date_time)
335
+ service = persistence_service
336
+ finish = finish_or_service
337
+ else
338
+ service = finish_or_service || persistence_service
339
+ finish = nil
340
+ end
341
+ else
342
+ finish = finish_or_service
343
+ end
344
+
345
+ result = if finish
346
+ Actions::PersistenceExtensions.public_send(
347
+ method,
348
+ self,
349
+ start.to_zoned_date_time,
350
+ finish.to_zoned_date_time,
351
+ service&.to_s
352
+ )
353
+ else
354
+ Actions::PersistenceExtensions.public_send(
355
+ method,
356
+ self,
357
+ start.to_zoned_date_time,
358
+ service&.to_s
359
+ )
360
+ end
361
+ wrap_result(result, method)
362
+ end
363
+
320
364
  alias_method :state_changes_since, :count_state_changes_since
321
365
  alias_method :state_changes_between, :count_state_changes_between
322
366
 
@@ -34,6 +34,10 @@ module OpenHAB
34
34
  item.members.each { |member| remove(member.name, true) } if recursive && item.is_a?(GroupItem)
35
35
  item
36
36
  end
37
+
38
+ def initialize
39
+ super(unload_priority: 50)
40
+ end
37
41
  end
38
42
  end
39
43
  end
@@ -59,16 +59,25 @@ module OpenHAB
59
59
  #
60
60
  # The item must be a managed item (typically created by Ruby or in the UI).
61
61
  #
62
+ # Any associated metadata or channel links are also removed.
63
+ #
62
64
  # @param [String, Item] item_name
63
65
  # @param recursive [true, false] Remove the item's members if it's a group
64
66
  # @return [Item, nil] The removed item, if found.
65
67
  def remove(item_name, recursive: false)
66
68
  item_name = item_name.name if item_name.is_a?(Item)
67
69
  provider = Provider.registry.provider_for(item_name)
68
- unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
70
+ unless provider.is_a?(ManagedProvider)
69
71
  raise "Cannot remove item #{item_name} from non-managed provider #{provider.inspect}"
70
72
  end
71
73
 
74
+ Metadata::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
75
+ managed_provider.remove_item_metadata(item_name)
76
+ end
77
+
78
+ Things::Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
79
+ managed_provider.remove_links_for_item(item_name)
80
+ end
72
81
  provider.remove(item_name, recursive)
73
82
  end
74
83
  end
@@ -40,33 +40,56 @@ module Enumerable
40
40
  #
41
41
 
42
42
  # Returns a new array of items that have at least one of the given tags
43
+ #
44
+ # @param tags [String, Module]
43
45
  # @return [Array<Item>]
44
46
  def tagged(*tags)
45
- reject { |i| (tags & i.tags.to_a).empty? }
47
+ select { |i| i.tagged?(*tags) }
46
48
  end
47
49
 
48
50
  # Returns a new array of items that do not have any of the given tags
51
+ # @param tags [String, Module]
49
52
  # @return [Array<Item>]
50
53
  def not_tagged(*tags)
51
- select { |i| (tags & i.tags.to_a).empty? }
54
+ reject { |i| i.tagged?(*tags) }
52
55
  end
53
56
 
54
57
  # Returns a new array of items that are a member of at least one of the given groups
58
+ # @param groups [String, GroupItem]
55
59
  # @return [Array<Item>]
56
60
  def member_of(*groups)
57
- reject { |i| (groups.map(&:name) & i.group_names).empty? }
61
+ select { |i| i.member_of?(*groups) }
58
62
  end
59
63
 
60
64
  # Returns a new array of items that are not a member of any of the given groups
65
+ # @param groups [String, GroupItem]
61
66
  # @return [Array<Item>]
62
67
  def not_member_of(*groups)
63
- select { |i| (groups.map(&:name) & i.group_names).empty? }
68
+ reject { |i| i.member_of?(*groups) }
64
69
  end
65
70
 
66
- # Returns the group members the elements
71
+ # Returns the group members of all group elements
67
72
  # @return [Array<Item>]
68
73
  def members
69
- grep(OpenHAB::Core::Items::GroupItem).flat_map(&:members)
74
+ grep(OpenHAB::Core::Items::GroupItem).flat_map(&:members).uniq
75
+ end
76
+
77
+ # Returns all non-group members of all group elements, recursively
78
+ # @return [Array<Item>]
79
+ def all_members
80
+ grep(OpenHAB::Core::Items::GroupItem).flat_map(&:all_members).uniq
81
+ end
82
+
83
+ # Returns the groups of all elements
84
+ # @return [Array<GroupItem>]
85
+ def groups
86
+ flat_map(&:groups).uniq
87
+ end
88
+
89
+ # Returns all groups all elements are a part of, recursively
90
+ # @return [Array<GroupItem>]
91
+ def all_groups
92
+ flat_map(&:all_groups).uniq
70
93
  end
71
94
 
72
95
  # @!group Items State and Command Methods
@@ -12,13 +12,13 @@ module OpenHAB
12
12
  #
13
13
  # Create a StateStorage object that stores the states of the given items
14
14
  #
15
- # @param [Array<Item>] items A list of items
15
+ # @param [Item] items A list of items
16
16
  #
17
17
  # @return [StateStorage] A state storage object
18
18
  #
19
19
  # @!visibility private
20
20
  def self.from_items(*items)
21
- StateStorage.new($events.store_states(*items).to_h)
21
+ StateStorage.new($events.store_states(*items.map(&:to_java)).to_h)
22
22
  end
23
23
 
24
24
  #
@@ -46,9 +46,9 @@ module OpenHAB
46
46
 
47
47
  logger.trace("Defining #{klass}##{state_predicate} for #{state}")
48
48
  klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
49
- def #{state_predicate} # def on?
50
- raw_state == #{state} # raw_state == ON
51
- end # end
49
+ def #{state_predicate} # def on?
50
+ raw_state.as(#{state.class.java_class.simple_name}).equal?(#{state}) # raw_state.as(OnOffType) == ON
51
+ end # end
52
52
  RUBY
53
53
  end
54
54
  end
@@ -74,18 +74,11 @@ module OpenHAB
74
74
  end # end
75
75
  RUBY
76
76
 
77
- # Override the inherited methods from Enumerable and send it to the base_item
78
- GroupItem.class_eval <<~RUBY, __FILE__, __LINE__ + 1
79
- def #{command} # def on
80
- method_missing(:#{command}) # method_missing(:on)
81
- end # end
82
- RUBY
83
-
84
77
  logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
85
78
  Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
86
- def #{command}? # def refresh?
87
- command == #{value} # command == REFRESH
88
- end # end
79
+ def #{command}? # def refresh?
80
+ command.as(#{value.class.java_class.simple_name}).equal?(#{value}) # command.as(RefreshType).equal?(REFRESH)
81
+ end # end
89
82
  RUBY
90
83
  end
91
84
  end
@@ -219,11 +219,11 @@ module OpenHAB
219
219
 
220
220
  private
221
221
 
222
- def initialize(script_unloaded_before: nil)
222
+ def initialize(unload_priority: nil)
223
223
  super()
224
224
  @elements = java.util.concurrent.ConcurrentHashMap.new
225
225
  self.class.registry.add_provider(self)
226
- ScriptHandling.script_unloaded(before: script_unloaded_before) { unregister }
226
+ ScriptHandling.script_unloaded(priority: unload_priority) { unregister }
227
227
  end
228
228
  end
229
229
  end
@@ -120,6 +120,11 @@ module OpenHAB
120
120
  # define a sub-class of EventSubscriber as a child class of the including class
121
121
  klass.const_set(:EventSubscriber, Class.new(EventSubscriber))
122
122
  end
123
+
124
+ # @!visibility private
125
+ def to_java
126
+ __getobj__
127
+ end
123
128
  end
124
129
  end
125
130
  end
@@ -4,7 +4,7 @@ module OpenHAB
4
4
  module Core
5
5
  Registry = org.openhab.core.common.registry.AbstractRegistry
6
6
 
7
- Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement
7
+ Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement, :providerToElements
8
8
 
9
9
  # @abstract
10
10
  #
@@ -19,12 +19,22 @@ module OpenHAB
19
19
  #
20
20
  def provider_for(key)
21
21
  elementReadLock.lock
22
- return nil unless (element = identifierToElement[key])
22
+ if key.is_a?(org.openhab.core.common.registry.Identifiable)
23
+ element = key
24
+ else
25
+ return nil unless (element = identifierToElement[key])
26
+ end
23
27
 
24
28
  elementToProvider[element]
25
29
  ensure
26
30
  elementReadLock.unlock
27
31
  end
32
+
33
+ # @!attribute [r] providers
34
+ # @return [Enumerable<org.openhab.core.common.registry.Provider>]
35
+ def providers
36
+ providerToElements.keys
37
+ end
28
38
  end
29
39
  end
30
40
  end
@@ -19,21 +19,6 @@ module OpenHAB
19
19
  $rules
20
20
  end
21
21
  end
22
-
23
- def initialize
24
- super(script_unloaded_before: lambda do |callbacks|
25
- callbacks.index do |cb|
26
- case cb.binding.receiver
27
- when Items::Provider,
28
- Things::Provider,
29
- DSL::TimerManager
30
- true
31
- else
32
- false
33
- end
34
- end
35
- end)
36
- end
37
22
  end
38
23
  end
39
24
  end
@@ -13,7 +13,7 @@ module OpenHAB
13
13
 
14
14
  class << self
15
15
  #
16
- # @!attribute [r] rule_manager
16
+ # @!attribute [r] manager
17
17
  # @return [org.openhab.core.automation.RuleManager] The openHAB rule manager/engine
18
18
  #
19
19
  def manager
@@ -32,8 +32,6 @@ module OpenHAB
32
32
  ScriptHandlingCallbacks.script_loaded_hooks << block
33
33
  end
34
34
 
35
- #
36
- # @!method script_unloaded(&block)
37
35
  #
38
36
  # Add a block of code to be executed when the script is unloaded.
39
37
  #
@@ -42,6 +40,10 @@ module OpenHAB
42
40
  # Multiple hooks can be added by calling {#script_unloaded} multiple times.
43
41
  # They can be used to perform final cleanup.
44
42
  #
43
+ # @param [Integer, nil] priority The order at which the the given hook will be executed.
44
+ # The higher the number, the lower the priority. Higher priority hooks will be executed
45
+ # first, before the lower priority hooks. When nil, the default priority of zero will
46
+ # be used.
45
47
  # @return [void]
46
48
  #
47
49
  # @example
@@ -49,10 +51,8 @@ module OpenHAB
49
51
  # logger.info 'Hi, this script has been unloaded'
50
52
  # end
51
53
  #
52
- def script_unloaded(before: nil, &block)
53
- # `before` is as yet undocumented, because I'm not set on its interface
54
- index = before.call(ScriptHandlingCallbacks.script_unloaded_hooks) if before
55
- ScriptHandlingCallbacks.script_unloaded_hooks.insert(index || -1, block)
54
+ def script_unloaded(priority: nil, &block)
55
+ ScriptHandlingCallbacks.script_unloaded_hooks[priority || 0] << block
56
56
  end
57
57
  end
58
58
 
@@ -82,7 +82,7 @@ module OpenHAB
82
82
  #
83
83
  # @!visibility private
84
84
  def script_unloaded_hooks
85
- @script_unloaded_hooks ||= []
85
+ @script_unloaded_hooks ||= Hash.new { |hash, key| hash[key] = [] }
86
86
  end
87
87
  end
88
88
  self.script_loaded = false
@@ -92,7 +92,7 @@ module OpenHAB
92
92
  #
93
93
  def scriptUnloaded # rubocop:disable Naming/MethodName method name dictated by openHAB
94
94
  logger.trace("Script unloaded")
95
- ScriptHandlingCallbacks.script_unloaded_hooks.each do |hook|
95
+ ScriptHandlingCallbacks.script_unloaded_hooks.sort_by(&:first).flat_map(&:last).each do |hook|
96
96
  hook.call
97
97
  rescue => e
98
98
  logger.error("Failed to call script_unloaded hook #{hook}: #{e}")
@@ -33,6 +33,44 @@ module OpenHAB
33
33
  current.add(link)
34
34
  end
35
35
  end
36
+
37
+ #
38
+ # Removes all links to a given item.
39
+ #
40
+ # @param [String] item_name
41
+ # @return [Integer] how many links were removed
42
+ #
43
+ def remove_links_for_item(item_name)
44
+ count = 0
45
+ @elements.delete_if do |_k, v|
46
+ next unless v.item_name == item_name
47
+
48
+ count += 1
49
+ notify_listeners_about_removed_element(v)
50
+ true
51
+ end
52
+ count
53
+ end
54
+ alias_method :removeLinksForItem, :remove_links_for_item
55
+
56
+ #
57
+ # Removes all links to a given thing.
58
+ #
59
+ # @param [ThingUID] thing_uid
60
+ # @return [Integer] how many links were removed
61
+ #
62
+ def remove_links_for_thing(thing_uid)
63
+ count = 0
64
+ @elements.delete_if do |_k, v|
65
+ next unless v.linked_uid.thing_uid == thing_uid
66
+
67
+ count += 1
68
+ notify_listeners_about_removed_element(v)
69
+ true
70
+ end
71
+ count
72
+ end
73
+ alias_method :removeLinksForThing, :remove_links_for_thing
36
74
  end
37
75
  end
38
76
  end
@@ -19,6 +19,10 @@ module OpenHAB
19
19
  $things
20
20
  end
21
21
  end
22
+
23
+ def initialize
24
+ super(unload_priority: 60)
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -61,6 +61,10 @@ module OpenHAB
61
61
  raise "Cannot remove thing #{thing_uid} from non-managed provider #{provider.inspect}"
62
62
  end
63
63
 
64
+ Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
65
+ managed_provider.remove_links_for_thing(thing_uid)
66
+ end
67
+
64
68
  provider.remove(thing_uid)
65
69
  end
66
70
  end
@@ -28,7 +28,7 @@ module OpenHAB
28
28
  # @return [true,false]
29
29
 
30
30
  def_delegator :@timer, :has_terminated, :terminated?
31
- def_delegators :@timer, :active?, :cancelled?, :running?
31
+ def_delegators :@timer, :active?, :cancelled?, :running?, :execution_time
32
32
 
33
33
  # @return [Object, nil]
34
34
  attr_accessor :id
@@ -49,19 +49,7 @@ module OpenHAB
49
49
  @id = id
50
50
  @thread_locals = thread_locals
51
51
  @block = block
52
- @timer = if defined?(ScriptExecution)
53
- ScriptExecution.create_timer(1.minute.from_now) { execute }
54
- else # DEPRECATED: openHAB 3.4.0
55
- org.openhab.core.model.script.actions.ScriptExecution.create_timer(
56
- # create it far enough in the future so it won't execute until we finish setting it up
57
- 1.minute.from_now,
58
- # when running in rspec, it may have troubles finding this class
59
- # for auto-conversion of block to interface, so use .impl
60
- org.eclipse.xtext.xbase.lib.Procedures::Procedure0.impl { execute }
61
- )
62
- end
63
- # DEPRECATED: openHAB 3.4.0.M6
64
- @timer.class.field_reader :future unless @timer.respond_to?(:future)
52
+ @timer = ScriptExecution.create_timer(1.minute.from_now) { execute }
65
53
  reschedule(@time)
66
54
  end
67
55
 
@@ -79,11 +67,7 @@ module OpenHAB
79
67
  alias_method :to_s, :inspect
80
68
 
81
69
  # @!attribute [r] execution_time
82
- # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
83
- def execution_time
84
- # DEPRECATED: openHAB 3.4.0.M6 (just remove the entire method)
85
- @timer.future.scheduled_time
86
- end
70
+ # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
87
71
 
88
72
  #
89
73
  # Reschedule timer
@@ -46,7 +46,7 @@ module OpenHAB
46
46
  rescue java.lang.StringIndexOutOfBoundsException, java.lang.IllegalArgumentException => e
47
47
  # Try Ruby's Time.parse if DateTimeType parser fails
48
48
  begin
49
- ::Time.parse(time_string).to_zoned_date_time
49
+ DateTimeType.new(::Time.parse(time_string).to_zoned_date_time)
50
50
  rescue ArgumentError
51
51
  raise ArgumentError, e.message
52
52
  end