openhab-scripting 4.47.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (281) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/audio.rb +47 -0
  3. data/lib/openhab/core/actions/ephemeris.rb +39 -0
  4. data/lib/openhab/core/actions/exec.rb +51 -0
  5. data/lib/openhab/core/actions/http.rb +80 -0
  6. data/lib/openhab/core/actions/ping.rb +30 -0
  7. data/lib/openhab/core/actions/transformation.rb +32 -0
  8. data/lib/openhab/core/actions/voice.rb +36 -0
  9. data/lib/openhab/core/actions.rb +82 -0
  10. data/lib/openhab/core/dependency_tracking.rb +34 -0
  11. data/lib/openhab/core/dto/item_channel_link.rb +33 -0
  12. data/lib/openhab/core/dto/thing.rb +27 -0
  13. data/lib/openhab/core/dto.rb +11 -0
  14. data/lib/openhab/core/entity_lookup.rb +152 -70
  15. data/lib/openhab/core/events/abstract_event.rb +18 -0
  16. data/lib/openhab/core/events/abstract_item_registry_event.rb +36 -0
  17. data/lib/openhab/core/events/abstract_thing_registry_event.rb +40 -0
  18. data/lib/openhab/core/events/item_command_event.rb +78 -0
  19. data/lib/openhab/core/events/item_event.rb +22 -0
  20. data/lib/openhab/core/events/item_state_changed_event.rb +75 -0
  21. data/lib/openhab/core/events/item_state_event.rb +79 -0
  22. data/lib/openhab/core/events/thing_status_info_event.rb +55 -0
  23. data/lib/openhab/core/events.rb +10 -0
  24. data/lib/openhab/core/items/accepted_data_types.rb +29 -0
  25. data/lib/openhab/core/items/color_item.rb +52 -0
  26. data/lib/openhab/core/items/contact_item.rb +52 -0
  27. data/lib/openhab/core/items/date_time_item.rb +59 -0
  28. data/lib/openhab/core/items/dimmer_item.rb +148 -0
  29. data/lib/openhab/core/items/generic_item.rb +292 -0
  30. data/lib/openhab/core/items/group_item.rb +176 -0
  31. data/lib/openhab/{dsl → core}/items/image_item.rb +35 -29
  32. data/lib/openhab/core/items/item.rb +273 -0
  33. data/lib/openhab/core/items/location_item.rb +34 -0
  34. data/lib/openhab/core/items/metadata/hash.rb +433 -0
  35. data/lib/openhab/core/items/metadata/namespace_hash.rb +475 -0
  36. data/lib/openhab/core/items/metadata/provider.rb +48 -0
  37. data/lib/openhab/core/items/metadata.rb +11 -0
  38. data/lib/openhab/core/items/number_item.rb +62 -0
  39. data/lib/openhab/core/items/numeric_item.rb +22 -0
  40. data/lib/openhab/core/items/persistence.rb +416 -0
  41. data/lib/openhab/core/items/player_item.rb +66 -0
  42. data/lib/openhab/core/items/provider.rb +44 -0
  43. data/lib/openhab/core/items/proxy.rb +136 -0
  44. data/lib/openhab/core/items/registry.rb +86 -0
  45. data/lib/openhab/core/items/rollershutter_item.rb +68 -0
  46. data/lib/openhab/core/items/semantics/enumerable.rb +177 -0
  47. data/lib/openhab/core/items/semantics.rb +473 -0
  48. data/lib/openhab/core/items/state_storage.rb +53 -0
  49. data/lib/openhab/core/items/string_item.rb +28 -0
  50. data/lib/openhab/core/items/switch_item.rb +78 -0
  51. data/lib/openhab/core/items.rb +108 -0
  52. data/lib/openhab/{dsl → core}/lazy_array.rb +9 -3
  53. data/lib/openhab/core/profile_factory.rb +132 -0
  54. data/lib/openhab/core/provider.rb +230 -0
  55. data/lib/openhab/core/proxy.rb +130 -0
  56. data/lib/openhab/core/registry.rb +40 -0
  57. data/lib/openhab/core/rules/module.rb +26 -0
  58. data/lib/openhab/core/rules/provider.rb +25 -0
  59. data/lib/openhab/core/rules/registry.rb +76 -0
  60. data/lib/openhab/core/rules/rule.rb +150 -0
  61. data/lib/openhab/core/rules.rb +25 -0
  62. data/lib/openhab/core/script_handling.rb +78 -20
  63. data/lib/openhab/core/things/channel.rb +48 -0
  64. data/lib/openhab/core/things/channel_uid.rb +51 -0
  65. data/lib/openhab/core/things/item_channel_link.rb +33 -0
  66. data/lib/openhab/core/things/links/provider.rb +78 -0
  67. data/lib/openhab/core/things/profile_callback.rb +52 -0
  68. data/lib/openhab/core/things/provider.rb +29 -0
  69. data/lib/openhab/core/things/proxy.rb +87 -0
  70. data/lib/openhab/core/things/registry.rb +73 -0
  71. data/lib/openhab/core/things/thing.rb +194 -0
  72. data/lib/openhab/core/things.rb +22 -0
  73. data/lib/openhab/core/timer.rb +148 -0
  74. data/lib/openhab/{dsl → core}/types/comparable_type.rb +5 -3
  75. data/lib/openhab/{dsl → core}/types/date_time_type.rb +55 -127
  76. data/lib/openhab/{dsl → core}/types/decimal_type.rb +50 -48
  77. data/lib/openhab/{dsl → core}/types/hsb_type.rb +35 -83
  78. data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
  79. data/lib/openhab/core/types/next_previous_type.rb +34 -0
  80. data/lib/openhab/{dsl → core}/types/numeric_type.rb +20 -7
  81. data/lib/openhab/core/types/on_off_type.rb +46 -0
  82. data/lib/openhab/core/types/open_closed_type.rb +41 -0
  83. data/lib/openhab/{dsl → core}/types/percent_type.rb +19 -20
  84. data/lib/openhab/core/types/play_pause_type.rb +38 -0
  85. data/lib/openhab/core/types/point_type.rb +117 -0
  86. data/lib/openhab/core/types/quantity_type.rb +325 -0
  87. data/lib/openhab/core/types/raw_type.rb +26 -0
  88. data/lib/openhab/core/types/refresh_type.rb +27 -0
  89. data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
  90. data/lib/openhab/core/types/stop_move_type.rb +34 -0
  91. data/lib/openhab/{dsl → core}/types/string_type.rb +17 -28
  92. data/lib/openhab/{dsl → core}/types/type.rb +42 -40
  93. data/lib/openhab/core/types/un_def_type.rb +38 -0
  94. data/lib/openhab/core/types/up_down_type.rb +50 -0
  95. data/lib/openhab/core/types.rb +82 -0
  96. data/lib/openhab/{dsl → core}/uid.rb +4 -23
  97. data/lib/openhab/core/value_cache.rb +188 -0
  98. data/lib/openhab/core.rb +98 -0
  99. data/lib/openhab/core_ext/between.rb +32 -0
  100. data/lib/openhab/core_ext/ephemeris.rb +53 -0
  101. data/lib/openhab/core_ext/java/class.rb +34 -0
  102. data/lib/openhab/core_ext/java/duration.rb +142 -0
  103. data/lib/openhab/core_ext/java/list.rb +436 -0
  104. data/lib/openhab/core_ext/java/local_date.rb +104 -0
  105. data/lib/openhab/core_ext/java/local_time.rb +118 -0
  106. data/lib/openhab/core_ext/java/map.rb +66 -0
  107. data/lib/openhab/core_ext/java/month.rb +71 -0
  108. data/lib/openhab/core_ext/java/month_day.rb +119 -0
  109. data/lib/openhab/core_ext/java/period.rb +103 -0
  110. data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
  111. data/lib/openhab/core_ext/java/time.rb +62 -0
  112. data/lib/openhab/core_ext/java/unit.rb +15 -0
  113. data/lib/openhab/core_ext/java/zoned_date_time.rb +213 -0
  114. data/lib/openhab/core_ext/ruby/array.rb +21 -0
  115. data/lib/openhab/core_ext/ruby/date.rb +96 -0
  116. data/lib/openhab/core_ext/ruby/date_time.rb +55 -0
  117. data/lib/openhab/core_ext/ruby/module.rb +15 -0
  118. data/lib/openhab/core_ext/ruby/numeric.rb +195 -0
  119. data/lib/openhab/core_ext/ruby/range.rb +70 -0
  120. data/lib/openhab/core_ext/ruby/symbol.rb +7 -0
  121. data/lib/openhab/core_ext/ruby/time.rb +108 -0
  122. data/lib/openhab/core_ext.rb +18 -0
  123. data/lib/openhab/dsl/debouncer.rb +259 -0
  124. data/lib/openhab/dsl/events/watch_event.rb +18 -0
  125. data/lib/openhab/dsl/events.rb +9 -0
  126. data/lib/openhab/dsl/gems.rb +1 -1
  127. data/lib/openhab/dsl/items/builder.rb +578 -0
  128. data/lib/openhab/dsl/items/ensure.rb +73 -82
  129. data/lib/openhab/dsl/items/timed_command.rb +214 -159
  130. data/lib/openhab/dsl/rules/automation_rule.rb +126 -115
  131. data/lib/openhab/dsl/rules/builder.rb +1935 -0
  132. data/lib/openhab/dsl/rules/guard.rb +51 -114
  133. data/lib/openhab/dsl/rules/name_inference.rb +66 -25
  134. data/lib/openhab/dsl/rules/property.rb +48 -75
  135. data/lib/openhab/dsl/rules/rule_triggers.rb +22 -27
  136. data/lib/openhab/dsl/rules/terse.rb +58 -14
  137. data/lib/openhab/dsl/rules/triggers/changed.rb +48 -94
  138. data/lib/openhab/dsl/rules/triggers/channel.rb +9 -40
  139. data/lib/openhab/dsl/rules/triggers/command.rb +14 -63
  140. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +34 -69
  141. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +6 -14
  142. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +48 -82
  143. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +30 -47
  144. data/lib/openhab/dsl/rules/triggers/trigger.rb +7 -28
  145. data/lib/openhab/dsl/rules/triggers/updated.rb +21 -45
  146. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +257 -102
  147. data/lib/openhab/dsl/rules/triggers.rb +12 -0
  148. data/lib/openhab/dsl/rules.rb +8 -0
  149. data/lib/openhab/dsl/things/builder.rb +299 -0
  150. data/lib/openhab/{core → dsl}/thread_local.rb +27 -17
  151. data/lib/openhab/dsl/timer_manager.rb +204 -0
  152. data/lib/openhab/dsl/version.rb +9 -0
  153. data/lib/openhab/dsl.rb +979 -0
  154. data/lib/openhab/log.rb +355 -0
  155. data/lib/openhab/osgi.rb +68 -0
  156. data/lib/openhab/rspec/configuration.rb +56 -0
  157. data/lib/openhab/rspec/example_group.rb +132 -0
  158. data/lib/openhab/rspec/helpers.rb +458 -0
  159. data/lib/openhab/rspec/hooks.rb +113 -0
  160. data/lib/openhab/rspec/jruby.rb +46 -0
  161. data/lib/openhab/rspec/karaf.rb +851 -0
  162. data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
  163. data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
  164. data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
  165. data/lib/openhab/rspec/mocks/instance_method_stasher.rb +22 -0
  166. data/lib/openhab/rspec/mocks/persistence_service.rb +155 -0
  167. data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
  168. data/lib/openhab/rspec/mocks/space.rb +23 -0
  169. data/lib/openhab/rspec/mocks/synchronous_executor.rb +63 -0
  170. data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
  171. data/lib/openhab/rspec/mocks/timer.rb +134 -0
  172. data/lib/openhab/rspec/openhab/core/actions.rb +38 -0
  173. data/lib/openhab/rspec/openhab/core/items/proxy.rb +15 -0
  174. data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
  175. data/lib/openhab/rspec/shell.rb +31 -0
  176. data/lib/openhab/rspec/suspend_rules.rb +50 -0
  177. data/lib/openhab/rspec.rb +26 -0
  178. data/lib/openhab/yard/base_helper.rb +19 -0
  179. data/lib/openhab/yard/cli/stats.rb +23 -0
  180. data/lib/openhab/yard/code_objects/group_object.rb +23 -0
  181. data/lib/openhab/yard/code_objects/java/base.rb +31 -0
  182. data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
  183. data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
  184. data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
  185. data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
  186. data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
  187. data/lib/openhab/yard/coderay.rb +17 -0
  188. data/lib/openhab/yard/handlers/jruby/base.rb +58 -0
  189. data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
  190. data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
  191. data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +30 -0
  192. data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
  193. data/lib/openhab/yard/html_helper.rb +78 -0
  194. data/lib/openhab/yard/markdown_helper.rb +148 -0
  195. data/lib/openhab/yard/tags/constant_directive.rb +20 -0
  196. data/lib/openhab/yard/tags/group_directive.rb +24 -0
  197. data/lib/openhab/yard/tags/library.rb +3 -0
  198. data/lib/openhab/yard.rb +38 -0
  199. metadata +475 -106
  200. data/lib/openhab/core/item_proxy.rb +0 -29
  201. data/lib/openhab/core/load_path.rb +0 -19
  202. data/lib/openhab/core/openhab_setup.rb +0 -29
  203. data/lib/openhab/core/osgi.rb +0 -58
  204. data/lib/openhab/core/services.rb +0 -24
  205. data/lib/openhab/dsl/actions.rb +0 -114
  206. data/lib/openhab/dsl/between.rb +0 -25
  207. data/lib/openhab/dsl/channel.rb +0 -43
  208. data/lib/openhab/dsl/dsl.rb +0 -59
  209. data/lib/openhab/dsl/group.rb +0 -54
  210. data/lib/openhab/dsl/imports.rb +0 -21
  211. data/lib/openhab/dsl/items/color_item.rb +0 -76
  212. data/lib/openhab/dsl/items/comparable_item.rb +0 -62
  213. data/lib/openhab/dsl/items/contact_item.rb +0 -41
  214. data/lib/openhab/dsl/items/date_time_item.rb +0 -65
  215. data/lib/openhab/dsl/items/dimmer_item.rb +0 -65
  216. data/lib/openhab/dsl/items/generic_item.rb +0 -229
  217. data/lib/openhab/dsl/items/group_item.rb +0 -127
  218. data/lib/openhab/dsl/items/item_equality.rb +0 -59
  219. data/lib/openhab/dsl/items/item_registry.rb +0 -54
  220. data/lib/openhab/dsl/items/items.rb +0 -109
  221. data/lib/openhab/dsl/items/location_item.rb +0 -59
  222. data/lib/openhab/dsl/items/metadata.rb +0 -326
  223. data/lib/openhab/dsl/items/number_item.rb +0 -17
  224. data/lib/openhab/dsl/items/numeric_item.rb +0 -87
  225. data/lib/openhab/dsl/items/persistence.rb +0 -307
  226. data/lib/openhab/dsl/items/player_item.rb +0 -58
  227. data/lib/openhab/dsl/items/rollershutter_item.rb +0 -51
  228. data/lib/openhab/dsl/items/semantics/enumerable.rb +0 -91
  229. data/lib/openhab/dsl/items/semantics.rb +0 -227
  230. data/lib/openhab/dsl/items/string_item.rb +0 -51
  231. data/lib/openhab/dsl/items/switch_item.rb +0 -70
  232. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +0 -4
  233. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +0 -39
  234. data/lib/openhab/dsl/monkey_patch/events/events.rb +0 -7
  235. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +0 -85
  236. data/lib/openhab/dsl/monkey_patch/events/item_event.rb +0 -28
  237. data/lib/openhab/dsl/monkey_patch/events/item_state.rb +0 -61
  238. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +0 -60
  239. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +0 -33
  240. data/lib/openhab/dsl/monkey_patch/java/java.rb +0 -4
  241. data/lib/openhab/dsl/monkey_patch/java/local_time.rb +0 -44
  242. data/lib/openhab/dsl/monkey_patch/java/time_extensions.rb +0 -50
  243. data/lib/openhab/dsl/monkey_patch/java/zoned_date_time.rb +0 -45
  244. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +0 -104
  245. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -6
  246. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +0 -47
  247. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -61
  248. data/lib/openhab/dsl/openhab.rb +0 -30
  249. data/lib/openhab/dsl/persistence.rb +0 -27
  250. data/lib/openhab/dsl/rules/item_event.rb +0 -19
  251. data/lib/openhab/dsl/rules/rule.rb +0 -160
  252. data/lib/openhab/dsl/rules/rule_config.rb +0 -147
  253. data/lib/openhab/dsl/rules/triggers/generic.rb +0 -31
  254. data/lib/openhab/dsl/rules/triggers/triggers.rb +0 -11
  255. data/lib/openhab/dsl/rules/triggers/watch/watch.rb +0 -81
  256. data/lib/openhab/dsl/states.rb +0 -89
  257. data/lib/openhab/dsl/things.rb +0 -147
  258. data/lib/openhab/dsl/time/month_day.rb +0 -180
  259. data/lib/openhab/dsl/time/time_of_day.rb +0 -235
  260. data/lib/openhab/dsl/timers/manager.rb +0 -119
  261. data/lib/openhab/dsl/timers/reentrant_timer.rb +0 -38
  262. data/lib/openhab/dsl/timers/timer.rb +0 -132
  263. data/lib/openhab/dsl/timers.rb +0 -77
  264. data/lib/openhab/dsl/types/increase_decrease_type.rb +0 -23
  265. data/lib/openhab/dsl/types/next_previous_type.rb +0 -23
  266. data/lib/openhab/dsl/types/on_off_type.rb +0 -28
  267. data/lib/openhab/dsl/types/open_closed_type.rb +0 -29
  268. data/lib/openhab/dsl/types/play_pause_type.rb +0 -27
  269. data/lib/openhab/dsl/types/point_type.rb +0 -180
  270. data/lib/openhab/dsl/types/quantity_type.rb +0 -265
  271. data/lib/openhab/dsl/types/refresh_type.rb +0 -18
  272. data/lib/openhab/dsl/types/rewind_fastforward_type.rb +0 -33
  273. data/lib/openhab/dsl/types/stop_move_type.rb +0 -23
  274. data/lib/openhab/dsl/types/types.rb +0 -83
  275. data/lib/openhab/dsl/types/un_def_type.rb +0 -22
  276. data/lib/openhab/dsl/types/up_down_type.rb +0 -32
  277. data/lib/openhab/dsl/units.rb +0 -45
  278. data/lib/openhab/log/configuration.rb +0 -21
  279. data/lib/openhab/log/logger.rb +0 -282
  280. data/lib/openhab/version.rb +0 -9
  281. data/lib/openhab.rb +0 -38
