openhab-jrubyscripting 5.0.0.rc2 → 5.0.0.rc4

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