openhab-scripting 4.46.2 → 5.0.0

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 (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 -36
@@ -0,0 +1,355 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenHAB
6
+ # rubocop:disable Layout/LineLength
7
+
8
+ #
9
+ # Provides access to the openHAB logging facilities using Ruby logging methods
10
+ #
11
+ # Logging is available everywhere through the {#logger} object.
12
+ #
13
+ # The logging prefix is `org.openhab.automation.jrubyscripting`.
14
+ # Logging within file-based rules will have the name of the file appended to
15
+ # the logger name. Logging inside of a rule will have the id of the rule
16
+ # appended to the logger name. Any classes will have the full class anem
17
+ # appended to the logger name.
18
+ #
19
+ # @example The following entries are in a file named 'log_test.rb'
20
+ # logger.trace('Test logging at trace') # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.log_test] - Test logging at trace
21
+ # logger.debug('Test logging at debug') # 2020-12-03 18:05:32.020 [DEBUG] [org.openhab.automation.jrubyscripting.log_test] - Test logging at debug
22
+ # logger.warn('Test logging at warn') # 2020-12-03 18:05:41.817 [WARN ] [org.openhab.automation.jrubyscripting.log_test] - Test logging at warn
23
+ # logger.info('Test logging at info') # 2020-12-03 18:05:41.817 [INFO ] [org.openhab.automation.jrubyscripting.log_test] - Test logging at info
24
+ # logger.error('Test logging at error') # 2020-12-03 18:06:02.021 [ERROR] [org.openhab.automation.jrubyscripting.log_test] - Test logging at error
25
+ #
26
+ # @example The following entries are in a file named 'log_test.rb'
27
+ # rule 'foo' do
28
+ # run { logger.trace('Test logging at trace') } # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.foo] - Test logging at trace
29
+ # on_load
30
+ # end
31
+ #
32
+ #
33
+ # @example A log entry from inside a class
34
+ # class MyClass
35
+ # def initialize
36
+ # logger.trace("hi!") # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.MyClass] - hi!
37
+ # end
38
+ # end
39
+ #
40
+ module Log
41
+ # rubocop:enable Layout/LineLength
42
+
43
+ # @!visibility private
44
+ def self.included(base)
45
+ return if base.singleton_class?
46
+
47
+ base.singleton_class.include(self)
48
+ end
49
+
50
+ protected
51
+
52
+ #
53
+ # Retrieve the {Logger} for this class.
54
+ #
55
+ # @return [Logger]
56
+ #
57
+ def logger
58
+ # no caching on `main`
59
+ if (instance_of?(Object) && !singleton_methods.empty?) ||
60
+ # also pretend loggers in example groups are in the top-level
61
+ (defined?(::RSpec::Core::ExampleGroup) && is_a?(Module) && self < ::RSpec::Core::ExampleGroup)
62
+ return Log.logger(:main)
63
+ end
64
+ return @logger ||= Log.logger(self) if equal?(self.class) || is_a?(Module)
65
+
66
+ self.class.logger
67
+ end
68
+
69
+ @loggers = {}
70
+ class << self
71
+ #
72
+ # Retrieve a {Logger} for a particular object.
73
+ #
74
+ # @param [Module,String] object Object the logger is for, or explicit name of the logger.
75
+ # @return [Logger]
76
+ #
77
+ def logger(object)
78
+ case object
79
+ when Module
80
+ name = Logger::PREFIX
81
+ klass = java_klass(object)
82
+ name += ".#{klass.name.gsub("::", ".")}" if klass.name
83
+ when String
84
+ name = object
85
+ when :main
86
+ name = "#{Logger::PREFIX}.#{rules_file.tr_s(":", "_")
87
+ .gsub(/[^A-Za-z0-9_.-]/, "")}"
88
+ return @loggers[name] ||= BiLogger.new(Logger.new(name))
89
+ end
90
+
91
+ @loggers[name] ||= Logger.new(name)
92
+ end
93
+
94
+ private
95
+
96
+ # Get the appropriate java class for the supplied klass if the supplied
97
+ # class is a java class
98
+ # @param [Class] klass to inspect
99
+ # @return Class or Java class of supplied class
100
+ def java_klass(klass)
101
+ if klass.respond_to?(:java_class) &&
102
+ klass.java_class &&
103
+ !klass.java_class.name.start_with?("org.jruby.Ruby") &&
104
+ !klass.java_class.name.start_with?("org.jruby.gen")
105
+ klass = klass.java_class
106
+ end
107
+ klass
108
+ end
109
+
110
+ #
111
+ # Figure out the log prefix
112
+ #
113
+ # @return [String] Prefix for log messages
114
+ #
115
+ def rules_file
116
+ caller_locations(3, 2).map(&:path)
117
+ .grep_v(%r{lib/openhab/log\.rb})
118
+ .first
119
+ .then { |caller| File.basename(caller, ".*") if caller }
120
+ end
121
+ end
122
+ end
123
+
124
+ #
125
+ # Ruby Logger that forwards messages at appropriate levels to openHAB Logger
126
+ #
127
+ class Logger
128
+ # The base prefix for all loggers from this gem.
129
+ PREFIX = "org.openhab.automation.jrubyscripting"
130
+
131
+ # @return [Array<symbol>] Supported logging levels
132
+ LEVELS = %i[trace debug warn info error].freeze
133
+
134
+ #
135
+ # Regex for matching internal calls in a stack trace
136
+ #
137
+ INTERNAL_CALL_REGEX = %r{(openhab-scripting-.*/lib)|org[./]jruby}.freeze
138
+ private_constant :INTERNAL_CALL_REGEX
139
+
140
+ #
141
+ # Regex for matching internal calls in a java stack trace
142
+ #
143
+ EXCLUDED_JAVA_PACKAGES = /jdk\.internal\.reflect|java\.lang\.reflect|org\.openhab|java\.lang\.Thread\.run/.freeze
144
+ private_constant :EXCLUDED_JAVA_PACKAGES
145
+
146
+ #
147
+ # Regex for matching internal calls in a java stack trace
148
+ #
149
+ JAVA_INTERNAL_CALL_REGEX = Regexp.union(INTERNAL_CALL_REGEX, EXCLUDED_JAVA_PACKAGES).freeze
150
+ private_constant :JAVA_INTERNAL_CALL_REGEX
151
+
152
+ class << self
153
+ # The root logger (all of openHAB)
154
+ # @return [Logger]
155
+ def root
156
+ Log.logger(org.slf4j.Logger::ROOT_LOGGER_NAME)
157
+ end
158
+
159
+ # The root logger for this gem
160
+ # @return [Logger]
161
+ def gem_root
162
+ Log.logger(PREFIX)
163
+ end
164
+
165
+ # The events logger (events.log)
166
+ # @return [Logger]
167
+ def events
168
+ Log.logger("openhab.event")
169
+ end
170
+
171
+ # @!visibility private
172
+ def log_service
173
+ @log_service = OSGi.service("org.apache.karaf.log.core.LogService")
174
+ end
175
+
176
+ private
177
+
178
+ # @!macro def_level_method
179
+ # @!method $1(msg = nil)
180
+ #
181
+ # Log a message at $1 level.
182
+ #
183
+ # @param msg [Object, nil] The log message
184
+ # @yield
185
+ # Pass a block to delay generating the log message until it's
186
+ # confirmed that logging is enabled at $1 level.
187
+ # @yieldreturn [Object, nil] The log message
188
+ # @return [void]
189
+ #
190
+ # @example
191
+ # logger.$1 do
192
+ # total = Item1.state + Item2.state
193
+ # average = total / 2
194
+ # "Total: #{total}, Average: #{average}"
195
+ # end
196
+ #
197
+ def def_level_method(level)
198
+ define_method(level) do |msg = nil, &block|
199
+ log(severity: level, msg: msg, &block)
200
+ end
201
+ end
202
+
203
+ # @!macro def_level_predicate
204
+ # @!method $1?
205
+ #
206
+ # If the logger is enabled at $1 level.
207
+ #
208
+ # @return [true,false]
209
+ #
210
+ def def_level_predicate(level)
211
+ define_method("#{level}?") { @slf4j_logger.send("is_#{level}_enabled") }
212
+ end
213
+ end
214
+
215
+ # @!visibility private
216
+ #
217
+ # Create a new logger
218
+ #
219
+ # @param [String] name of the logger
220
+ #
221
+ def initialize(name)
222
+ @slf4j_logger = org.slf4j.LoggerFactory.getLogger(name)
223
+ end
224
+
225
+ # The logger name
226
+ # @return [String]
227
+ def name
228
+ @slf4j_logger.name
229
+ end
230
+
231
+ # @return [String]
232
+ def inspect
233
+ "#<OpenHAB::Logger #{name}>"
234
+ end
235
+ alias_method :to_s, :inspect
236
+
237
+ # @!attribute [rw] level
238
+ #
239
+ # @note When a logger's level is modified, the logging infrastructure has
240
+ # to reload, and logging may be completely unavailable for a short time.
241
+ #
242
+ # @return [:error,:warn,:info,:debug,:trace] The current log level
243
+ #
244
+ def level
245
+ Logger.log_service.get_level(name)[name]&.downcase&.to_sym
246
+ end
247
+
248
+ def level=(level)
249
+ return if self.level == level
250
+
251
+ Logger.log_service.set_level(name, level.to_s)
252
+ end
253
+
254
+ def_level_method(:error)
255
+ def_level_predicate(:error)
256
+ def_level_method(:warn)
257
+ def_level_predicate(:warn)
258
+ def_level_method(:info)
259
+ def_level_predicate(:info)
260
+ def_level_method(:debug)
261
+ def_level_predicate(:debug)
262
+ def_level_method(:trace)
263
+ def_level_predicate(:trace)
264
+
265
+ #
266
+ # Print error and stack trace without calls to internal classes
267
+ #
268
+ # @param [Exception] exception A rescued error
269
+ # @return [void]
270
+ #
271
+ def log_exception(exception)
272
+ exception = clean_backtrace(exception)
273
+ error do
274
+ "#{exception.message} (#{exception.class})\n#{exception.backtrace&.join("\n")}"
275
+ end
276
+ end
277
+
278
+ private
279
+
280
+ #
281
+ # Cleans the backtrace of an error to remove internal calls. If logging is set
282
+ # to debug or lower, the full backtrace is kept
283
+ #
284
+ # @param [Exception] error An exception to be cleaned
285
+ #
286
+ # @return [Exception] the exception, potentially with a cleaned backtrace.
287
+ #
288
+ def clean_backtrace(error)
289
+ return error if debug?
290
+
291
+ if error.respond_to? :backtrace_locations
292
+ backtrace = error.backtrace_locations.map(&:to_s).grep_v(INTERNAL_CALL_REGEX)
293
+ error.set_backtrace(backtrace)
294
+ elsif error.respond_to? :stack_trace
295
+ backtrace = error.stack_trace.reject { |line| JAVA_INTERNAL_CALL_REGEX.match? line.to_s }
296
+ error.set_stack_trace(backtrace)
297
+ end
298
+ error
299
+ end
300
+
301
+ #
302
+ # Log a message to the openHAB Logger
303
+ #
304
+ # @param [Symbol] severity Severity to log message at
305
+ # @param [Object] msg to log, if no msg supplied and a block is provided,
306
+ # the msg is taken from the result of the block
307
+ #
308
+ def log(severity:, msg: nil)
309
+ raise ArgumentError, "Unknown Severity #{severity}" unless LEVELS.include? severity
310
+
311
+ # Dynamically check enablement of underlying logger
312
+ return unless send("#{severity}?")
313
+
314
+ # Process block if no message provided
315
+ msg = yield if msg.nil? && block_given?
316
+
317
+ @slf4j_logger.send(severity, msg.to_s)
318
+ end
319
+ end
320
+
321
+ module Log
322
+ # Logger that changes its backing logger depending on thread context
323
+ class BiLogger < Logger
324
+ @rule_loggers = {}
325
+ class << self
326
+ # class shared cache of loggers-per-rule
327
+ attr_reader :rule_loggers
328
+ end
329
+
330
+ def initialize(file_logger) # rubocop:disable Lint/MissingSuper
331
+ @file_logger = file_logger
332
+ end
333
+
334
+ # The current logger - the file logger if rule_uid is nil,
335
+ # otherwise a logger specific to the rule.
336
+ def current_logger
337
+ return @file_logger unless (rule_uid = Thread.current[:openhab_rule_uid])
338
+
339
+ rule_type = Thread.current[:openhab_rule_type]
340
+ full_id = "#{rule_type}:#{rule_uid}"
341
+
342
+ self.class.rule_loggers[full_id] ||= Logger.new("#{Logger::PREFIX}.#{rule_type}.#{rule_uid
343
+ .gsub(/[^A-Za-z0-9_.:-]/, "")}")
344
+ end
345
+
346
+ extend Forwardable
347
+ def_delegators :current_logger, *(Logger.public_instance_methods.select do |m|
348
+ Logger.instance_method(m).owner == Logger
349
+ end - BasicObject.public_instance_methods)
350
+ end
351
+ private_constant :BiLogger
352
+ end
353
+
354
+ Object.include(Log)
355
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ #
5
+ # OSGi services interface
6
+ #
7
+ module OSGi
8
+ class << self
9
+ #
10
+ # @param name [String] The service name
11
+ # @param filter [String] Filter for service names. See https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/Filter.html
12
+ #
13
+ # @return [Object]
14
+ #
15
+ def service(name, filter: nil)
16
+ services(name, filter: filter).first
17
+ end
18
+
19
+ #
20
+ # @param name [String] The service name
21
+ # @param filter [String] Filter for service names. See https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/Filter.html
22
+ #
23
+ # @return [Array<Object>] An array of services
24
+ #
25
+ def services(name, filter: nil)
26
+ (bundle_context.get_service_references(name, filter) || []).map do |reference|
27
+ logger.trace "OSGi service found for '#{name}' using OSGi Service Reference #{reference}"
28
+ bundle_context.get_service(reference)
29
+ end
30
+ end
31
+
32
+ #
33
+ # Register a new service instance with OSGi
34
+ #
35
+ # @param [Object] instance The service instance
36
+ # @param [Module] interfaces The interfaces to register this service for.
37
+ # If not provided, it will default to all Java interfaces the instance
38
+ # implements.
39
+ # @param [Hash] properties The service registration properties.
40
+ # @return [org.osgi.framework.ServiceRegistration]
41
+ #
42
+ def register_service(instance, *interfaces, **properties)
43
+ if interfaces.empty?
44
+ interfaces = instance.class.ancestors.select { |k| k.respond_to?(:java_class) && k.java_class&.interface? }
45
+ end
46
+
47
+ bundle = org.osgi.framework.FrameworkUtil.get_bundle(interfaces.first.java_class)
48
+ bundle.bundle_context.register_service(
49
+ interfaces.map(&:java_class).map(&:name).to_java(java.lang.String),
50
+ instance,
51
+ java.util.Hashtable.new(properties)
52
+ )
53
+ end
54
+
55
+ # @!attribute [r] bundle_context
56
+ # @return [org.osgi.framework.BundleContext] OSGi bundle context for ScriptExtension Class
57
+ def bundle_context
58
+ @bundle_context ||= bundle.bundle_context
59
+ end
60
+
61
+ # @!attribute [r] bundle
62
+ # @return [org.osgi.framework.Bundle] The OSGi Bundle for ScriptExtension Class
63
+ def bundle
64
+ @bundle ||= org.osgi.framework.FrameworkUtil.getBundle($scriptExtension.java_class)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module RSpec
5
+ #
6
+ # Contains configuration for how the openHAB instance should be set
7
+ # up for the testing environment.
8
+ #
9
+ module Configuration
10
+ class << self
11
+ #
12
+ # Copy binding configuration from the root openHAB instance.
13
+ #
14
+ # Default `true`.
15
+ # @return [true, false]
16
+ #
17
+ attr_accessor :include_bindings
18
+
19
+ #
20
+ # Copy the JSONDB (managed thing and item configuration) from the root
21
+ # openHAB instance.
22
+ #
23
+ # Default `true`.
24
+ #
25
+ # @return [true, false]
26
+ #
27
+ attr_accessor :include_jsondb
28
+
29
+ #
30
+ # Use a private (empty) confdir (scripts, rules, items, and things
31
+ # files), instead of sharing with the root openHAB instance.
32
+ #
33
+ # Default `false`.
34
+ #
35
+ # @return [true, false]
36
+ #
37
+ attr_accessor :private_confdir
38
+
39
+ #
40
+ # Use the root openHAB instance directly, rather than creating a
41
+ # private (but linked) instance.
42
+ #
43
+ # Default `false`.
44
+ #
45
+ # @return [true, false]
46
+ #
47
+ attr_accessor :use_root_instance
48
+ end
49
+
50
+ self.include_bindings = true
51
+ self.include_jsondb = true
52
+ self.private_confdir = false
53
+ self.use_root_instance = false
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module RSpec
5
+ # ::RSpec::ExampleGroup extensions
6
+ module ExampleGroup
7
+ # Extensions for ::RSpec::ExampleGroup's singleton class.
8
+ module ClassMethods
9
+ # @!attribute [w] mock_timers
10
+ #
11
+ # Set if timers should be mocked for this example group.
12
+ #
13
+ # @param value [true, false, nil]
14
+ # @return [true, false, nil]
15
+ #
16
+ # @example
17
+ # describe "my_rule" do
18
+ # self.mock_timers = false
19
+ #
20
+ # it "runs a timer" do
21
+ # expect(self.class.mock_timers?).to be false
22
+ # end
23
+ # end
24
+ #
25
+ def mock_timers=(value)
26
+ @mock_timers = value
27
+ end
28
+
29
+ #
30
+ # If timers are mocked for this example group
31
+ #
32
+ # It will search through parent groups until it finds one where it's
33
+ # explicitly defined, or defaults to `true` if none are.
34
+ #
35
+ # @return [true, false]
36
+ #
37
+ def mock_timers?
38
+ return @mock_timers if instance_variable_defined?(:@mock_timers) && !@mock_timers.nil?
39
+ return superclass.mock_timers? if superclass.is_a?(ClassMethods)
40
+
41
+ true
42
+ end
43
+
44
+ # @!attribute [w] consistent_proxies
45
+ #
46
+ # Set if Items and Thing proxies should return consistent objects.
47
+ #
48
+ # @param value [true, false, nil]
49
+ # @return [true, false, nil]
50
+ #
51
+ # @example
52
+ # describe "my_rule" do
53
+ # self.consistent_proxies = false
54
+ #
55
+ # it "does something" do
56
+ # expect(self.class.consistent_proxies?).to be false
57
+ # end
58
+ # end
59
+ #
60
+ # @see #consistent_proxies?
61
+ #
62
+ def consistent_proxies=(value)
63
+ @consistent_proxies = value
64
+ end
65
+
66
+ #
67
+ # If Item and Thing proxies will consistently return the same object.
68
+ #
69
+ # Useful for mocking and using the `be` matcher.
70
+ #
71
+ # It will search through parent groups until it finds one where it's
72
+ # explicitly defined, or defaults to `true` if none are.
73
+ #
74
+ # @return [true, false]
75
+ #
76
+ def consistent_proxies?
77
+ return @consistent_proxies if instance_variable_defined?(:@consistent_proxies) && !@consistent_proxies.nil?
78
+ return superclass.consistent_proxies? if superclass.is_a?(ClassMethods)
79
+
80
+ true
81
+ end
82
+
83
+ # @!attribute [w] propagate_exceptions
84
+ #
85
+ # Set if exceptions in rules should be propagated in specs, instead of just logged.
86
+ #
87
+ # @param value [true, false, nil]
88
+ # @return [true, false, nil]
89
+ #
90
+ # @example
91
+ # describe "my_rule" do
92
+ # self.propagate_exceptions = false
93
+ #
94
+ # it "logs exceptions in rule execution" do
95
+ # expect(self.class.propagate_exceptions?).to be false
96
+ # rule do
97
+ # on_load
98
+ # run { raise "exception is logged" }
99
+ # end
100
+ # expect(spec_log_lines).to include(match(/exception is logged/))
101
+ # end
102
+ # end
103
+ #
104
+ def propagate_exceptions=(value)
105
+ @propagate_exceptions = value
106
+ end
107
+
108
+ #
109
+ # If timers are mocked for this example group
110
+ #
111
+ # It will search through parent groups until it finds one where it's
112
+ # explicitly defined, or defaults to `true` if none are.
113
+ #
114
+ # @return [true, false]
115
+ #
116
+ def propagate_exceptions?
117
+ if instance_variable_defined?(:@propagate_exceptions) && !@propagate_exceptions.nil?
118
+ return @propagate_exceptions
119
+ end
120
+ return superclass.propagate_exceptions? if superclass.is_a?(ClassMethods)
121
+
122
+ true
123
+ end
124
+ end
125
+
126
+ # @!visibility private
127
+ def self.included(klass)
128
+ klass.singleton_class.include(ClassMethods)
129
+ end
130
+ end
131
+ end
132
+ end