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,325 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "numeric_type"
4
+ require_relative "type"
5
+
6
+ module OpenHAB
7
+ module Core
8
+ module Types
9
+ QuantityType = org.openhab.core.library.types.QuantityType
10
+
11
+ #
12
+ # {QuantityType} extends {DecimalType} to handle physical unit measurement.
13
+ #
14
+ # {QuantityType} is part of the [Units of Measurement](https://www.openhab.org/docs/concepts/units-of-measurement.html)
15
+ # framework in openHAB. It is represented as a decimal number with a unit.
16
+ # You can construct a {QuantityType} object by using the pipe operator with any Numeric.
17
+ #
18
+ # @see OpenHAB::DSL.unit unit: Implicit unit conversions
19
+ # @see OpenHAB::CoreExt::Ruby::QuantityTypeConversion Convert Numeric to QuantityType
20
+ #
21
+ # @example QuantityTypes can perform math operations between them.
22
+ # (50 | "°F") + (-25 | "°F") # => 25.0 °F
23
+ # (100 | "°F") / (2 | "°F") # => 50
24
+ # (50 | "°F") - (25 | "°F") # => 25 °F
25
+ # (50 | "°F") + (50 | "°F") # => 100 °F
26
+ #
27
+ # @example If the operand is a number, it will be unit-less, but the result of the operation will have a unit. This only works for multiplication and division.
28
+ # (50 | "°F") * 2 # => 100 °F
29
+ # (100 | "°F") / 2 # => 50 °F
30
+ #
31
+ # @example If the operand is a dimensioned NumberItem it will automatically be converted to a quantity for the operation.
32
+ # # NumberF = "2 °F"
33
+ # # NumberC = "2 °C"
34
+ # (50 | "°F") + NumberF.state # => 52.0 °F
35
+ # (50 | "°F") + NumberC.state # => 85.60 °F
36
+ #
37
+ # @example If the operand is a non-dimensioned NumberItem it can be used only in multiplication and division operations.
38
+ # # Number Dimensionless = 2
39
+ # (50 | "°F") * Dimensionless.state # => 100 °F
40
+ # (50 | "°F") / Dimensionless.state # => 25 °F
41
+ #
42
+ # @example Quantities can be compared, if they have comparable units.
43
+ # (50 | "°F") > (25 | "°F")
44
+ # (50 | "°F") > (525 | "°F")
45
+ # (50 | "°F") >= (50 | "°F")
46
+ # (50 | "°F") == (50 | "°F")
47
+ # (50 | "°F") < (25 | "°C")
48
+ #
49
+ # @example A Range can be used with QuantityType:
50
+ # ((0 | "°C")..(100 | "°C")).cover?(NumberC)
51
+ #
52
+ # @example A Range can also be used in a case statement for a dimensioned item:
53
+ # description = case NumberC.state
54
+ # when (-20 | "°C")...(18 | "°C") then "too cold"
55
+ # when (18 | "°C")...(25 | "°C") then "comfortable"
56
+ # when (25 | "°C")...(40 | "°C") then "too warm"
57
+ # else "out of range"
58
+ # end
59
+ #
60
+ # @example Dimensioned Number Items can be converted to quantities with other units using the | operator
61
+ # # NumberC = "23 °C"
62
+ #
63
+ # # Using a unit
64
+ # logger.info("In Fahrenheit #{NumberC.state | ImperialUnits::FAHRENHEIT }")
65
+ #
66
+ # # Using a string
67
+ # logger.info("In Fahrenheit #{NumberC.state | "°F"}")
68
+ #
69
+ # @example Dimensionless Number Items can be converted to quantities with units using the | operator
70
+ # # Dimensionless = 70
71
+ #
72
+ # # Using a unit
73
+ # logger.info("In Fahrenheit #{Dimensionless.state | ImperialUnits::FAHRENHEIT }")
74
+ #
75
+ # # Using a string
76
+ # logger.info("In Fahrenheit #{Dimensionless.state | "°F"}")
77
+ #
78
+ # @example Dimensioned Number Items automatically use their units and convert automatically for math operations
79
+ # # Number:Temperature NumberC = 23 °C
80
+ # # Number:Temperature NumberF = 70 °F
81
+ # NumberC.state - NumberF.state # => 1.88 °C
82
+ # NumberF.state + NumberC.state # => 143.40 °F
83
+ #
84
+ # @example Dimensionless Number Items can be used for multiplication and division.
85
+ # # Number Dimensionless = 2
86
+ # # Number:Temperature NumberF = 70 °F
87
+ # NumberF.state * Dimensionless.state # => 140.0 °F
88
+ # NumberF.state / Dimensionless.state # => 35.0 °F
89
+ # Dimensionless.state * NumberF.state # => 140.0 °F
90
+ # 2 * NumberF.state # => 140.0 °F
91
+ #
92
+ # @example Comparisons work on dimensioned number items with different, but comparable units.
93
+ # # Number:Temperature NumberC = 23 °C
94
+ # # Number:Temperature NumberF = 70 °F
95
+ # NumberC.state > NumberF.state # => true
96
+ #
97
+ # @example For certain unit types, such as temperature, all unit needs to be normalized to the comparator for all operations when combining comparison operators with dimensioned numbers.
98
+ # (NumberC.state | "°F") - (NumberF.state | "°F") < 4 | "°F"
99
+ #
100
+ class QuantityType
101
+ # @!parse include Command, State
102
+ include NumericType
103
+ include ComparableType
104
+
105
+ # @!parse
106
+ # #
107
+ # # Convert this {QuantityType} into another unit.
108
+ # #
109
+ # # @param [String, javax.measure.units.Unit] unit
110
+ # # @return [QuantityType]
111
+ # #
112
+ # # @example
113
+ # # NumberC.state | ImperialUnits::FAHRENHEIT
114
+ # #
115
+ # def to_unit(unit); end
116
+
117
+ alias_method :|, :to_unit
118
+
119
+ #
120
+ # Comparison
121
+ #
122
+ # Comparisons against Numeric and DecimalType are allowed only within a
123
+ # {OpenHAB::DSL.unit unit} block to avoid unit ambiguities.
124
+ # Comparisons against other types may be done if supported by that type's coercion.
125
+ #
126
+ # @param [QuantityType, DecimalType, Numeric, Object]
127
+ # other object to compare to
128
+ #
129
+ # @return [Integer, nil] -1, 0, +1 depending on whether `other` is
130
+ # less than, equal to, or greater than self
131
+ #
132
+ # `nil` is returned if the two values are incomparable.
133
+ #
134
+ def <=>(other)
135
+ logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
136
+ case other
137
+ when self.class
138
+ return unitize(other.unit).compare_to(other) if unit == Units::ONE
139
+ return compare_to(other.unitize(unit)) if other.unit == Units::ONE
140
+
141
+ return compare_to(other)
142
+ when Numeric, DecimalType
143
+ if (unit = OpenHAB::DSL.unit(dimension))
144
+ return compare_to(QuantityType.new(other, unit))
145
+ end
146
+
147
+ return nil # don't allow comparison with numeric outside a unit block
148
+ end
149
+
150
+ return nil unless other.respond_to?(:coerce)
151
+
152
+ other.coerce(self)&.then { |lhs, rhs| lhs <=> rhs }
153
+ end
154
+
155
+ #
156
+ # Type Coercion
157
+ #
158
+ # Coerce object to a {QuantityType}
159
+ #
160
+ # @param [Numeric] other object to coerce to a {QuantityType}
161
+ #
162
+ # @return [Array<(QuantityType, QuantityType)>, nil]
163
+ def coerce(other)
164
+ logger.trace("Coercing #{self} as a request from #{other.class}")
165
+ return unless other.respond_to?(:to_d)
166
+
167
+ [QuantityType.new(other.to_d.to_java, Units::ONE), self]
168
+ end
169
+
170
+ # arithmetic operators
171
+ alias_method :-@, :negate
172
+
173
+ {
174
+ add: :+,
175
+ subtract: :-
176
+ }.each do |java_op, ruby_op|
177
+ convert = "self.class.new(other, DSL.unit(dimension) || unit)"
178
+
179
+ class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
180
+ # def +(other)
181
+ # logger.trace("#{self} + #{other} (#{other.class})")
182
+ # if other.is_a?(QuantityType)
183
+ # add_quantity(other)
184
+ # elsif other.is_a?(DecimalType)
185
+ # other = other.to_big_decimal
186
+ # add_quantity(self.class.new(other, DSL.unit(dimension) || unit))
187
+ # elsif other.is_a?(java.math.BigDecimal)
188
+ # add_quantity(self.class.new(other, DSL.unit(dimension) || unit))
189
+ # elsif other.respond_to?(:to_d)
190
+ # other = other.to_d.to_java
191
+ # add_quantity(self.class.new(other, DSL.unit(dimension) || unit))
192
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
193
+ # lhs + rhs
194
+ # else
195
+ # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
196
+ # end
197
+ # end
198
+ <<~RUBY, __FILE__, __LINE__ + 1
199
+ def #{ruby_op}(other)
200
+ logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
201
+ if other.is_a?(QuantityType)
202
+ #{java_op}_quantity(other)
203
+ elsif other.is_a?(DecimalType)
204
+ other = other.to_big_decimal
205
+ #{java_op}_quantity(#{convert})
206
+ elsif other.is_a?(java.math.BigDecimal)
207
+ #{java_op}_quantity(#{convert})
208
+ elsif other.respond_to?(:to_d)
209
+ other = other.to_d.to_java
210
+ #{java_op}_quantity(#{convert})
211
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
212
+ lhs #{ruby_op} rhs
213
+ else
214
+ raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
215
+ end
216
+ end
217
+ RUBY
218
+ )
219
+ end
220
+
221
+ {
222
+ multiply: :*,
223
+ divide: :/
224
+ }.each do |java_op, ruby_op|
225
+ class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
226
+ # def *(other)
227
+ # logger.trace("#{self} * #{other} (#{other.class})")
228
+ # if other.is_a?(QuantityType)
229
+ # multiply_quantity(other)
230
+ # elsif other.is_a?(DecimalType)
231
+ # multiply(other.to_big_decimal)
232
+ # elsif other.is_a?(java.math.BigDecimal)
233
+ # multiply(other)
234
+ # elsif other.respond_to?(:to_d)
235
+ # multiply(other.to_d.to_java)
236
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
237
+ # lhs * rhs
238
+ # else
239
+ # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
240
+ # end
241
+ # end
242
+ <<~RUBY, __FILE__, __LINE__ + 1
243
+ def #{ruby_op}(other)
244
+ logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
245
+ if other.is_a?(QuantityType)
246
+ #{java_op}_quantity(other)
247
+ elsif other.is_a?(DecimalType)
248
+ #{java_op}(other.to_big_decimal)
249
+ elsif other.is_a?(java.math.BigDecimal)
250
+ #{java_op}(other)
251
+ elsif other.respond_to?(:to_d)
252
+ #{java_op}(other.to_d.to_java)
253
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
254
+ lhs #{ruby_op} rhs
255
+ else
256
+ raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
257
+ end
258
+ end
259
+ RUBY
260
+ )
261
+ end
262
+
263
+ # if it's a dimensionless quantity, change the unit to match other_unit
264
+ # @!visibility private
265
+ def unitize(other_unit = unit)
266
+ # prefer converting to the thread-specified unit if there is one
267
+ other_unit = DSL.unit(dimension) || other_unit
268
+ logger.trace("Converting #{self} to #{other_unit}")
269
+
270
+ case unit
271
+ when Units::ONE
272
+ QuantityType.new(to_big_decimal, other_unit)
273
+ when other_unit
274
+ self
275
+ else
276
+ to_unit(other_unit)
277
+ end
278
+ end
279
+
280
+ # if unit is {org.openhab.core.library.unit.Units.ONE}, return a plain
281
+ # Java BigDecimal
282
+ # @!visibility private
283
+ def deunitize
284
+ return to_big_decimal if unit == Units::ONE
285
+
286
+ self
287
+ end
288
+
289
+ private
290
+
291
+ # do addition directly against a QuantityType while ensuring we unitize
292
+ # both sides
293
+ def add_quantity(other)
294
+ unitize(other.unit).add(other.unitize(unit))
295
+ end
296
+
297
+ # do subtraction directly against a QuantityType while ensuring we
298
+ # unitize both sides
299
+ def subtract_quantity(other)
300
+ unitize(other.unit).subtract(other.unitize(unit))
301
+ end
302
+
303
+ # do multiplication directly against a QuantityType while ensuring
304
+ # we deunitize both sides, and also invert the operation if one side
305
+ # isn't actually a unit
306
+ def multiply_quantity(other)
307
+ lhs = deunitize
308
+ rhs = other.deunitize
309
+ # reverse the arguments if it's multiplication and the LHS isn't a QuantityType
310
+ lhs, rhs = rhs, lhs if lhs.is_a?(java.math.BigDecimal)
311
+ # what a waste... using a QuantityType to multiply two dimensionless quantities
312
+ # have to make sure lhs is still a QuantityType in order to return a new
313
+ # QuantityType that's still dimensionless
314
+ lhs = other if lhs.is_a?(java.math.BigDecimal)
315
+
316
+ lhs.multiply(rhs)
317
+ end
318
+
319
+ alias_method :divide_quantity, :divide
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ # @!parse QuantityType = OpenHAB::Core::Types::QuantityType
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "type"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Types
8
+ RawType = org.openhab.core.library.types.RawType
9
+
10
+ #
11
+ # This type can be used for all binary data such as images, documents, sounds etc.
12
+ #
13
+ class RawType # rubocop:disable Lint/EmptyClass
14
+ # @!parse include State
15
+
16
+ # @!method mime_type
17
+ # @return [String]
18
+
19
+ # @!method bytes
20
+ # @return [String]
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # @!parse RawType = OpenHAB::Core::Types::RawType
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "type"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Types
8
+ RefreshType = org.openhab.core.types.RefreshType
9
+
10
+ # Implements the {REFRESH} command.
11
+ class RefreshType # rubocop:disable Lint/EmptyClass
12
+ # @!parse include Command
13
+
14
+ # @!constant REFRESH
15
+ # Refresh Command
16
+
17
+ # @!method refresh?
18
+ # Check if `self == REFRESH`
19
+ # @return [true,false]
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # @!parse
26
+ # RefreshType = OpenHAB::Core::Types::RefreshType
27
+ # REFRESH = OpenHAB::Core::Types::RefreshType::REFRESH
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "type"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Types
8
+ RewindFastforwardType = org.openhab.core.library.types.RewindFastforwardType
9
+
10
+ # Implements the {REWIND} and {FASTFORWARD} commands and states.
11
+ class RewindFastforwardType # rubocop:disable Lint/EmptyClass
12
+ # @!parse include Command, State
13
+
14
+ # @!constant REWIND
15
+ # Rewind Command/Rewinding State
16
+ # @!constant FASTFORWARD
17
+ # Fast Forward Command/Fast Forwarding State
18
+
19
+ # @!method rewinding?
20
+ # Check if `self == REWIND`
21
+ # @return [true,false]
22
+
23
+ # @!parse alias rewind? rewinding?
24
+
25
+ # @!method fast_forwarding?
26
+ # Check if `self == FASTFORWARD`
27
+ # @return [true,false]
28
+
29
+ # @!parse alias fast_forward? fast_forwarding?
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # @!parse
36
+ # RewindFastforwardType = OpenHAB::Core::Types::RewindFastforwardType
37
+ # REWIND = OpenHAB::Core::Types::RewindFastforwardType::REWIND
38
+ # FASTFORWARD = OpenHAB::Core::Types::RewindFastforwardType::FASTFORWARD
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "type"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Types
8
+ StopMoveType = org.openhab.core.library.types.StopMoveType
9
+
10
+ # Implements the {STOP} and {MOVE} commands.
11
+ class StopMoveType # rubocop:disable Lint/EmptyClass
12
+ # @!parse include Command
13
+
14
+ # @!constant STOP
15
+ # Stop Command
16
+ # @!constant MOVE
17
+ # Move Command
18
+
19
+ # @!method stop?
20
+ # Check if `self == STOP`
21
+ # @return [true,false]
22
+
23
+ # @!method move?
24
+ # Check if `self == MOVE`
25
+ # @return [true,false]
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # @!parse
32
+ # StopMoveType = OpenHAB::Core::Types::StopMoveType
33
+ # STOP = OpenHAB::Core::Types::StopMoveType::STOP
34
+ # MOVE = OpenHAB::Core::Types::StopMoveType::MOVE
@@ -1,20 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
- require_relative 'comparable_type'
5
+ require_relative "comparable_type"
6
+ require_relative "type"
6
7
 