@@ -1,44 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'openhab/log/logger'
4
- require_relative 'trigger'
3
+ require_relative "trigger"
5
4
 
6
5
  module OpenHAB
7
6
  module DSL
8
7
  module Rules
9
- #
10
- # Module holds rule triggers
11
- #
12
8
  module Triggers
13
- include OpenHAB::Log
14
-
15
- #
16
- # Create a trigger when item, group or thing is updated
17
- #
18
- # @param [Array] items array to trigger on updated
19
- # @param [State] to to match for tigger
20
- # @param [Object] attach object to be attached to the trigger
21
- #
22
- # @return [Trigger] Trigger for updated entity
23
- #
24
- def updated(*items, to: nil, attach: nil)
25
- updated = Updated.new(rule_triggers: @rule_triggers)
26
- flattened_items = Updated.flatten_items(items)
27
- @ruby_triggers << [:updated, flattened_items, { to: to }]
28
- flattened_items.map do |item|
29
- logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
30
- [to].flatten.map do |to_state|
31
- updated.trigger(item: item, to: to_state, attach: attach)
32
- end
33
- end.flatten
34
- end
35
-
9
+ # @!visibility private
36
10
  #
37
11
  # Creates updated triggers
38
12
  #
39
13
  class Updated < Trigger
40
- include OpenHAB::Log
41
-
42
14
  #
