openhab-jrubyscripting 5.0.0.rc2 → 5.0.0.rc4

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions.rb +6 -2
  3. data/lib/openhab/core/items/generic_item.rb +13 -5
  4. data/lib/openhab/core/items/metadata/hash.rb +19 -35
  5. data/lib/openhab/core/items/persistence.rb +3 -1
  6. data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
  7. data/lib/openhab/core/items/semantics.rb +18 -22
  8. data/lib/openhab/core/profile_factory.rb +15 -3
  9. data/lib/openhab/core/provider.rb +11 -4
  10. data/lib/openhab/core/rules/module.rb +26 -0
  11. data/lib/openhab/core/rules/provider.rb +40 -0
  12. data/lib/openhab/core/rules/registry.rb +76 -0
  13. data/lib/openhab/core/rules/rule.rb +150 -0
  14. data/lib/openhab/core/rules.rb +25 -0
  15. data/lib/openhab/core/script_handling.rb +32 -3
  16. data/lib/openhab/core/timer.rb +5 -7
  17. data/lib/openhab/core/types.rb +1 -1
  18. data/lib/openhab/core.rb +0 -16
  19. data/lib/openhab/core_ext/java/list.rb +436 -0
  20. data/lib/openhab/core_ext/java/map.rb +66 -0
  21. data/lib/openhab/core_ext/java/month.rb +1 -1
  22. data/lib/openhab/core_ext/java/zoned_date_time.rb +1 -2
  23. data/lib/openhab/core_ext/ruby/date.rb +3 -0
  24. data/lib/openhab/core_ext/ruby/date_time.rb +53 -0
  25. data/lib/openhab/core_ext/ruby/time.rb +88 -86
  26. data/lib/openhab/dsl/events/watch_event.rb +1 -1
  27. data/lib/openhab/dsl/items/builder.rb +8 -3
  28. data/lib/openhab/dsl/items/ensure.rb +6 -2
  29. data/lib/openhab/dsl/items/timed_command.rb +10 -11
  30. data/lib/openhab/dsl/rules/automation_rule.rb +36 -13
  31. data/lib/openhab/dsl/rules/builder.rb +100 -9
  32. data/lib/openhab/dsl/rules/name_inference.rb +0 -5
  33. data/lib/openhab/dsl/rules/rule_triggers.rb +1 -1
  34. data/lib/openhab/dsl/rules/terse.rb +1 -2
  35. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +18 -54
  36. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +0 -3
  37. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
  38. data/lib/openhab/dsl/rules.rb +0 -21
  39. data/lib/openhab/dsl/thread_local.rb +2 -2
  40. data/lib/openhab/dsl/timer_manager.rb +3 -1
  41. data/lib/openhab/dsl/version.rb +1 -1
  42. data/lib/openhab/dsl.rb +12 -105
  43. data/lib/openhab/log.rb +9 -2
  44. data/lib/openhab/rspec/example_group.rb +42 -0
  45. data/lib/openhab/rspec/helpers.rb +31 -8
  46. data/lib/openhab/rspec/hooks.rb +6 -10
  47. data/lib/openhab/rspec/karaf.rb +50 -27
  48. data/lib/openhab/rspec/mocks/synchronous_executor.rb +11 -4
  49. data/lib/openhab/rspec/mocks/timer.rb +2 -1
  50. data/lib/openhab/rspec/suspend_rules.rb +4 -2
  51. metadata +24 -3
  52. data/lib/openhab/dsl/script_handling.rb +0 -6
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Rules
6
+ # @interface
7
+ java_import org.openhab.core.automation.Rule
8
+
9
+ #
10
+ # A {Rule} is a chunk of code that can execute when certain conditions are
11
+ # met, enabling the core dynamic functionality of openHAB.
12
+ #
13
+ module Rule
14
+ #
15
+ # @!method visible?
16
+ # Check if visibility == `VISIBLE`
17
+ # @return [true,false]
18
+ #
19
+
20
+ #
21
+ # @!method hidden?
22
+ # Check if visibility == `HIDDEN`
23
+ # @return [true,false]
24
+ #
25
+
26
+ #
27
+ # @!method expert?
28
+ # Check if visibility == `EXPERT`
29
+ # @return [true,false]
30
+ #
31
+
32
+ #
33
+ # @!method initializing?
34
+ # Check if rule status == `INITIALIZING`
35
+ # @return [true,false]
36
+ #
37
+ #
38
+ # @!method idle?
39
+ # Check if rule status == `IDLE`
40
+ # @return [true,false]
41
+ #
42
+ #
43
+ # @!method running?
44
+ # Check if rule status == `RUNNING`
45
+ # @return [true,false]
46
+ #
47
+
48
+ Visibility.constants.each do |visibility|
49
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
50
+ def #{visibility.to_s.downcase}? # def visibile?
51
+ visibility == Visibility::#{visibility} # visibility == Visibility::VISIBLE
52
+ end # end
53
+ RUBY
54
+ end
55
+
56
+ RuleStatus.constants.each do |status|
57
+ next if status == :UNINITIALIZED
58
+
59
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
60
+ def #{status.to_s.downcase}? # def initializing?
61
+ status == RuleStatus::#{status} # status == RuleStatus::INITIALIZING
62
+ end # end
63
+ RUBY
64
+ end
65
+
66
+ #
67
+ # Check if rule status == `UNINITIALIZED`
68
+ #
69
+ # @return [true,false]
70
+ #
71
+ def uninitialized?
72
+ s = status
73
+ s.nil? || s == RuleStatus::UNINITIALIZED
74
+ end
75
+
76
+ #
77
+ # Enable the Rule
78
+ #
79
+ # @param [true, false] enabled
80
+ # @return [void]
81
+ #
82
+ def enable(enabled: true)
83
+ Rules.manager.set_enabled(uid, enabled)
84
+ end
85
+
86
+ #
87
+ # Disable the Rule
88
+ #
89
+ # @return [void]
90
+ #
91
+ def disable
92
+ enable(enabled: false)
93
+ end
94
+
95
+ #
96
+ # Check if the rule's status detail == `DISABLED`
97
+ #
98
+ # @return [true, false]
99
+ #
100
+ def disabled?
101
+ info = status_info
102
+ info.nil? || info.status_detail == RuleStatusDetail::DISABLED
103
+ end
104
+
105
+ #
106
+ # @!attribute [r] status
107
+ # @return [RuleStatus nil]
108
+ #
109
+ def status
110
+ Rules.manager.get_status(uid)
111
+ end
112
+
113
+ #
114
+ # @!attribute [r] status_info
115
+ # @return [RuleStatusInfo, nil]
116
+ #
117
+ def status_info
118
+ Rules.manager.get_status_info(uid)
119
+ end
120
+
121
+ # @return [String]
122
+ def inspect
123
+ r = "#<OpenHAB::Core::Rules::Rule #{uid}"
124
+ r += " #{name.inspect}" if name
125
+ r += " #{visibility}" unless visible?
126
+ r += " #{status || "<detached>"}"
127
+ r += " (#{status_info.status_detail})" if status_info && status_info.status_detail != RuleStatusDetail::NONE
128
+ r += " tags=#{tags.to_a.inspect}" unless tags.empty?
129
+ r += " configuration=#{configuration.properties.to_h}" if configuration && !configuration.properties.empty?
130
+ "#{r}>"
131
+ end
132
+
133
+ # @return [String]
134
+ def to_s
135
+ uid
136
+ end
137
+
138
+ #
139
+ # Manually trigger the rule
140
+ #
141
+ # @param [Object, nil] event The event to pass to the rule's execution blocks.
142
+ # @return [void]
143
+ #
144
+ def trigger(event = nil)
145
+ Rules.manager.run_now(uid, false, { "event" => event })
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ #
6
+ # Contains the core {Rule} as well as related infrastructure.
7
+ #
8
+ module Rules
9
+ java_import org.openhab.core.automation.RuleStatus,
10
+ org.openhab.core.automation.RuleStatusInfo,
11
+ org.openhab.core.automation.RuleStatusDetail,
12
+ org.openhab.core.automation.Visibility
13
+
14
+ class << self
15
+ #
16
+ # @!attribute [r] rule_manager
17
+ # @return [org.openhab.core.automation.RuleManager] The OpenHAB rule manager/engine
18
+ #
19
+ def manager
20
+ @manager ||= OSGi.service("org.openhab.core.automation.RuleManager")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -29,9 +29,11 @@ module OpenHAB
29
29
  # end
