openhab-jrubyscripting 5.0.0.rc1

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 (164) hide show
  1. checksums.yaml +7 -0
  2. data/lib/openhab/core/actions.rb +163 -0
  3. data/lib/openhab/core/entity_lookup.rb +144 -0
  4. data/lib/openhab/core/events/abstract_event.rb +17 -0
  5. data/lib/openhab/core/events/item_channel_link.rb +36 -0
  6. data/lib/openhab/core/events/item_command_event.rb +78 -0
  7. data/lib/openhab/core/events/item_event.rb +22 -0
  8. data/lib/openhab/core/events/item_state_changed_event.rb +52 -0
  9. data/lib/openhab/core/events/item_state_event.rb +51 -0
  10. data/lib/openhab/core/events/thing.rb +29 -0
  11. data/lib/openhab/core/events/thing_status_info_event.rb +53 -0
  12. data/lib/openhab/core/events.rb +10 -0
  13. data/lib/openhab/core/items/accepted_data_types.rb +29 -0
  14. data/lib/openhab/core/items/color_item.rb +52 -0
  15. data/lib/openhab/core/items/contact_item.rb +52 -0
  16. data/lib/openhab/core/items/date_time_item.rb +58 -0
  17. data/lib/openhab/core/items/dimmer_item.rb +148 -0
  18. data/lib/openhab/core/items/generic_item.rb +344 -0
  19. data/lib/openhab/core/items/group_item.rb +174 -0
  20. data/lib/openhab/core/items/image_item.rb +109 -0
  21. data/lib/openhab/core/items/location_item.rb +34 -0
  22. data/lib/openhab/core/items/metadata/hash.rb +390 -0
  23. data/lib/openhab/core/items/metadata/namespace_hash.rb +469 -0
  24. data/lib/openhab/core/items/metadata.rb +11 -0
  25. data/lib/openhab/core/items/number_item.rb +62 -0
  26. data/lib/openhab/core/items/numeric_item.rb +22 -0
  27. data/lib/openhab/core/items/persistence.rb +327 -0
  28. data/lib/openhab/core/items/player_item.rb +66 -0
  29. data/lib/openhab/core/items/proxy.rb +59 -0
  30. data/lib/openhab/core/items/registry.rb +66 -0
  31. data/lib/openhab/core/items/rollershutter_item.rb +68 -0
  32. data/lib/openhab/core/items/semantics/enumerable.rb +152 -0
  33. data/lib/openhab/core/items/semantics.rb +476 -0
  34. data/lib/openhab/core/items/state_storage.rb +53 -0
  35. data/lib/openhab/core/items/string_item.rb +28 -0
  36. data/lib/openhab/core/items/switch_item.rb +78 -0
  37. data/lib/openhab/core/items.rb +114 -0
  38. data/lib/openhab/core/lazy_array.rb +52 -0
  39. data/lib/openhab/core/profile_factory.rb +118 -0
  40. data/lib/openhab/core/script_handling.rb +55 -0
  41. data/lib/openhab/core/things/channel.rb +48 -0
  42. data/lib/openhab/core/things/channel_uid.rb +51 -0
  43. data/lib/openhab/core/things/item_channel_link.rb +33 -0
  44. data/lib/openhab/core/things/profile_callback.rb +52 -0
  45. data/lib/openhab/core/things/proxy.rb +69 -0
  46. data/lib/openhab/core/things/registry.rb +46 -0
  47. data/lib/openhab/core/things/thing.rb +194 -0
  48. data/lib/openhab/core/things.rb +22 -0
  49. data/lib/openhab/core/timer.rb +128 -0
  50. data/lib/openhab/core/types/comparable_type.rb +23 -0
  51. data/lib/openhab/core/types/date_time_type.rb +259 -0
  52. data/lib/openhab/core/types/decimal_type.rb +192 -0
  53. data/lib/openhab/core/types/hsb_type.rb +183 -0
  54. data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
  55. data/lib/openhab/core/types/next_previous_type.rb +34 -0
  56. data/lib/openhab/core/types/numeric_type.rb +52 -0
  57. data/lib/openhab/core/types/on_off_type.rb +46 -0
  58. data/lib/openhab/core/types/open_closed_type.rb +41 -0
  59. data/lib/openhab/core/types/percent_type.rb +95 -0
  60. data/lib/openhab/core/types/play_pause_type.rb +38 -0
  61. data/lib/openhab/core/types/point_type.rb +117 -0
  62. data/lib/openhab/core/types/quantity_type.rb +327 -0
  63. data/lib/openhab/core/types/raw_type.rb +26 -0
  64. data/lib/openhab/core/types/refresh_type.rb +27 -0
  65. data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
  66. data/lib/openhab/core/types/stop_move_type.rb +34 -0
  67. data/lib/openhab/core/types/string_type.rb +76 -0
  68. data/lib/openhab/core/types/type.rb +117 -0
  69. data/lib/openhab/core/types/un_def_type.rb +38 -0
  70. data/lib/openhab/core/types/up_down_type.rb +50 -0
  71. data/lib/openhab/core/types.rb +69 -0
  72. data/lib/openhab/core/uid.rb +36 -0
  73. data/lib/openhab/core.rb +85 -0
  74. data/lib/openhab/core_ext/java/duration.rb +115 -0
  75. data/lib/openhab/core_ext/java/local_date.rb +93 -0
  76. data/lib/openhab/core_ext/java/local_time.rb +106 -0
  77. data/lib/openhab/core_ext/java/month.rb +59 -0
  78. data/lib/openhab/core_ext/java/month_day.rb +105 -0
  79. data/lib/openhab/core_ext/java/period.rb +103 -0
  80. data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
  81. data/lib/openhab/core_ext/java/time.rb +58 -0
  82. data/lib/openhab/core_ext/java/unit.rb +15 -0
  83. data/lib/openhab/core_ext/java/zoned_date_time.rb +116 -0
  84. data/lib/openhab/core_ext/ruby/array.rb +21 -0
  85. data/lib/openhab/core_ext/ruby/class.rb +15 -0
  86. data/lib/openhab/core_ext/ruby/date.rb +89 -0
  87. data/lib/openhab/core_ext/ruby/numeric.rb +190 -0
  88. data/lib/openhab/core_ext/ruby/range.rb +70 -0
  89. data/lib/openhab/core_ext/ruby/time.rb +104 -0
  90. data/lib/openhab/core_ext.rb +18 -0
  91. data/lib/openhab/dsl/events/watch_event.rb +18 -0
  92. data/lib/openhab/dsl/events.rb +9 -0
  93. data/lib/openhab/dsl/gems.rb +3 -0
  94. data/lib/openhab/dsl/items/builder.rb +618 -0
  95. data/lib/openhab/dsl/items/ensure.rb +93 -0
  96. data/lib/openhab/dsl/items/timed_command.rb +236 -0
  97. data/lib/openhab/dsl/rules/automation_rule.rb +308 -0
  98. data/lib/openhab/dsl/rules/builder.rb +1373 -0
  99. data/lib/openhab/dsl/rules/guard.rb +115 -0
  100. data/lib/openhab/dsl/rules/name_inference.rb +160 -0
  101. data/lib/openhab/dsl/rules/property.rb +76 -0
  102. data/lib/openhab/dsl/rules/rule_triggers.rb +96 -0
  103. data/lib/openhab/dsl/rules/terse.rb +63 -0
  104. data/lib/openhab/dsl/rules/triggers/changed.rb +169 -0
  105. data/lib/openhab/dsl/rules/triggers/channel.rb +57 -0
  106. data/lib/openhab/dsl/rules/triggers/command.rb +107 -0
  107. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +161 -0
  108. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +164 -0
  109. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +195 -0
  110. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +127 -0
  111. data/lib/openhab/dsl/rules/triggers/trigger.rb +56 -0
  112. data/lib/openhab/dsl/rules/triggers/updated.rb +130 -0
  113. data/lib/openhab/dsl/rules/triggers/watch/watch.rb +55 -0
  114. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +155 -0
  115. data/lib/openhab/dsl/rules/triggers.rb +12 -0
  116. data/lib/openhab/dsl/rules.rb +29 -0
  117. data/lib/openhab/dsl/script_handling.rb +55 -0
  118. data/lib/openhab/dsl/things/builder.rb +263 -0
  119. data/lib/openhab/dsl/thread_local.rb +48 -0
  120. data/lib/openhab/dsl/timer_manager.rb +191 -0
  121. data/lib/openhab/dsl/version.rb +9 -0
  122. data/lib/openhab/dsl.rb +686 -0
  123. data/lib/openhab/log.rb +348 -0
  124. data/lib/openhab/osgi.rb +70 -0
  125. data/lib/openhab/rspec/configuration.rb +56 -0
  126. data/lib/openhab/rspec/example_group.rb +90 -0
  127. data/lib/openhab/rspec/helpers.rb +439 -0
  128. data/lib/openhab/rspec/hooks.rb +93 -0
  129. data/lib/openhab/rspec/jruby.rb +46 -0
  130. data/lib/openhab/rspec/karaf.rb +811 -0
  131. data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
  132. data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
  133. data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
  134. data/lib/openhab/rspec/mocks/metadata_provider.rb +75 -0
  135. data/lib/openhab/rspec/mocks/persistence_service.rb +140 -0
  136. data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
  137. data/lib/openhab/rspec/mocks/synchronous_executor.rb +56 -0
  138. data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
  139. data/lib/openhab/rspec/mocks/timer.rb +95 -0
  140. data/lib/openhab/rspec/openhab/core/actions.rb +26 -0
  141. data/lib/openhab/rspec/openhab/core/items/proxy.rb +27 -0
  142. data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
  143. data/lib/openhab/rspec/shell.rb +31 -0
  144. data/lib/openhab/rspec/suspend_rules.rb +60 -0
  145. data/lib/openhab/rspec.rb +17 -0
  146. data/lib/openhab/yard/cli/stats.rb +23 -0
  147. data/lib/openhab/yard/code_objects/group_object.rb +17 -0
  148. data/lib/openhab/yard/code_objects/java/base.rb +31 -0
  149. data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
  150. data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
  151. data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
  152. data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
  153. data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
  154. data/lib/openhab/yard/handlers/jruby/base.rb +49 -0
  155. data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
  156. data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
  157. data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +27 -0
  158. data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
  159. data/lib/openhab/yard/html_helper.rb +44 -0
  160. data/lib/openhab/yard/tags/constant_directive.rb +20 -0
  161. data/lib/openhab/yard/tags/group_directive.rb +24 -0
  162. data/lib/openhab/yard/tags/library.rb +3 -0
  163. data/lib/openhab/yard.rb +32 -0
  164. metadata +504 -0
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cron"
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ module Triggers
9
+ # @!visibility private
10
+ #
11
+ # Cron trigger handler that provides trigger ID
12
+ #
13
+ module CronHandler
14
+ # Cron Trigger Handler that provides trigger IDs
15
+ # Unfortunatly because the CronTriggerHandler in OpenHAB core is marked internal
16
+ # the entire thing must be recreated here
17
+ class CronTriggerHandler < org.openhab.core.automation.handler.BaseTriggerModuleHandler
18
+ include org.openhab.core.scheduler.SchedulerRunnable
19
+ include org.openhab.core.automation.handler.TimeBasedTriggerHandler
20
+
21
+ # Provides access to protected fields
22
+ field_accessor :callback
23
+
24
+ # Creates a new CronTriggerHandler
25
+ # @param [Trigger] trigger OpenHAB trigger associated with handler
26
+ #
27
+ def initialize(trigger)
28
+ @trigger = trigger
29
+ @scheduler = OSGi.service("org.openhab.core.scheduler.CronScheduler")
30
+ @schedule = nil
31
+ @expression = trigger.configuration.get("cronExpression")
32
+ super(trigger)
33
+ end
34
+
35
+ #
36
+ # Set the callback to execute when cron trigger fires
37
+ # @param [Object] callback to run
38
+ #
39
+ def setCallback(callback) # rubocop:disable Naming/MethodName
40
+ synchronized do
41
+ super(callback)
42
+ @schedule = @scheduler.schedule(self, @expression)
43
+ logger.trace("Scheduled cron job '#{@expression}' for trigger '#{@trigger.id}'.")
44
+ end
45
+ end
46
+
47
+ #
48
+ # Get the temporal adjuster
49
+ # @return [CronAdjuster]
50
+ #
51
+ def getTemporalAdjuster # rubocop:disable Naming/MethodName
52
+ org.openhab.core.scheduler.CronAdjuster.new(expression)
53
+ end
54
+
55
+ #
56
+ # Execute the callback
57
+ #
58
+ def run
59
+ callback&.triggered(@trigger, { "module" => @trigger.id })
60
+ end
61
+
62
+ #
63
+ # Displose of the handler
64
+ # cancel the cron scheduled task
65
+ #
66
+ def dispose
67
+ synchronized do
68
+ super
69
+ return unless @schedule
70
+
71
+ @schedule.cancel(true)
72
+ @schedule = nil
73
+ end
74
+ logger.trace("cancelled job for trigger '#{@trigger.id}'.")
75
+ end
76
+ end
77
+
78
+ # Implements the ScriptedTriggerHandlerFactory interface to create a new Cron Trigger Handler
79
+ class CronTriggerHandlerFactory
80
+ include org.openhab.core.automation.module.script.rulesupport.shared.factories.ScriptedTriggerHandlerFactory
81
+
82
+ # Invoked by the OpenHAB core to get a trigger handler for the supllied trigger
83
+ # @param [Trigger] trigger OpenHAB trigger
84
+ #
85
+ # @return [WatchTriggerHandler] trigger handler for supplied trigger
86
+ def get(trigger)
87
+ CronTriggerHandler.new(trigger)
88
+ end
89
+ end
90
+
91
+ class << self
92
+ private
93
+
94
+ #
95
+ # Creates trigger types and trigger type factories for OpenHAB
96
+ #
97
+ def add_script_cron_handler
98
+ Core.automation_manager.add_trigger_handler(
99
+ Cron::CRON_TRIGGER_MODULE_ID,
100
+ CronTriggerHandlerFactory.new
101
+ )
102
+
103
+ Core.automation_manager.add_trigger_type(cron_trigger_type)
104
+ logger.trace("Added script cron trigger handler")
105
+ end
106
+
107
+ #
108
+ # Creates trigger types and trigger type factories for OpenHAB
109
+ #
110
+ def cron_trigger_type
111
+ org.openhab.core.automation.type.TriggerType.new(
112
+ Cron::CRON_TRIGGER_MODULE_ID,
113
+ nil,
114
+ "A specific instant occurs",
115
+ "Triggers when the specified instant occurs",
116
+ nil,
117
+ org.openhab.core.automation.Visibility::VISIBLE,
118
+ nil
119
+ )
120
+ end
121
+ end
122
+ add_script_cron_handler
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ module Triggers
9
+ # @!visibility private
10
+ #
11
+ # Class for creating and managing triggers
12
+ #
13
+ class Trigger
14
+ extend Forwardable
15
+
16
+ delegate append_trigger: :@rule_triggers
17
+
18
+ #
19
+ # Creates a new Trigger
20
+ # @param [RuleTrigger] rule_triggers rule trigger information
21
+ def initialize(rule_triggers:)
22
+ @rule_triggers = rule_triggers
23
+ end
24
+
25
+ #
26
+ # Create a trigger for a thing
27
+ #
28
+ # @param [Thing] thing to create trigger for
29
+ # @param [Trigger] type trigger to map with thing
30
+ # @param [State] to for thing
31
+ # @param [State] from state of thing
32
+ #
33
+ # @return [Array] Trigger and config for thing
34
+ #
35
+ def trigger_for_thing(thing:, type:, to: nil, from: nil)
36
+ config = { "thingUID" => thing.uid.to_s }
37
+ config["status"] = trigger_state_from_symbol(to).to_s if to
38
+ config["previousStatus"] = trigger_state_from_symbol(from).to_s if from
39
+ [type, config]
40
+ end
41
+
42
+ #
43
+ # converts object to upcase string if its a symbol
44
+ #
45
+ # @param [sym] sym potential symbol to convert
46
+ #
47
+ # @return [String] Upcased symbol as string
48
+ #
49
+ def trigger_state_from_symbol(sym)
50
+ sym.to_s.upcase if sym.is_a?(Symbol) || sym
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "trigger"
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ module Triggers
9
+ # @!visibility private
10
+ #
11
+ # Creates updated triggers
12
+ #
13
+ class Updated < Trigger
14
+ #
15
+ # Create the trigger
16
+ #
17
+ # @param [Object] item item to create trigger for
18
+ # @param [Item State] to state to restrict trigger to
19
+ # @param [Object] attach object to be attached to the trigger
20
+ #
21
+ # @return [Trigger] OpenHAB triggers
22
+ #
23
+ def trigger(item:, to:, attach:)
24
+ case to
25
+ when Range then range_trigger(item: item, to: to, attach: attach)
26
+ when Proc then proc_trigger(item: item, to: to, attach: attach)
27
+ else update_trigger(item: item, to: to, attach: attach)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # @return [String] A thing status update trigger
34
+ THING_UPDATE = "core.ThingStatusUpdateTrigger"
35
+
36
+ # @return [String] An item state update trigger
37
+ ITEM_STATE_UPDATE = "core.ItemStateUpdateTrigger"
38
+
39
+ # @return [String] A group state update trigger for items in the group
40
+ GROUP_STATE_UPDATE = "core.GroupStateUpdateTrigger"
41
+
42
+ #
43
+ # Creates a trigger with a range condition on the 'to' field
44
+ # @param [Object] item to create changed trigger on
45
+ # @param [Object] to state restrict trigger to
46
+ # @param [Object] attach object to be attached to the trigger
47
+ # @return [Trigger] OpenHAB trigger
48
+ #
49
+ def range_trigger(item:, to:, attach:)
50
+ to, * = Conditions::Proc.range_procs(to)
51
+ proc_trigger(item: item, to: to, attach: attach)
52
+ end
53
+
54
+ #
55
+ # Creates a trigger with a proc condition on the 'to' field
56
+ # @param [Object] item to create changed trigger on
57
+ # @param [Object] to state restrict trigger to
58
+ # @param [Object] attach object to be attached to the trigger
59
+ # @return [Trigger] OpenHAB trigger
60
+ #
61
+ def proc_trigger(item:, to:, attach:)
62
+ conditions = Conditions::Proc.new(to: to)
63
+ update_trigger(item: item, to: nil, attach: attach, conditions: conditions)
64
+ end
65
+
66
+ #
67
+ # Create a trigger for updates
68
+ #
69
+ # @param [Object] item Type of item [Group,Thing,Item] to create update trigger for
70
+ # @param [State] to state restriction on trigger
71
+ # @param [Object] attach object to be attached to the trigger
72
+ #
73
+ # @return [Trigger] OpenHAB triggers
74
+ #
75
+ def update_trigger(item:, to:, attach: nil, conditions: nil)
76
+ type, config = case item
77
+ when GroupItem::Members then group_update(item: item, to: to)
78
+ when Core::Things::Thing then thing_update(thing: item, to: to)
79
+ else item_update(item: item, to: to)
80
+ end
81
+ append_trigger(type: type, config: config, attach: attach, conditions: conditions)
82
+ end
83
+
84
+ #
85
+ # Create an update trigger for an item
86
+ #
87
+ # @param [Item] item to create trigger for
88
+ # @param [State] to optional state restriction for target
89
+ #
90
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
91
+ # second element is a Hash configuring trigger
92
+ #
93
+ def item_update(item:, to:)
94
+ config = { "itemName" => item.name }
95
+ config["state"] = to.to_s unless to.nil?
96
+ [ITEM_STATE_UPDATE, config]
97
+ end
98
+
99
+ #
100
+ # Create an update trigger for a group
101
+ #
102
+ # @param [Item] item to create trigger for
103
+ # @param [State] to optional state restriction for target
104
+ #
105
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
106
+ # second element is a Hash configuring trigger
107
+ #
108
+ def group_update(item:, to:)
109
+ config = { "groupName" => item.group.name }
110
+ config["state"] = to.to_s unless to.nil?
111
+ [GROUP_STATE_UPDATE, config]
112
+ end
113
+
114
+ #
115
+ # Create an update trigger for a thing
116
+ #
117
+ # @param [Thing] thing to create trigger for
118
+ # @param [State] to optional state restriction for target
119
+ #
120
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
121
+ # second element is a Hash configuring trigger
122
+ #
123
+ def thing_update(thing:, to:)
124
+ trigger_for_thing(thing: thing, type: THING_UPDATE, to: to)
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openhab/dsl/rules/triggers/trigger"
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ module Triggers
9
+ # @!visibility private
10
+ #
11
+ # Creates watch triggers
12
+ #
13
+ class Watch < Trigger
14
+ # Characters in an fnmatch compatible glob
15
+ GLOB_CHARS = ["**", "*", "?", "[", "]", "{", "}"].freeze
16
+ private_constant :GLOB_CHARS
17
+
18
+ #
19
+ # Automatically creates globs for supplied paths if necessary
20
+ #
21
+ # @param [Pathname] path to check
22
+ # @param [String] glob
23
+ #
24
+ # @return [Pathname,String] Pathname to watch and glob to match
25
+ #
26
+ def self.glob_for_path(path, glob)
27
+ # Checks if the supplied pathname last element contains a glob char
28
+ if GLOB_CHARS.any? { |char| path.basename.to_s.include? char }
29
+ # Splits the supplied pathname into a glob string and parent path
30
+ [path.basename.to_s, path.parent]
31
+ elsif path.file? || !path.exist?
32
+ # glob string matching end of Pathname and parent path
33
+ ["*/#{path.basename}", path.parent]
34
+ else
35
+ [glob, path]
36
+ end
37
+ end
38
+
39
+ #
40
+ # Create a watch trigger based on item type
41
+ #
42
+ # @param [Config] config Rule configuration
43
+ # @param [Object] attach object to be attached to the trigger
44
+ #
45
+ #
46
+ def trigger(config:, attach:)
47
+ append_trigger(type: WatchHandler::WATCH_TRIGGER_MODULE_ID,
48
+ config: config,
49
+ attach: attach)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Rules
6
+ module Triggers
7
+ # @!visibility private
8
+ #
9
+ # Module for watching directories/files
10
+ #
11
+ module WatchHandler
12
+ #
13
+ # Creates trigger types and trigger type factories for OpenHAB
14
+ #
15
+ private_class_method def self.watch_trigger_type
16
+ org.openhab.core.automation.type.TriggerType.new(
17
+ WATCH_TRIGGER_MODULE_ID,
18
+ nil,
19
+ "A path change event is detected",
20
+ "Triggers when a path change event is detected",
21
+ nil,
22
+ org.openhab.core.automation.Visibility::VISIBLE,
23
+ nil
24
+ )
25
+ end
26
+
27
+ # Trigger ID for Watch Triggers
28
+ WATCH_TRIGGER_MODULE_ID = "jsr223.jruby.WatchTrigger"
29
+
30
+ # Extends the OpenHAB watch service to watch directories
31
+ #
32
+ # Must match java method name style
33
+ # rubocop:disable Naming/MethodName
34
+ class Watcher < org.openhab.core.service.AbstractWatchService
35
+ java_import java.nio.file.StandardWatchEventKinds
36
+
37
+ # Hash of event symbols as strings to map to NIO events
38
+ STRING_TO_EVENT = {
39
+ created: StandardWatchEventKinds::ENTRY_CREATE,
40
+ deleted: StandardWatchEventKinds::ENTRY_DELETE,
41
+ modified: StandardWatchEventKinds::ENTRY_MODIFY
42
+ }.transform_keys(&:to_s).freeze
43
+
44
+ # Hash of NIO event kinds to ruby symbols
45
+ EVENT_TO_SYMBOL = STRING_TO_EVENT.invert.transform_values(&:to_sym).freeze
46
+
47
+ # Creates a new Watch Service
48
+ def initialize(path, types, &block)
49
+ super(path)
50
+ @types = types.map { |type| STRING_TO_EVENT[type] }
51
+ @block = block
52
+ end
53
+
54
+ # Invoked by java super class to get type of events to watch for
55
+ # @param [String] _path ignored
56
+ #
57
+ # @return [Array] array of NIO event kinds
58
+ def getWatchEventKinds(_path)
59
+ @types
60
+ end
61
+
62
+ # Invoked by java super class to check if sub directories should be watched
63
+ # @return [false] false
64
+ def watchSubDirectories
65
+ false
66
+ end
67
+
68
+ # Invoked by java super class when an watch event occurs
69
+ # @param [String] _event ignored
70
+ # @param [StandardWatchEventKind] kind NIO watch event kind
71
+ # @param [java.nio.Path] path that had an event
72
+ def processWatchEvent(_event, kind, path)
73
+ @block.call(Events::WatchEvent.new(EVENT_TO_SYMBOL[kind], Pathname.new(path.to_s)))
74
+ end
75
+ end
76
+ # rubocop:enable Naming/MethodName
77
+
78
+ # Implements the OpenHAB TriggerHandler interface to process Watch Triggers
79
+ class WatchTriggerHandler
80
+ include org.openhab.core.automation.handler.TriggerHandler
81
+
82
+ # Creates a new WatchTriggerHandler
83
+ # @param [Trigger] trigger OpenHAB trigger associated with handler
84
+ #
85
+ def initialize(trigger)
86
+ @trigger = trigger
87
+ config = trigger.configuration.properties.to_hash.transform_keys(&:to_sym)
88
+ @path = config[:path]
89
+ @watcher = Watcher.new(@path, config[:types], &watch_event_handler(config[:glob]))
90
+ @watcher.activate
91
+ logger.trace("Created watcher for #{@path}")
92
+ end
93
+
94
+ # Create a lambda to use to invoke rule engine when file watch notification happens
95
+ # @param [String] glob to match for notification events
96
+ #
97
+ # @return [Lambda] lambda to execute on notification events
98
+ #
99
+ def watch_event_handler(glob)
100
+ lambda { |watch_event|
101
+ logger.trace("Received event(#{watch_event})")
102
+ if watch_event.path.fnmatch?(glob)
103
+ @rule_engine_callback&.triggered(@trigger, { "event" => watch_event })
104
+ else
105
+ logger.trace("Event #{watch_event} did not match glob(#{glob})")
106
+ end
107
+ }
108
+ end
109
+
110
+ # Called by OpenHAB to set the rule engine to invoke when triggered
111
+ # Must match java method name style
112
+ def setCallback(callback) # rubocop:disable Naming/MethodName
113
+ @rule_engine_callback = callback
114
+ end
115
+
116
+ #
117
+ # Dispose of handler which deactivates watcher
118
+ #
119
+ def dispose
120
+ logger.trace("Deactivating watcher for #{@path}")
121
+ @watcher&.deactivate
122
+ end
123
+ end
124
+
125
+ # Implements the ScriptedTriggerHandlerFactory interface to create a new Trigger Handler
126
+ class WatchTriggerHandlerFactory
127
+ include org.openhab.core.automation.module.script.rulesupport.shared.factories.ScriptedTriggerHandlerFactory
128
+
129
+ # Invoked by the OpenHAB core to get a trigger handler for the supllied trigger
130
+ # @param [Trigger] trigger OpenHAB trigger
131
+ #
132
+ # @return [WatchTriggerHandler] trigger handler for supplied trigger
133
+ def get(trigger)
134
+ WatchTriggerHandler.new(trigger)
135
+ end
136
+ end
137
+
138
+ #
139
+ # Creates trigger types and trigger type factories for OpenHAB
140
+ #
141
+ def self.add_watch_handler
142
+ Core.automation_manager.add_trigger_handler(
143
+ WATCH_TRIGGER_MODULE_ID,
144
+ WatchTriggerHandlerFactory.new
145
+ )
146
+
147
+ Core.automation_manager.add_trigger_type(watch_trigger_type)
148
+ logger.trace("Added watch trigger handler")
149
+ end
150
+ add_watch_handler
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Rules
6
+ # Contains helper classes for implementing triggers.
7
+ # @!visibility private
8
+ module Triggers
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "script_handling"
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ @script_rules = {}
9
+
10
+ @scripted_rule_provider = OSGi.service(
11
+ "org.openhab.core.automation.module.script.rulesupport.shared.ScriptedRuleProvider"
12
+ )
13
+ class << self
14
+ # @!visibility private
15
+ attr_reader :script_rules, :scripted_rule_provider
16
+
17
+ #
18
+ # Cleanup rules in this script file
19
+ #
20
+ # @return [void]
21
+ #
22
+ def cleanup_rules
23
+ script_rules.each_value(&:cleanup)
24
+ end
25
+ end
26
+ ScriptHandling.script_unloaded { cleanup_rules }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ #
6
+ # Provide callback mechanisms for script handling
7
+ #
8
+ module ScriptHandling
9
+ module_function
10
+
11
+ #
12
+ # Add a block of code to be executed once the rule script has finished loading.
13
+ #
14
+ # This can occur on OpenHAB start up, when the script is first created, or updated.
15
+ #
16
+ # Multiple hooks can be added by calling {#script_loaded} multiple times.
17
+ # They can be used to perform final initializations.
18
+ #
19
+ # @return [void]
20
+ #
21
+ # @example
22
+ # script_loaded do
23
+ # logger.info 'Hi, this script has just finished loading'
24
+ # end
25
+ #
26
+ # @example
27
+ # script_loaded do
28
+ # logger.info 'I will be called after the script finished loading too'
29
+ # end
30
+ #
31
+ def script_loaded(&block)
32
+ Core::ScriptHandlingCallbacks.script_loaded_hooks << block
33
+ end
34
+
35
+ #
36
+ # Add a block of code to be executed when the script is unloaded.
37
+ #
38
+ # This can occur when OpenHAB shuts down, or when the script is being reloaded.
39
+ #
40
+ # Multiple hooks can be added by calling {#script_unloaded} multiple times.
41
+ # They can be used to perform final cleanup.
42
+ #
43
+ # @return [void]
44
+ #
45
+ # @example
46
+ # script_unloaded do
47
+ # logger.info 'Hi, this script has been unloaded'
48
+ # end
49
+ #
50
+ def script_unloaded(&block)
51
+ Core::ScriptHandlingCallbacks.script_unloaded_hooks << block
52
+ end
53
+ end
54
+ end
55
+ end