43
15
  # Create the trigger
44
16
  #
@@ -46,7 +18,7 @@ module OpenHAB
46
18
  # @param [Item State] to state to restrict trigger to
47
19
  # @param [Object] attach object to be attached to the trigger
48
20
  #
49
- # @return [Trigger] OpenHAB triggers
21
+ # @return [org.openhab.core.automation.Trigger]
50
22
  #
51
23
  def trigger(item:, to:, attach:)
52
24
  case to
@@ -59,20 +31,20 @@ module OpenHAB
59
31
  private
60
32
 
61
33
  # @return [String] A thing status update trigger
62
- THING_UPDATE = 'core.ThingStatusUpdateTrigger'
34
+ THING_UPDATE = "core.ThingStatusUpdateTrigger"
63
35
 
64
36
  # @return [String] An item state update trigger
65
- ITEM_STATE_UPDATE = 'core.ItemStateUpdateTrigger'
37
+ ITEM_STATE_UPDATE = "core.ItemStateUpdateTrigger"
66
38
 
67
39
  # @return [String] A group state update trigger for items in the group
68
- GROUP_STATE_UPDATE = 'core.GroupStateUpdateTrigger'
40
+ GROUP_STATE_UPDATE = "core.GroupStateUpdateTrigger"
69
41
 