30
30
  #
31
31
  def script_loaded(&block)
32
- Core::ScriptHandlingCallbacks.script_loaded_hooks << block
32
+ ScriptHandlingCallbacks.script_loaded_hooks << block
33
33
  end
34
34
 
35
+ #
36
+ # @!method script_unloaded(&block)
35
37
  #
36
38
  # Add a block of code to be executed when the script is unloaded.
37
39
  #
@@ -47,8 +49,10 @@ module OpenHAB
47
49
  # logger.info 'Hi, this script has been unloaded'
48
50
  # end
49
51
  #
50
- def script_unloaded(&block)
51
- Core::ScriptHandlingCallbacks.script_unloaded_hooks << block
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)
52
56
  end
53
57
  end
54
58
 
@@ -58,6 +62,13 @@ module OpenHAB
58
62
  # @!visibility private
59
63
  module ScriptHandlingCallbacks
60
64
  class << self
65
+ #
66
+ # Has the script completed loading?
67
+ #
68
+ # @!visibility private
69
+ # @return [true, false]
70
+ attr_accessor :script_loaded
71
+
61
72
  #
62
73
  # Return script_loaded_hooks
63
74
  #
@@ -74,6 +85,7 @@ module OpenHAB
74
85
  @script_unloaded_hooks ||= []