7
8
  module OpenHAB
8
- module DSL
9
+ module Core
9
10
  module Types
10
11
  StringType = org.openhab.core.library.types.StringType
11
12
 
12
- #
13
- # Add methods to core OpenHAB StringType to make it behave as a Ruby
14
- # String object
15
- #
13
+ # {StringType} represents a String as a {Type} and a {Command}.
16
14
  class StringType
17
- # @!parse include Type
15
+ # @!parse include Command, State
18
16
 
19
17
  extend Forwardable
20
18
  include Comparable
@@ -23,7 +21,7 @@ module OpenHAB
23
21
  #
24
22
  # Check equality without type conversion
25
23
  #
26
- # @return [Boolean] if the same value is represented, without type
24
+ # @return [true,false] if the same value is represented, without type
27
25
  # conversion
28
26
  def eql?(other)
29
27
  return false unless other.instance_of?(self.class)
@@ -34,22 +32,17 @@ module OpenHAB
34
32
  #
35
33
  # Comparison
36
34
  #
37
- # @param [StringType, Items::StringItem, String]
35
+ # @param [StringType, String]
38
36
  # other object to compare to
39
37
  #
40
- # @return [Integer, nil] -1, 0, +1 depending on whether +other+ is
38
+ # @return [Integer, nil] -1, 0, +1 depending on whether `other` is
41
39
  # less than, equal to, or greater than self