70
42
  #
71
43
  # Creates a trigger with a range condition on the 'to' field
72
44
  # @param [Object] item to create changed trigger on
73
45
  # @param [Object] to state restrict trigger to
74
46
  # @param [Object] attach object to be attached to the trigger
75
- # @return [Trigger] OpenHAB trigger
47
+ # @return [org.openhab.core.automation.Trigger]
76
48
  #
77
49
  def range_trigger(item:, to:, attach:)
78
50
  to, * = Conditions::Proc.range_procs(to)
@@ -84,7 +56,7 @@ module OpenHAB
84
56
  # @param [Object] item to create changed trigger on
85
57
  # @param [Object] to state restrict trigger to
86
58
  # @param [Object] attach object to be attached to the trigger
87
- # @return [Trigger] OpenHAB trigger
59
+ # @return [org.openhab.core.automation.Trigger]
88
60
  #
89
61
  def proc_trigger(item:, to:, attach:)
90
62
  conditions = Conditions::Proc.new(to: to)
@@ -98,13 +70,17 @@ module OpenHAB
98
70
  # @param [State] to state restriction on trigger
99
71
  # @param [Object] attach object to be attached to the trigger
100
72
  #
101
- # @return [Trigger] OpenHAB triggers
73
+ # @return [org.openhab.core.automation.Trigger]
102
74
  #