75
86
  end
76
87
  end
88
+ self.script_loaded = false
77
89
 
78
90
  #
79
91
  # Executed when OpenHAB unloads a script file
@@ -85,6 +97,22 @@ module OpenHAB
85
97
  rescue => e
86
98
  logger.error("Failed to call script_unloaded hook #{hook}: #{e}")
87
99
  end
100
+
101
+ return if ScriptHandlingCallbacks.script_loaded
102
+
103
+ # Make sure we terminate the main thread if it's still set up, in case
104
+ # it's timing out and that's why we're unloading.
105
+ #
106
+ # It would seem simpler to just record Thread.current when this file
107
+ # loads, but if the user is using the autorequire feature of the
108
+ # jrubyscripting addon, this file will load before the main script.
109
+ #
110
+ # Note that Thread.list only includes threads that have had Ruby
111
+ # execute in them, so we don't need to worry about accidentally killing
112
+ # a random Java thread.
113
+ #
114
+ main_thread = Thread.list.find { |t| t != Thread.current && t.name.include?("-safeCall-") }
115
+ main_thread&.raise(Interrupt.new)
88
116
  end
89
117
 
90
118
  #
@@ -97,6 +125,7 @@ module OpenHAB
97
125
  rescue => e
98
126
  logger.error("Failed to call script_loaded hook #{hook}: #{e}")
99
127
  end
128
+ ScriptHandlingCallbacks.script_loaded = true
100
129
  end
101
130
  end
102
131
  end
@@ -35,7 +35,6 @@ module OpenHAB
35
35
  # @return [Object, nil]
36
36
  attr_accessor :id
37
37
 
38
- # @!visibility private
39
38
  # @!visibility private
40
39
  attr_reader :block
41
40
 
@@ -84,6 +83,7 @@ module OpenHAB
84
83
  # @return [self]
85
84
  #
86
85
  def reschedule(time = nil)
86
+ Thread.current[:openhab_rescheduled_timer] = true if Thread.current[:openhab_rescheduled_timer] == self
87
87
  DSL.timers.add(self)
88
88
  @timer.reschedule(new_execution_time(time || @time))
89
89
  self
@@ -119,12 +119,10 @@ module OpenHAB
119
119
  # @return [void]
120
120
  #
121
121
  def execute
122
- last_execution_time = execution_time
123
- DSL::ThreadLocal.thread_local(**@thread_locals) do
124
- @block.call(self)
125
- end
126
- # don't remove ourselves if we were rescheduled in the block
127
- DSL.timers.delete(self) if execution_time == last_execution_time
122
+ Thread.current[:openhab_rescheduled_timer] = self
123
+ DSL::ThreadLocal.thread_local(**@thread_locals) { @block.call(self) }
124
+ DSL.timers.delete(self) unless Thread.current[:openhab_rescheduled_timer] == true
125
+ Thread.current[:openhab_rescheduled_timer] = nil
128
126
  end
129
127
 
130
128
  #
@@ -13,7 +13,7 @@ module OpenHAB
13
13
  # Types are the specific data types that commands and states are. They can be
14
14
  # sent to items, be the current state of an item, or be the `command`, `state`,
15
15
  # and `was` field of various
16
- # {group::OpenHAB::DSL::Rules::Builder::Triggers triggers}.
16
+ # {group::OpenHAB::DSL::Rules::BuilderDSL::Triggers triggers}.
17
17
  # Some types have additional useful methods.
18
18
  #
19
19
  module Types
data/lib/openhab/core.rb CHANGED
@@ -53,22 +53,6 @@ module OpenHAB
53
53
  def automation_manager
54
54
  $scriptExtension.get("automationManager")
55
55
  end
56
-
57
- #
58
- # @!attribute [r] rule_registry
59
- # @return [org.openhab.core.automation.RuleRegistry] The OpenHAB rule registry
60
- #
61
- def rule_registry
62
- $scriptExtension.get("ruleRegistry")
63
- end
64
-
65
- #
66
- # @!attribute [r] rule_manager
67
- # @return [org.openhab.core.automation.RuleManager] The OpenHAB rule manager/engine
68
- #
69
- def rule_manager
70
- @rule_manager ||= OSGi.service("org.openhab.core.automation.RuleManager")
71
- end
72
56
  end
73
57
  end
74
58
  end