42
40
  #
43
- # nil is returned if the two values are incomparable
41
+ # `nil` is returned if the two values are incomparable.
44
42
  #
45
- def <=>(other) # rubocop:disable Metrics
43
+ def <=>(other)
46
44
  logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
47
- if other.is_a?(Items::StringItem) ||
48
- (other.is_a?(Items::GroupItem) && other.base_item.is_a?(StringItem))
49
- return nil unless other.state?
50
-
51
- self <=> other.state
52
- elsif other.respond_to?(:to_str)
45
+ if other.respond_to?(:to_str)
53
46
  to_str <=> other.to_str
54
47
  elsif other.respond_to?(:coerce)
55
48
  return nil unless (lhs, rhs = other.coerce(self))
@@ -63,20 +56,14 @@ module OpenHAB
63
56
  #
64
57
  # Coerce object to a StringType
65
58
  #
66
- # @param [Items::StringItem, String] other object to coerce to a
59
+ # @param [String] other object to coerce to a
67
60
  # DateTimeType
68
61
  #
69
- # @return [[StringType, StringType]]
62
+ # @return [[StringType, StringType], nil]
70
63
  #
71
64
  def coerce(other)
72
65
  logger.trace("Coercing #{self} as a request from #{other.class}")
73
- if other.is_a?(Items::StringItem)
74
- return unless other.state?
75
-
76
- [other.state, self]
77
- elsif other.respond_to?(:to_str)
78
- [String.new(other.to_str), self]
79
- end
66
+ return [other.to_str, self] if other.respond_to?(:to_str)
80
67
  end