103
75
  def update_trigger(item:, to:, attach: nil, conditions: nil)
104
76
  type, config = case item
105
- when OpenHAB::DSL::Items::GroupItem::GroupMembers then group_update(item: item, to: to)
106
- when Thing then thing_update(thing: item, to: to)
107
- else item_update(item: item, to: to)
77
+ when GroupItem::Members
78
+ group_update(item: item, to: to)
79
+ when Core::Things::Thing,
80
+ Core::Things::ThingUID
81
+ thing_update(thing: item, to: to)
82
+ else
83
+ item_update(item: item, to: to)
108
84
  end
109
85
  append_trigger(type: type, config: config, attach: attach, conditions: conditions)
110
86
  end
@@ -119,23 +95,23 @@ module OpenHAB
119
95
  # second element is a Hash configuring trigger
120
96
  #
121
97
  def item_update(item:, to:)
122
- config = { 'itemName' => item.name }
123
- config['state'] = to.to_s unless to.nil?
98
+ config = { "itemName" => item.name }
99
+ config["state"] = to.to_s unless to.nil?
124
100
  [ITEM_STATE_UPDATE, config]
125
101
  end
126
102
 
127
103
  #
128
104
  # Create an update trigger for a group
129
105
  #
130
- # @param [Item] item to create trigger for
106
+ # @param [GroupItem::Members] item to create trigger for
131
107
  # @param [State] to optional state restriction for target
132
108
  #
133
109
  # @return [Array<Hash,String>] first element is a String specifying trigger type
134
110
  # second element is a Hash configuring trigger
135
111
  #
136
112
  def group_update(item:, to:)
137
- config = { 'groupName' => item.group.name }
138
- config['state'] = to.to_s unless to.nil?
113
+ config = { "groupName" => item.group.name }
114
+ config["state"] = to.to_s unless to.nil?
139
115
  [GROUP_STATE_UPDATE, config]
140
116
  end
141
117
 
@@ -1,126 +1,278 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'java'
4
- require 'openhab/log/logger'
5
- require 'openhab/core/services'
3
+ require "singleton"
4
+ require "pathname"
5
+ require "securerandom"
6
6
 
7
7
  module OpenHAB
8
8
  module DSL
9
9
  module Rules
10
- #
11
- # Module holds rule triggers
12
- #
13
10
  module Triggers
11
+ # @!visibility private
14
12
  #
15
13
  # Module for watching directories/files
16
14
  #
17
15
  module WatchHandler
18
- include OpenHAB::Log
19
-
20
- #
21
- # Creates trigger types and trigger type factories for OpenHAB
22
- #
23
- private_class_method def self.watch_trigger_type
24
- TriggerType.new(
25
- WATCH_TRIGGER_MODULE_ID,
26
- nil,
27
- 'A path change event is detected',
28
- 'Triggers when a path change event is detected',
29
- nil,
30
- org.openhab.core.automation.Visibility::VISIBLE,
31
- nil
32
- )
16
+ # Trigger ID for Watch Triggers
17
+ WATCH_TRIGGER_MODULE_ID = "jsr223.jruby.WatchTrigger"
18
+
19
+ # WatchService is only available in openHAB4
20
+ def self.factory
21
+ @factory ||= OSGi.service("org.openhab.core.service.WatchServiceFactory")
33
22
  end
34
23
 
35
- # Struct for Watch Events
36
- WatchEvent = Struct.new(:type, :path, :attachment)
24
+ # Due to the refactoring in OH4, we need a different watcher implementation
25
+ if WatchHandler.factory
26
+ # A class that implements openHAB4's WatchEventListener
27
+ # and also creates and removes a unique WatchService for each instance
28
+ class Watcher
29
+ # Use full java class name here to satisfy YARD linter
30
+ include org.openhab.core.service.WatchService::WatchEventListener
31
+ java_import org.openhab.core.service.WatchService
37
32
 
