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,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "types"
4
+
5
+ Dir[File.expand_path("items/*.rb", __dir__)].sort.each do |f|
6
+ require f
7
+ end
8
+
9
+ module OpenHAB
10
+ module Core
11
+ #
12
+ # Contains the core types that openHAB uses to represent items.
13
+ # Items have states from the {Types} module.
14
+ #
15
+ # You may use an item or group name anywhere {DSL} (or just {Core::EntityLookup})
16
+ # is available, and it will automatically be loaded.
17
+ #
18
+ module Items
19
+ class << self
20
+ # Imports all of the item classes into the global namespace
21
+ # for convenient access.
22
+ def import_into_global_namespace
23
+ concrete_item_classes.each do |k|
24
+ const_name = k.java_class.simple_name
25
+ Object.const_set(const_name, k) unless Object.const_defined?(const_name)
26
+ end
27
+ Object.const_set(:GenericItem, GenericItem) unless Object.const_defined?(:GenericItem)
28
+ Object.const_set(:Item, Item) unless Object.const_defined?(:Item)
29
+ end
30
+
31
+ private
32
+
33
+ # takes an array of Type java classes and returns
34
+ # all the Enum values, in a flat array
35
+ def values_for_enums(enums)
36
+ enums.map(&:ruby_class)
37
+ .select { |k| k < java.lang.Enum }
38
+ .flat_map(&:values)
39
+ end
40
+
41
+ # define predicates for checking if an item is in one of the Enum states
42
+ def def_predicate_methods(klass)
43
+ values_for_enums(klass.ACCEPTED_DATA_TYPES).each do |state|
44
+ _command_predicate, state_predicate = Types::PREDICATE_ALIASES[state.to_s]
45
+ next if klass.instance_methods.include?(state_predicate)
46
+
47
+ logger.trace("Defining #{klass}##{state_predicate} for #{state}")
48
+ klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
49
+ def #{state_predicate} # def on?
50
+ raw_state.as(#{state.class.java_class.simple_name}).equal?(#{state}) # raw_state.as(OnOffType) == ON
51
+ end # end
52
+ RUBY
53
+ end
54
+ end
55
+
56
+ # define methods for commanding an item to one of the Enum states
57
+ # as well as predicates for if an ItemCommandEvent is one of those commands
58
+ def def_command_methods(klass)
59
+ values_for_enums(klass.ACCEPTED_COMMAND_TYPES).each do |value|
60
+ command = Types::COMMAND_ALIASES[value.to_s]
61
+ next if klass.instance_methods.include?(command)
62
+
63
+ logger.trace("Defining #{klass}##{command} for #{value}")
64
+ klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
65
+ ruby2_keywords def #{command}(*args, &block) # ruby2_keywords def on(*args, &block)
66
+ command(#{value}, *args, &block) # command(ON, *args, &block)
67
+ end # end
68
+ RUBY
69
+
70
+ logger.trace("Defining Enumerable##{command} for #{value}")
71
+ Enumerable.class_eval <<~RUBY, __FILE__, __LINE__ + 1
72
+ def #{command} # def on
73
+ each(&:#{command}) # each(&:on)
74
+ end # end
75
+ RUBY
76
+
77
+ logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
78
+ Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
79
+ def #{command}? # def refresh?
80
+ command.as(#{value.class.java_class.simple_name}).equal?(#{value}) # command.as(RefreshType).equal?(REFRESH)
81
+ end # end
82
+ RUBY
83
+ end
84
+ end
85
+
86
+ def concrete_item_classes
87
+ constants.map { |c| const_get(c) }
88
+ .grep(Module)
89
+ .select { |k| k < GenericItem }
90
+ end
91
+ end
92
+
93
+ # sort classes by hierarchy so we define methods on parent classes first
94
+ constants.map { |c| const_get(c) }
95
+ .grep(Module)
96
+ .select { |k| k <= GenericItem && k != GroupItem && k != StringItem }
97
+ .sort { |a, b| (a < b) ? 1 : -1 }
98
+ .each do |klass|
99
+ klass.field_reader :ACCEPTED_COMMAND_TYPES, :ACCEPTED_DATA_TYPES unless klass == GenericItem
100
+
101
+ def_predicate_methods(klass)
102
+ def_command_methods(klass)
103
+ end
104
+
105
+ prepend_accepted_data_types
106
+ end
107
+ end
108
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenHAB
4
- module DSL
4
+ module Core
5
5
  # Common base class for array-like collections that have lookup
6
6
  # methods to avoid instantiating the elements if you only use
7
7
  # the lookup method
@@ -11,6 +11,12 @@ module OpenHAB
11
11
  module LazyArray
12
12
  include Enumerable
13
13
 
14
+ # @!visibility private
15
+ def self.included(klass)
16
+ klass.undef_method :inspect
17
+ klass.undef_method :to_s
18
+ end
19
+
14
20
  # Calls the given block once for each object, passing that object as a
15
21
  # parameter. Returns self.
16
22
  #
@@ -30,14 +36,14 @@ module OpenHAB
30
36
 
31
37
  # Delegate any other methods to the actual array, exclude mutating methods
32
38
  def method_missing(method, *args, &block)
33
- return to_a.send(method, *args, &block) if method[-1] != '!' && Array.instance_methods.include?(method)
39
+ return to_a.send(method, *args, &block) if method[-1] != "!" && Array.instance_methods.include?(method)
34
40
 
35
41
  super
36
42
  end
37
43
 
38
44
  # @!visibility private
39
45
  def respond_to_missing?(method, include_private = false)
40
- return true if method[-1] != '!' && Array.instance_methods.include?(method.to_sym)
46
+ return true if method[-1] != "!" && Array.instance_methods.include?(method.to_sym)
41
47
 
42
48
  super
43
49
  end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ require_relative "script_handling"
6
+
7
+ module OpenHAB
8
+ module Core
9
+ # @!visibility private
10
+ class ProfileFactory
11
+ include org.openhab.core.thing.profiles.ProfileFactory
12
+ include Singleton
13
+
14
+ # rubocop:disable Naming/MethodName
15
+ class Profile
16
+ include org.openhab.core.thing.profiles.StateProfile
17
+
18
+ def initialize(callback, context, uid, thread_locals, block)
19
+ unless callback.class.ancestors.include?(Things::ProfileCallback)
20
+ callback.class.prepend(Things::ProfileCallback)
21
+ callback.class.field_reader :link
22
+ end
23
+
24
+ @callback = callback
25
+ @context = context
26
+ @uid = uid
27
+ @thread_locals = thread_locals
28
+ @block = block
29
+ end
30
+
31
+ # @!visibility private
32
+ def getProfileTypeUID
33
+ @uid
34
+ end
35
+
36
+ # @!visibility private
37
+ def onCommandFromItem(command)
38
+ return unless process_event(:command_from_item, command: command) == true
39
+
40
+ logger.trace("Forwarding original command")
41
+ @callback.handle_command(command)
42
+ end
43
+
44
+ # @!visibility private
45
+ def onStateUpdateFromHandler(state)
46
+ return unless process_event(:state_from_handler, state: state) == true
47
+
48
+ logger.trace("Forwarding original update")
49
+ @callback.send_update(state)
50
+ end
51
+
52
+ # @!visibility private
53
+ def onCommandFromHandler(command)
54
+ return unless process_event(:command_from_handler, command: command) == true
55
+
56
+ logger.trace("Forwarding original command")
57
+ callback.send_command(command)
58
+ end
59
+
60
+ # @!visibility private
61
+ def onStateUpdateFromItem(state)
62
+ process_event(:state_from_item, state: state)
63
+ end
64
+
65
+ private
66
+
67
+ def process_event(event, **params)
68
+ logger.trace("Handling event #{event.inspect} in profile #{@uid} with param #{params.values.first.inspect}.")
69
+
70
+ params[:callback] = @callback
71
+ params[:context] = @context
72
+ params[:configuration] = @context.configuration.properties
73
+ params[:link] = @callback.link
74
+ params[:item] = @callback.link.item
75
+ params[:channel_uid] = @callback.link.linked_uid
76
+ params[:state] ||= nil
77
+ params[:command] ||= nil
78
+
79
+ kwargs = {}
80
+ @block.parameters.each do |(param_type, name)|
81
+ case param_type
82
+ when :keyreq, :key
83
+ kwargs[name] = params[name] if params.key?(name)
84
+ when :keyrest
85
+ kwargs = params
86
+ end
87
+ end
88
+
89
+ DSL::ThreadLocal.thread_local(**@thread_locals) do
90
+ @block.call(event, **kwargs)
91
+ rescue Exception => e
92
+ raise if defined?(::RSpec)
93
+
94
+ @block.binding.eval("self").logger.log_exception(e)
95
+ end
96
+ end
97
+ end
98
+ private_constant :Profile
99
+ # rubocop:enable Naming/MethodName
100
+
101
+ def initialize
102
+ @profiles = {}
103
+
104
+ @registration = OSGi.register_service(self)
105
+ ScriptHandling.script_unloaded { unregister }
106
+ end
107
+
108
+ #
109
+ # Unregister the ProfileFactory OSGi service
110
+ #
111
+ # @!visibility private
112
+ # @return [void]
113
+ #
114
+ def unregister
115
+ @registration.unregister
116
+ end
117
+
118
+ # @!visibility private
119
+ def register(uid, block)
120
+ @profiles[uid] = [DSL::ThreadLocal.persist, block]
121
+ end
122
+
123
+ def createProfile(type, callback, context) # rubocop:disable Naming/MethodName
124
+ @profiles[type].then { |(thread_locals, block)| Profile.new(callback, context, type, thread_locals, block) }
125
+ end
126
+
127
+ def getSupportedProfileTypeUIDs # rubocop:disable Naming/MethodName
128
+ @profiles.keys
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ # @interface
8
+ java_import org.openhab.core.common.registry.ManagedProvider
9
+
10
+ # @!visibility private
11
+ module ManagedProvider
12
+ # Maps actual element types to the symbol used in Thread.local[:openhab_providers]
13
+ TYPE_TO_PROVIDER_TYPE = {
14
+ org.openhab.core.items.Item.java_class => :items,
15
+ org.openhab.core.items.Metadata.java_class => :metadata,
16
+ org.openhab.core.automation.Rule.java_class => :rules,
17
+ org.openhab.core.thing.Thing.java_class => :things,
18
+ org.openhab.core.thing.link.ItemChannelLink.java_class => :links
19
+ }.freeze
20
+ private_constant :TYPE_TO_PROVIDER_TYPE
21
+
22
+ # @return [Symbol, nil]
23
+ def type
24
+ java_class.generic_ancestors.each do |klass|
25
+ next unless klass.respond_to?(:raw_type)
26
+ next unless klass.raw_type == org.openhab.core.common.registry.Provider.java_class
27
+
28
+ type_arg = klass.actual_type_arguments.first
29
+ next unless type_arg.is_a?(java.lang.Class)
30
+ next unless klass.actual_type_arguments.first.is_a?(java.lang.Class)
31
+
32
+ return TYPE_TO_PROVIDER_TYPE[type_arg]
33
+ end
34
+ nil
35
+ end
36
+ end
37
+
38
+ # @abstract
39
+ class Provider < org.openhab.core.common.registry.AbstractProvider
40
+ include org.openhab.core.common.registry.ManagedProvider
41
+ include Enumerable
42
+ include Singleton
43
+ public_class_method :new
44
+
45
+ # Known supported provider types
46
+ # @return [Array<Symbol>]
47
+ KNOWN_TYPES = %i[items metadata things links].freeze
48
+
49
+ class << self
50
+ #
51
+ # Determines the current provider that should be used to create elements belonging to this registry.
52
+ #
53
+ # @param [org.openhab.core.common.registry.Provider, Proc, :persistent, :transient, nil] preferred_provider
54
+ # An optional preferred provider to use. Can be one of several types:
55
+ # * An explicit instance of {org.openhab.core.common.registry.ManagedProvider ManagedProvider}
56
+ # * A Proc, which can calculate the preferred provider based on whatever conditions it wants,
57
+ # and then is further processed as this parameter.
58
+ # * `:persistent`, meaning the default {org.openhab.core.common.registry.ManagedProvider ManagedProvider}
59
+ # for this registry. Managed providers persist their objects to JSON, and will survive after the
60
+ # Ruby script is unloaded. This is where objects you configure with MainUI are stored. You should
61
+ # use this provider when you're creating something in response to a one-time event.
62
+ # * `:transient`, meaning a {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that
63
+ # will remove all of its contents when the Ruby script is unloaded. You should use this if you're
64
+ # generating objects dynamically, either based on some sort of other configuration, or simply
65
+ # hard coded and you're using Ruby as a more expressive way to define things than a `.items` or
66
+ # `.things` file. If you _don't_ use this provider for something such as metadata, then you
67
+ # may have issues such as metadata still showing up even though you're no longer creating items
68
+ # with it anymore.
69
+ # * `nil`, meaning to fall back to the current thread setting. See {OpenHAB::DSL.provider}.
70
+ # If there is no thread setting (or the thread setting was Proc that returned `nil`),
71
+ # it defaults to `:transient`.
72
+ # @return [org.openhab.core.common.registry.Provider]
73
+ #
74
+ def current(preferred_provider = nil, element = nil)
75
+ preferred_provider ||= Thread.current[:openhab_providers]&.[](type)
76
+ if preferred_provider.is_a?(Proc)
77
+ preferred_provider = if preferred_provider.arity.zero? || element.nil?
78
+ preferred_provider.call
79
+ else
80
+ preferred_provider.call(element)
81
+ end
82
+ end
83
+
84
+ case preferred_provider
85
+ when nil, :transient
86
+ instance
87
+ when :persistent
88
+ registry.managed_provider.get
89
+ when org.openhab.core.common.registry.ManagedProvider
90
+ preferred_provider
91
+ else
92
+ raise ArgumentError, "#{preferred_provider.inspect} is not a ManagedProvider"
93
+ end
94
+ end
95
+
96
+ # @abstract
97
+ # @!attribute [r] registry
98
+ #
99
+ # The registry that this provider provides elements for.
100
+ #
101
+ # @return [org.openhab.core.common.registry.Registry]
102
+ #
103
+ def registry
104
+ raise NotImplementedError
105
+ end
106
+
107
+ #
108
+ # Creates a new instance of a provider, registers it, sets it as the
109
+ # default for the thread, calls the block, and then unregisters it.
110
+ #
111
+ # @param [true, false] thread_provider Set this new provider as the default for the thread
112
+ # @yieldparam [Provider] provider The provider
113
+ # @return [Object] The result of the block
114
+ #
115
+ # @!visibility private
116
+ def new(thread_provider: true)
117
+ unless @singleton__instance__.nil? || block_given?
118
+ raise NoMethodError,
119
+ "private method `new' called for #{self}:Class"
120
+ end
121
+
122
+ r = provider = super()
123
+ if block_given?
124
+ if thread_provider
125
+ DSL.provider(provider) do
126
+ r = yield provider
127
+ end
128
+ else
129
+ r = yield provider
130
+ end
131
+ provider.unregister
132
+ end
133
+ r
134
+ end
135
+
136
+ # @!attribute [r] type
137
+ # @!visibility private
138
+ # @return [Symbol]
139
+ #
140
+ def type
141
+ name.split("::")[-2].downcase.to_sym
142
+ end
143
+ end
144
+
145
+ # @!visibility private
146
+ def each(&block)
147
+ @elements.each_value(&block)
148
+ end
149
+
150
+ # @return [String]
151
+ def inspect
152
+ "#<#{self.class.name}:#{object_id}>"
153
+ end
154
+
155
+ # @!visibility private
156
+ def add(element)
157
+ @elements.compute(element.uid) do |_k, old_element|
158
+ raise ArgumentError, "Element #{element.uid} already exists, and cannot be added again" if old_element
159
+
160
+ element
161
+ end
162
+ notify_listeners_about_added_element(element)
163
+ element
164
+ end
165
+
166
+ #
167
+ # Get an element from this provider
168
+ #
169
+ # @param [Object] key The proper key type for the elements in this provider.
170
+ # @return [Object]
171
+ #
172
+ def [](key)
173
+ @elements[key]
174
+ end
175
+ alias_method :get, :[]
176
+
177
+ #
178
+ # Get all elements in this provider
179
+ #
180
+ # @return [Array<Object>]
181
+ #
182
+ def all
183
+ @elements.values
184
+ end
185
+ alias_method :getAll, :all
186
+
187
+ #
188
+ # Remove an element from this provider
189
+ #
190
+ # @return [Object, nil] the removed element
191
+ #
192
+ # @!visibility private
193
+ #
194
+ def remove(key)
195
+ @elements.delete(key)&.tap do |element|
196
+ notify_listeners_about_removed_element(element)
197
+ end
198
+ end
199
+
200
+ # @return [Object, nil] the previous version of the element
201
+ # @!visibility private
202
+ #
203
+ def update(element)
204
+ old = nil
205
+ @elements.compute(element.uid) do |_k, old_element|
206
+ raise ArgumentError, "Element #{element.uid} does not exist to update" unless old_element
207
+
208
+ old = old_element
209
+ element
210
+ end
211
+ notify_listeners_about_updated_element(old, element)
212
+ old
213
+ end
214
+
215
+ # @!visibility private
216
+ def unregister
217
+ self.class.registry.remove_provider(self)
218
+ end
219
+
220
+ private
221
+
222
+ def initialize(unload_priority: nil)
223
+ super()
224
+ @elements = java.util.concurrent.ConcurrentHashMap.new
225
+ self.class.registry.add_provider(self)
226
+ ScriptHandling.script_unloaded(priority: unload_priority) { unregister }
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+ require "weakref"
5
+
6
+ require_relative "script_handling"
7
+
8
+ module OpenHAB
9
+ module Core
10
+ #
11
+ # Contains the infrastructure necessary to listen for events when objects are
12
+ # added/removed from their registry, and keep Proxy objects up-to-date with
13
+ # their underlying object.
14
+ #
15
+ # The including class must meet a few requirements:
16
+ # * Have an `EVENTS` constant that is an Array<String> of the events to
17
+ # listen for
18
+ # * The _last_ entry in the `EVENTS` array must be the "removed" event
19
+ # * It must have a sibling class called `Provider`, with a `.registry`
20
+ # method
21
+ # * It's parent module, downcased and with trailing "s" stripped, must be
22
+ # the method name to retrieve an object from one of the incoming events
23
+ #
24
+ # @!visibility private
25
+ #
26
+ module Proxy
27
+ #
28
+ # Registers and listens to openHAB bus events for objects getting
29
+ # added/updated/removed, and updates references from proxy objects
30
+ # to real objects.
31
+ #
32
+ # Proxies are tracked (via a WeakRef), and their underlying object is
33
+ # if it has changed.
34
+ #
35
+ class EventSubscriber
36
+ include Singleton
37
+ include org.openhab.core.events.EventSubscriber
38
+
39
+ def initialize
40
+ @proxies = java.util.concurrent.ConcurrentHashMap.new
41
+ @parent_module = Object.const_get(self.class.name.split("::")[0..-3].join("::"), false)
42
+ @object_type = @parent_module.name.split("::").last.downcase[0..-2].to_sym
43
+
44
+ @event_types = @parent_module::Proxy::EVENTS
45
+ @uid_method = @parent_module::Proxy::UID_METHOD
46
+ @registry = @parent_module::Provider.registry
47
+ @registration = OSGi.register_service(self, "event.topics": "openhab/*")
48
+ ScriptHandling.script_unloaded { @registration.unregister }
49
+ end
50
+
51
+ #
52
+ # @!attribute [r] subscribed_event_types
53
+ # @return [Set<String>]
54
+ #
55
+ def subscribed_event_types
56
+ @event_types.to_set
57
+ end
58
+
59
+ # @return [org.openhab.core.events.EventFilter, nil]
60
+ def event_filter
61
+ nil
62
+ end
63
+
64
+ #
65
+ # @param [Events::AbstractEvent] event
66
+ # @return [void]
67
+ #
68
+ def receive(event)
69
+ uid = event.__send__(@object_type).__send__(@uid_method)
70
+ object = @registry.get(uid) unless event.class.simple_name == @event_types.last
71
+
72
+ @proxies.compute_if_present(uid) do |_, proxy_ref|
73
+ proxy = resolve_ref(proxy_ref)
74
+ next nil unless proxy
75
+
76
+ proxy.__setobj__(object)
77
+ proxy_ref
78
+ end
79
+ end
80
+
81
+ #
82
+ # Get or create a Proxy for the given raw openHAB object.
83
+ #
84
+ def fetch(object)
85
+ result = nil
86
+
87
+ @proxies.compute(object.__send__(@uid_method)) do |_k, proxy_ref|
88
+ result = resolve_ref(proxy_ref)
89
+ proxy_ref = nil unless result
90
+ result ||= yield
91
+
92
+ proxy_ref || WeakRef.new(result)
93
+ end
94
+
95
+ result
96
+ end
97
+
98
+ private
99
+
100
+ def resolve_ref(proxy_ref)
101
+ proxy_ref.__getobj__ if proxy_ref&.weakref_alive?
102
+ rescue WeakRef::RefError
103
+ nil
104
+ end
105
+ end
106
+
107
+ # @!visibility private
108
+ module ClassMethods
109
+ # Intercepts calls to create new proxies, and returns the already
110
+ # existing (and tracked) proxy if it exists. Otherwise it does create
111
+ # a new instance of Proxy.
112
+ def new(object)
113
+ self::EventSubscriber.instance.fetch(object) { super }
114
+ end
115
+ end
116
+
117
+ # @!visibility private
118
+ def self.included(klass)
119
+ klass.singleton_class.prepend(ClassMethods)
120
+ # define a sub-class of EventSubscriber as a child class of the including class
121
+ klass.const_set(:EventSubscriber, Class.new(EventSubscriber))
122
+ end
123
+
124
+ # @!visibility private
125
+ def to_java
126
+ __getobj__
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ Registry = org.openhab.core.common.registry.AbstractRegistry
6
+
7
+ Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement, :providerToElements
8
+
9
+ # @abstract
10
+ #
11
+ # The base class for all registries in openHAB.
12
+ #
13
+ class Registry
14
+ #
15
+ # Determines which provider an element is associated with.
16
+ #
17
+ # @param [Object] key
18
+ # @return [org.openhab.core.common.registry.Provider]
19
+ #
20
+ def provider_for(key)
21
+ elementReadLock.lock
22
+ if key.is_a?(org.openhab.core.common.registry.Identifiable)
23
+ element = key
24
+ else
25
+ return nil unless (element = identifierToElement[key])
26
+ end
27
+
28
+ elementToProvider[element]
29
+ ensure
30
+ elementReadLock.unlock
31
+ end
32
+
33
+ # @!attribute [r] providers
34
+ # @return [Enumerable<org.openhab.core.common.registry.Provider>]
35
+ def providers
36
+ providerToElements.keys
37
+ end
38
+ end
39
+ end
40
+ end