81
68
 
82
69
  # any method that exists on String gets forwarded to to_s
@@ -85,3 +72,5 @@ module OpenHAB
85
72
  end
86
73
  end
87
74
  end
75
+
76
+ # @!parse StringType = OpenHAB::Core::Types::StringType
@@ -1,13 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenHAB
4
- module DSL
4
+ module Core
5
5
  module Types
6
- java_import org.openhab.core.types.Type
6
+ # @interface
7
+ Type = org.openhab.core.types.Type
7
8
 
8
- #
9
- # Add basic type conversion and comparison to all core OpenHAB types
10
- #
9
+ # @interface
10
+ Command = org.openhab.core.types.Command
11
+
12
+ # @interface
13
+ State = org.openhab.core.types.State
14
+
15
+ # This is a parent interface for all {State}s and {Command}s. It
16
+ # was introduced as many states can be commands at the same time and vice
17
+ # versa. E.g. a light can have the state {ON} or {OFF} and one can also
18
+ # send {ON} and {OFF} as commands to the device. This duality is captured
19
+ # by this marker interface and allows implementing classes to be both
20
+ # state and command at the same time.
11
21
  module Type
12
22
  # can't alias because to_s doesn't exist on Type
13
23
  # @!visibility private
@@ -15,25 +25,10 @@ module OpenHAB
15
25
  to_s