38
- # Trigger ID for Watch Triggers
39
- WATCH_TRIGGER_MODULE_ID = 'jsr223.jruby.WatchTrigger'
40
-
41
- # Extends the OpenHAB watch service to watch directories
42
- #
43
- # Must match java method name style
44
- # rubocop:disable Naming/MethodName
45
- class Watcher < org.openhab.core.service.AbstractWatchService
46
- java_import java.nio.file.StandardWatchEventKinds
47
-
48
- # Hash of event symbols as strings to map to NIO events
49
- STRING_TO_EVENT = {
50
- created: StandardWatchEventKinds::ENTRY_CREATE,
51
- deleted: StandardWatchEventKinds::ENTRY_DELETE,
52
- modified: StandardWatchEventKinds::ENTRY_MODIFY
53
- }.transform_keys(&:to_s).freeze
54
-
55
- # Hash of NIO event kinds to ruby symbols
56
- EVENT_TO_SYMBOL = STRING_TO_EVENT.invert.transform_values(&:to_sym).freeze
57
-
58
- # Creates a new Watch Service
59
- def initialize(path, types, &block)
60
- super(path)
61
- @types = types.map { |type| STRING_TO_EVENT[type] }
62
- @block = block
63
- end
33
+ # Hash of event symbols as strings to map to WatchService events
34
+ STRING_TO_EVENT = {
35
+ created: WatchService::Kind::CREATE,
36
+ deleted: WatchService::Kind::DELETE,
37
+ modified: WatchService::Kind::MODIFY
38
+ }.transform_keys(&:to_s).freeze
64
39
 
65
- # Invoked by java super class to get type of events to watch for
66
- # @param [String] _path ignored
67
- #
68
- # @return [Array] array of NIO event kinds
69
- def getWatchEventKinds(_path)
70
- @types
71
- end
40
+ # Hash of WatchService event kinds to ruby symbols
41
+ EVENT_TO_SYMBOL = STRING_TO_EVENT.invert.transform_values(&:to_sym).freeze
72
42
 
73
- # Invoked by java super class to check if sub directories should be watched
74
- # @return [false] false
75
- def watchSubDirectories
76
- false
43
+ # constructor
44
+ def initialize(path, subdirs, types, &block)
45
+ @types = types.map { |type| STRING_TO_EVENT[type] }
46
+ @block = block
47
+ @subdirs = subdirs
48
+ @path = Pathname.new(path)
49
+ return if path.to_s.start_with?(OpenHAB::Core.config_folder.to_s)
50
+
51
+ @custom_watcher = "jrubyscripting-#{SecureRandom.uuid}"
52
+ end
53
+
54
+ # Creates a new Watch Service and registers ourself as a listener
55
+ # This isn't an OSGi service, but it's called by {WatchTriggerHandler} below.
56
+ def activate
57
+ java_path = java.nio.file.Path.of(@path.to_s)
58
+
59
+ service_name = WatchService::SERVICE_PID
60
+ filter = if @custom_watcher
61
+ WatchHandler.factory.create_watch_service(@custom_watcher, java_path)
62
+ logger.trace { "Created a watch service #{@custom_watcher} for #{@path}" }
63
+ "(name=#{@custom_watcher})"
64
+ else
65
+ logger.trace { "Using configWatcher service for #{@path}" }
66
+ WatchService::CONFIG_WATCHER_FILTER
67
+ end
68
+
69
+ start = Time.now
70
+ sleep 0.1 until (@watch_service = OSGi.service(service_name, filter: filter)) || Time.now - start > 2
71
+
72
+ unless @watch_service
73
+ logger.warn("Watch service is not ready in time. #{@path} will not be monitored!")
74
+ return
75
+ end
76
+
77
+ @watch_service.register_listener(self, java_path, @subdirs)
78
+ logger.trace { "Registered watch service listener for #{@path} including subdirs: #{@subdirs}" }
79
+ end
80
+
81
+ # Unregister ourself as a listener and remove the watch service
82
+ def deactivate
83
+ @watch_service&.unregister_listener(self)
84
+ return unless @custom_watcher
85
+
86
+ WatchHandler.factory.remove_watch_service(@custom_watcher)
87
+ logger.trace { "Removed watch service #{@custom_watcher} for #{@path}" }
88
+ end
89
+
90
+ # Invoked by the WatchService when a watch event occurs
91
+ # @param [org.openhab.core.service.WatchService.Kind] kind WatchService event kind
92
+ # @param [java.nio.file.Path] path The path that had an event
93
+ def processWatchEvent(kind, path) # rubocop:disable Naming/MethodName
94
+ logger.trace { "processWatchEvent triggered #{path} #{kind} #{@types}" }
95
+ return unless @types.include?(kind)
96
+
97
+ # OH4 WatchService feeds us a relative path,
98
+ # but just in case its implementation changes in the future
99
+ path = path.absolute? ? Pathname.new(path.to_s) : @path + path.to_s
100
+ @block.call(Events::WatchEvent.new(EVENT_TO_SYMBOL[kind], path))
101
+ end
77
102
  end
103
+ else
104
+ # @deprecated OH3.4
105
+ #
106
+ # Extends the openHAB3 watch service to watch directories
107
+ #
108
+ # Must match java method name style
109
+ # rubocop:disable Naming/MethodName
110
+ class Watcher < org.openhab.core.service.AbstractWatchService
111
+ java_import java.nio.file.StandardWatchEventKinds
112
+
113
+ # Hash of event symbols as strings to map to NIO events
114
+ STRING_TO_EVENT = {
115
+ created: StandardWatchEventKinds::ENTRY_CREATE,
116
+ deleted: StandardWatchEventKinds::ENTRY_DELETE,
117
+ modified: StandardWatchEventKinds::ENTRY_MODIFY
118
+ }.transform_keys(&:to_s).freeze
119
+
120
+ # Hash of NIO event kinds to ruby symbols
121
+ EVENT_TO_SYMBOL = STRING_TO_EVENT.invert.transform_values(&:to_sym).freeze
122
+
123
+ # Creates a new Watch Service
124
+ def initialize(path, subdirs, types, &block)
125
+ super(path)
126
+ @types = types.map { |type| STRING_TO_EVENT[type] }
127
+ @block = block
128
+ @subdirs = subdirs
129
+ end
78
130
 