16
26
  end
17
27
 
18
- #
19
- # Type Coercion
20
- #
21
- # Coerce object to the same Type
22
- #
23
- # @param [Type] other object to coerce to the same
24
- # Type as this one
25
- #
26
- # @return [[Type, Type]]
27
- #
28
- def coerce(other)
29
- logger.trace("Coercing #{self} (#{self.class}) as a request from #{other.class}")
30
- return [other.as(self.class), self] if other.is_a?(Type) && other.respond_to?(:as)
31
- end
32
-
33
28
  #
34
29
  # Check equality without type conversion
35
30
  #
36
- # @return [Boolean] if the same value is represented, without type
31
+ # @return [true,false] if the same value is represented, without type
37
32
  # conversion
38
33
  def eql?(other)
39
34
  return false unless other.instance_of?(self.class)
@@ -41,27 +36,13 @@ module OpenHAB
41
36
  equals(other)
42
37
  end
43
38
 
44
- #
45
- # Case equality
46
- #
47
- # @return [Boolean] if the values are of the same Type
48
- # or item state of the same type
49
- #
50
- def ===(other)
51
- logger.trace { "Type (#{self.class}) #{self} === #{other} (#{other.class})" }
52
- other = other.state if other.respond_to?(:state) && !other.is_a?(OpenHAB::DSL::GenericItemObject)
53
- return false unless instance_of?(other.class)
54
-
55
- eql?(other)
56
- end
57
-
58
39
  #