79
- # Invoked by java super class when an watch event occurs
80
- # @param [String] _event ignored
81
- # @param [StandardWatchEventKind] kind NIO watch event kind
82
- # @param [java.nio.Path] path that had an event
83
- def processWatchEvent(_event, kind, path)
84
- @block.call(WatchEvent.new(EVENT_TO_SYMBOL[kind], Pathname.new(path.to_s)))
131
+ # Invoked by java super class to get type of events to watch for
132
+ # @param [String] _path ignored
133
+ #
134
+ # @return [Array] array of NIO event kinds
135
+ def getWatchEventKinds(_path)
136
+ @types
137
+ end
138
+
139
+ # Invoked by java super class to check if sub directories should be watched
140
+ # @return [false] false
141
+ def watchSubDirectories
142
+ logger.trace("watchSubDirectories returning #{@subdirs}")
143
+ @subdirs
144
+ end
145
+
146
+ # Invoked by java super class when a watch event occurs
147
+ # @param [String] _event ignored
148
+ # @param [StandardWatchEventKind] kind NIO watch event kind
149
+ # @param [java.nio.file.Path] path that had an event
150
+ def processWatchEvent(_event, kind, path)
151
+ @block.call(Events::WatchEvent.new(EVENT_TO_SYMBOL[kind], Pathname.new(path.to_s)))
152
+ end
85
153
  end
154
+ # rubocop:enable Naming/MethodName
86
155
  end
87
- # rubocop:enable Naming/MethodName
88
156
 
89
- # Implements the OpenHAB TriggerHandler interface to process Watch Triggers
157
+ # Implements the openHAB TriggerHandler interface to process Watch Triggers
90
158
  class WatchTriggerHandler
91
- include OpenHAB::Log
92
159
  include org.openhab.core.automation.handler.TriggerHandler
93
160
 
161
+ class << self
162
+ #
163
+ # Returns the directory to watch, subdir flag, and glob pattern to use
164
+ #
165
+ # @param [String] path The path provided to the watch trigger which may include glob patterns
166
+ # @param [String] glob The glob pattern provided by the user
167
+ #
168
+ # @return [Array<String,Boolean,String>,nil] An array of directory to watch,
169
+ # whether to watch in subdirectories, and the glob pattern to use.
170
+ # Returns nil if the given path doesn't exist all the way to root, e.g. /nonexistent
171
+ #
172
+ def dir_subdir_glob(path, glob)
173
+ pathname = Pathname.new(path)
174
+ return [pathname.dirname.to_s, false, path] if pathname.file?
175
+
176
+ dir = find_parent(pathname)
177
+ return unless dir
178
+
179
+ # we were given the exact existing directory to watch
180
+ if dir == pathname
181
+ glob_pathname = Pathname.new(glob)
182
+ subdirs = recursive_glob?(glob)
183
+ unless glob_pathname.absolute? || glob.start_with?("**")
184
+ glob = subdirs ? "**/#{glob}" : "#{path}/#{glob}"
185
+ end
186
+ return [path, subdirs, glob]
187
+ end
188
+
189
+ if glob != "*" # if it isn't the default glob
190
+ logger.warn("The provided glob '#{glob}' is ignored because " \
191
+ "the given path (#{path}) isn't an existing directory, " \
192
+ "so it is used as the glob pattern")
193
+ end
194
+
195
+ relative_glob = pathname.relative_path_from(dir).to_s
196
+ subdir_flag = dir != pathname.dirname || recursive_glob?(relative_glob)
197
+ [dir.to_s, subdir_flag, path]
198
+ end
199
+
200
+ # Returns true if string contains glob characters
201
+ def glob?(string)
202
+ unless @regexp
203
+ # (?<!X) is a negative lookbehind pattern: only match the pattern if it wasn't
204
+ # preceded with X. In this case we want to match only non escaped glob chars
205
+ glob_pattern = %w[** * ? [ ] { }].map { |char| Regexp.escape(char) }
206
+ .join("|")
207
+ .then { |pattern| "(?<!\\\\)(#{pattern})" }
208
+
209
+ @regexp = Regexp.new(glob_pattern)
210
+ end
211
+ @regexp.match?(string)
212
+ end
213
+
214
+ # Returns true if string contains a recursive glob pattern (** or x/y)
215
+ def recursive_glob?(string)
216
+ /(?<!\\\\)\*\*/.match?(string) || Pathname.new(string).each_filename.to_a.size > 1
217
+ end
218
+
219
+ #
220
+ # Find the part of the path that exists on disk.
221
+ #
222
+ # /a/b/c/*/d/*.e -> /a/b/c if it exists
223
+ # /a/b/c/d/e/f -> /a/b/c if /a/b/c directory exists, but /a/b/c/d doesn't exist
224
+ # /a/b/c -> nil if /a doesn't exist
225
+ # / -> /
226
+ #
227
+ # @param [Pathname] pathname The pathname to check
228
+ # @return [Pathname,nil] The leading part of the path name that corresponds to
229
+ # an existing directory. nil if none was found up until the root directory
230
+ #
231
+ def find_parent(pathname)
232
+ return pathname if pathname.root?
233
+
234
+ pathname.ascend { |part| return part if part.directory? && !part.root? }
235
+ end
236
+ end
237
+
94
238
  # Creates a new WatchTriggerHandler