59
40
  # Check equality, including type conversion
60
41
  #
61
- # @return [Boolean] if the same value is represented, including
42
+ # @return [true,false] if the same value is represented, including
62
43
  # type conversions
63
44
  #
64
- def ==(other) # rubocop:disable Metrics
45
+ def ==(other)
65
46
  logger.trace { "(#{self.class}) #{self} == #{other} (#{other.class})" }
66
47
  return true if equal?(other)
67
48
 
@@ -69,9 +50,6 @@ module OpenHAB
69
50
  # (RefreshType isn't really coercible)
70
51
  return equals(other) if other.instance_of?(self.class) || is_a?(RefreshType) || other.is_a?(RefreshType)
71
52
 
72
- # i.e. ON == DimmerItem (also case statements)
73
- return self == other.raw_state if other.is_a?(Items::GenericItem)
74
-
75
53
  if other.respond_to?(:coerce)
76
54
  begin
77
55
  return false unless (lhs, rhs = other.coerce(self))
@@ -89,7 +67,31 @@ module OpenHAB
89
67
 
90
68
  super
91
69
  end
70
+
71
+ # @!visibility private
72
+ #
73
+ # some openHAB Types don't implement as; do it for them
74
+ #
75
+ def as(klass)
76
+ self if klass == self.class
77
+ end
92
78
  end
79
+
80
+ #
81
+ # @!parse
82
+ # # This is a marker interface for all command types.
83
+ # module Command
84
+ # include Type
85
+ # end
86
+ #
87
+ # # This is a marker interface for all state types.
88
+ # module State
89
+ # include Type
90
+ # end
93
91
  end
94
92
  end
95
93
  end
94
+
95
+ # @!parse
96
+ # Command = OpenHAB::Core::Types::Command
97
+ # State = OpenHAB::Core::Types::State