95
- # @param [Trigger] trigger OpenHAB trigger associated with handler
239
+ # @param [org.openhab.core.automation.Trigger] trigger
96
240
  #
97
241
  def initialize(trigger)
98
242
  @trigger = trigger
99
243
  config = trigger.configuration.properties.to_hash.transform_keys(&:to_sym)
100
- @path = config[:path]
101
- @watcher = Watcher.new(@path, config[:types], &watch_event_handler(config[:glob]))
244
+ @path, subdirs, glob = self.class.dir_subdir_glob(config[:path], config[:glob])
245
+ logger.trace { "WatchTriggerHandler#initialize path: #{@path}, subdirs: #{subdirs}, glob: #{glob}" }
246
+ unless @path
247
+ logger.warn("Watch error: the given path doesn't exist: '#{@path}'")
248
+ return
249
+ end
250
+ @watcher = Watcher.new(@path, subdirs, config[:types], &watch_event_handler(glob))
102
251
  @watcher.activate
103
- logger.trace("Created watcher for #{@path}")
252
+ logger.trace { "Created watcher for #{@path} subdirs: #{subdirs}" }
104
253
  end
105
254
 
106
255
  # Create a lambda to use to invoke rule engine when file watch notification happens
107
256
  # @param [String] glob to match for notification events
108
257
  #
109
- # @return [Lambda] lambda to execute on notification events
258
+ # @return [Proc] lambda to execute on notification events
110
259
  #
111
260
  def watch_event_handler(glob)
112
- lambda { |watch_event|
113
- logger.trace("Received event(#{watch_event})")
114
- if watch_event.path.fnmatch?(glob)
115
- @rule_engine_callback&.triggered(@trigger, { 'event' => watch_event })
261
+ default_fs = java.nio.file.FileSystems.default
262
+ path_matcher = default_fs.get_path_matcher("glob:#{glob}")
263
+ lambda do |watch_event|
264
+ if path_matcher.matches(default_fs.get_path(watch_event.path.to_s))
265
+ logger.trace do
266
+ "Received event(#{watch_event}) glob: #{glob}, rule_engine_callback = #{@rule_engine_callback}"
267
+ end
268
+ @rule_engine_callback&.triggered(@trigger, { "event" => watch_event })
116
269
  else
117
- logger.trace("Event #{watch_event} did not match glob(#{glob})")
270
+ logger.trace { "Event #{watch_event} did not match glob(#{glob})" }
118
271
  end
119
- }
272
+ end
120
273
  end
121
274
 
122
- # Called by OpenHAB to set the rule engine to invoke when triggered
123
- # Must match java method name style
275
+ # Called by openHAB to set the rule engine to invoke when triggered
124
276
  def setCallback(callback) # rubocop:disable Naming/MethodName
125
277
  @rule_engine_callback = callback
126
278
  end
@@ -129,41 +281,44 @@ module OpenHAB
129
281
  # Dispose of handler which deactivates watcher
130
282
  #
131
283
  def dispose
132
- logger.trace("Deactivating watcher for #{@path}")
133
- @watcher&.deactivate
284
+ logger.trace { "Deactivating watcher for #{@path}" }
285
+ @watcher.deactivate
134
286
  end
135
287
  end
136
288
 
137
289
  # Implements the ScriptedTriggerHandlerFactory interface to create a new Trigger Handler
138
290
  class WatchTriggerHandlerFactory
291
+ include Singleton
139
292
  include org.openhab.core.automation.module.script.rulesupport.shared.factories.ScriptedTriggerHandlerFactory
140
293
 
141
- # Invoked by the OpenHAB core to get a trigger handler for the supllied trigger
142
- # @param [Trigger] trigger OpenHAB trigger
294
+ def initialize
295
+ Core.automation_manager.add_trigger_handler(
296
+ WATCH_TRIGGER_MODULE_ID,
297
+ self
298
+ )
299
+
300
+ Core.automation_manager.add_trigger_type(org.openhab.core.automation.type.TriggerType.new(
301
+ WATCH_TRIGGER_MODULE_ID,
302
+ nil,
303
+ "A path change event is detected",
304
+ "Triggers when a path change event is detected",
305
+ nil,
306
+ org.openhab.core.automation.Visibility::VISIBLE,
307
+ nil
308
+ ))
309
+ logger.trace("Added watch trigger handler")
310
+ end
311
+
312
+ # Invoked by openHAB core to get a trigger handler for the supllied trigger
313
+ # @param [org.openhab.core.automation.Trigger] trigger
143
314
  #
144
315
  # @return [WatchTriggerHandler] trigger handler for supplied trigger
145
316
  def get(trigger)
146
317
  WatchTriggerHandler.new(trigger)
147
318
  end
148
319
  end
149
-
150
- #
151
- # Creates trigger types and trigger type factories for OpenHAB
152
- #
153
- def self.add_watch_handler
154
- java_import org.openhab.core.automation.type.TriggerType
155
- OpenHAB::Core.automation_manager.add_trigger_handler(
156
- WATCH_TRIGGER_MODULE_ID,
157
- WatchTriggerHandlerFactory.new
158
- )
159
-
160
- OpenHAB::Core.automation_manager.add_trigger_type(watch_trigger_type)
161
- OpenHAB::Log.logger(self).trace('Added watch trigger handler')
162
- end
163
320
  end
164
321
  end
165
322
  end
166
323
  end
167
324
  end
168
- # Add the watch handler to OpenHAB
169
- OpenHAB::DSL::Rules::Triggers::WatchHandler.add_watch_handler
@@ -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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Rules
6
+ end
7
+ end
8
+ end