openhab-jrubyscripting 5.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/lib/openhab/core/actions.rb +163 -0
  3. data/lib/openhab/core/entity_lookup.rb +144 -0
  4. data/lib/openhab/core/events/abstract_event.rb +17 -0
  5. data/lib/openhab/core/events/item_channel_link.rb +36 -0
  6. data/lib/openhab/core/events/item_command_event.rb +78 -0
  7. data/lib/openhab/core/events/item_event.rb +22 -0
  8. data/lib/openhab/core/events/item_state_changed_event.rb +52 -0
  9. data/lib/openhab/core/events/item_state_event.rb +51 -0
  10. data/lib/openhab/core/events/thing.rb +29 -0
  11. data/lib/openhab/core/events/thing_status_info_event.rb +53 -0
  12. data/lib/openhab/core/events.rb +10 -0
  13. data/lib/openhab/core/items/accepted_data_types.rb +29 -0
  14. data/lib/openhab/core/items/color_item.rb +52 -0
  15. data/lib/openhab/core/items/contact_item.rb +52 -0
  16. data/lib/openhab/core/items/date_time_item.rb +58 -0
  17. data/lib/openhab/core/items/dimmer_item.rb +148 -0
  18. data/lib/openhab/core/items/generic_item.rb +344 -0
  19. data/lib/openhab/core/items/group_item.rb +174 -0
  20. data/lib/openhab/core/items/image_item.rb +109 -0
  21. data/lib/openhab/core/items/location_item.rb +34 -0
  22. data/lib/openhab/core/items/metadata/hash.rb +390 -0
  23. data/lib/openhab/core/items/metadata/namespace_hash.rb +469 -0
  24. data/lib/openhab/core/items/metadata.rb +11 -0
  25. data/lib/openhab/core/items/number_item.rb +62 -0
  26. data/lib/openhab/core/items/numeric_item.rb +22 -0
  27. data/lib/openhab/core/items/persistence.rb +327 -0
  28. data/lib/openhab/core/items/player_item.rb +66 -0
  29. data/lib/openhab/core/items/proxy.rb +59 -0
  30. data/lib/openhab/core/items/registry.rb +66 -0
  31. data/lib/openhab/core/items/rollershutter_item.rb +68 -0
  32. data/lib/openhab/core/items/semantics/enumerable.rb +152 -0
  33. data/lib/openhab/core/items/semantics.rb +476 -0
  34. data/lib/openhab/core/items/state_storage.rb +53 -0
  35. data/lib/openhab/core/items/string_item.rb +28 -0
  36. data/lib/openhab/core/items/switch_item.rb +78 -0
  37. data/lib/openhab/core/items.rb +114 -0
  38. data/lib/openhab/core/lazy_array.rb +52 -0
  39. data/lib/openhab/core/profile_factory.rb +118 -0
  40. data/lib/openhab/core/script_handling.rb +55 -0
  41. data/lib/openhab/core/things/channel.rb +48 -0
  42. data/lib/openhab/core/things/channel_uid.rb +51 -0
  43. data/lib/openhab/core/things/item_channel_link.rb +33 -0
  44. data/lib/openhab/core/things/profile_callback.rb +52 -0
  45. data/lib/openhab/core/things/proxy.rb +69 -0
  46. data/lib/openhab/core/things/registry.rb +46 -0
  47. data/lib/openhab/core/things/thing.rb +194 -0
  48. data/lib/openhab/core/things.rb +22 -0
  49. data/lib/openhab/core/timer.rb +128 -0
  50. data/lib/openhab/core/types/comparable_type.rb +23 -0
  51. data/lib/openhab/core/types/date_time_type.rb +259 -0
  52. data/lib/openhab/core/types/decimal_type.rb +192 -0
  53. data/lib/openhab/core/types/hsb_type.rb +183 -0
  54. data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
  55. data/lib/openhab/core/types/next_previous_type.rb +34 -0
  56. data/lib/openhab/core/types/numeric_type.rb +52 -0
  57. data/lib/openhab/core/types/on_off_type.rb +46 -0
  58. data/lib/openhab/core/types/open_closed_type.rb +41 -0
  59. data/lib/openhab/core/types/percent_type.rb +95 -0
  60. data/lib/openhab/core/types/play_pause_type.rb +38 -0
  61. data/lib/openhab/core/types/point_type.rb +117 -0
  62. data/lib/openhab/core/types/quantity_type.rb +327 -0
  63. data/lib/openhab/core/types/raw_type.rb +26 -0
  64. data/lib/openhab/core/types/refresh_type.rb +27 -0
  65. data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
  66. data/lib/openhab/core/types/stop_move_type.rb +34 -0
  67. data/lib/openhab/core/types/string_type.rb +76 -0
  68. data/lib/openhab/core/types/type.rb +117 -0
  69. data/lib/openhab/core/types/un_def_type.rb +38 -0
  70. data/lib/openhab/core/types/up_down_type.rb +50 -0
  71. data/lib/openhab/core/types.rb +69 -0
  72. data/lib/openhab/core/uid.rb +36 -0
  73. data/lib/openhab/core.rb +85 -0
  74. data/lib/openhab/core_ext/java/duration.rb +115 -0
  75. data/lib/openhab/core_ext/java/local_date.rb +93 -0
  76. data/lib/openhab/core_ext/java/local_time.rb +106 -0
  77. data/lib/openhab/core_ext/java/month.rb +59 -0
  78. data/lib/openhab/core_ext/java/month_day.rb +105 -0
  79. data/lib/openhab/core_ext/java/period.rb +103 -0
  80. data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
  81. data/lib/openhab/core_ext/java/time.rb +58 -0
  82. data/lib/openhab/core_ext/java/unit.rb +15 -0
  83. data/lib/openhab/core_ext/java/zoned_date_time.rb +116 -0
  84. data/lib/openhab/core_ext/ruby/array.rb +21 -0
  85. data/lib/openhab/core_ext/ruby/class.rb +15 -0
  86. data/lib/openhab/core_ext/ruby/date.rb +89 -0
  87. data/lib/openhab/core_ext/ruby/numeric.rb +190 -0
  88. data/lib/openhab/core_ext/ruby/range.rb +70 -0
  89. data/lib/openhab/core_ext/ruby/time.rb +104 -0
  90. data/lib/openhab/core_ext.rb +18 -0
  91. data/lib/openhab/dsl/events/watch_event.rb +18 -0
  92. data/lib/openhab/dsl/events.rb +9 -0
  93. data/lib/openhab/dsl/gems.rb +3 -0
  94. data/lib/openhab/dsl/items/builder.rb +618 -0
  95. data/lib/openhab/dsl/items/ensure.rb +93 -0
  96. data/lib/openhab/dsl/items/timed_command.rb +236 -0
  97. data/lib/openhab/dsl/rules/automation_rule.rb +308 -0
  98. data/lib/openhab/dsl/rules/builder.rb +1373 -0
  99. data/lib/openhab/dsl/rules/guard.rb +115 -0
  100. data/lib/openhab/dsl/rules/name_inference.rb +160 -0
  101. data/lib/openhab/dsl/rules/property.rb +76 -0
  102. data/lib/openhab/dsl/rules/rule_triggers.rb +96 -0
  103. data/lib/openhab/dsl/rules/terse.rb +63 -0
  104. data/lib/openhab/dsl/rules/triggers/changed.rb +169 -0
  105. data/lib/openhab/dsl/rules/triggers/channel.rb +57 -0
  106. data/lib/openhab/dsl/rules/triggers/command.rb +107 -0
  107. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +161 -0
  108. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +164 -0
  109. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +195 -0
  110. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +127 -0
  111. data/lib/openhab/dsl/rules/triggers/trigger.rb +56 -0
  112. data/lib/openhab/dsl/rules/triggers/updated.rb +130 -0
  113. data/lib/openhab/dsl/rules/triggers/watch/watch.rb +55 -0
  114. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +155 -0
  115. data/lib/openhab/dsl/rules/triggers.rb +12 -0
  116. data/lib/openhab/dsl/rules.rb +29 -0
  117. data/lib/openhab/dsl/script_handling.rb +55 -0
  118. data/lib/openhab/dsl/things/builder.rb +263 -0
  119. data/lib/openhab/dsl/thread_local.rb +48 -0
  120. data/lib/openhab/dsl/timer_manager.rb +191 -0
  121. data/lib/openhab/dsl/version.rb +9 -0
  122. data/lib/openhab/dsl.rb +686 -0
  123. data/lib/openhab/log.rb +348 -0
  124. data/lib/openhab/osgi.rb +70 -0
  125. data/lib/openhab/rspec/configuration.rb +56 -0
  126. data/lib/openhab/rspec/example_group.rb +90 -0
  127. data/lib/openhab/rspec/helpers.rb +439 -0
  128. data/lib/openhab/rspec/hooks.rb +93 -0
  129. data/lib/openhab/rspec/jruby.rb +46 -0
  130. data/lib/openhab/rspec/karaf.rb +811 -0
  131. data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
  132. data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
  133. data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
  134. data/lib/openhab/rspec/mocks/metadata_provider.rb +75 -0
  135. data/lib/openhab/rspec/mocks/persistence_service.rb +140 -0
  136. data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
  137. data/lib/openhab/rspec/mocks/synchronous_executor.rb +56 -0
  138. data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
  139. data/lib/openhab/rspec/mocks/timer.rb +95 -0
  140. data/lib/openhab/rspec/openhab/core/actions.rb +26 -0
  141. data/lib/openhab/rspec/openhab/core/items/proxy.rb +27 -0
  142. data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
  143. data/lib/openhab/rspec/shell.rb +31 -0
  144. data/lib/openhab/rspec/suspend_rules.rb +60 -0
  145. data/lib/openhab/rspec.rb +17 -0
  146. data/lib/openhab/yard/cli/stats.rb +23 -0
  147. data/lib/openhab/yard/code_objects/group_object.rb +17 -0
  148. data/lib/openhab/yard/code_objects/java/base.rb +31 -0
  149. data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
  150. data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
  151. data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
  152. data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
  153. data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
  154. data/lib/openhab/yard/handlers/jruby/base.rb +49 -0
  155. data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
  156. data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
  157. data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +27 -0
  158. data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
  159. data/lib/openhab/yard/html_helper.rb +44 -0
  160. data/lib/openhab/yard/tags/constant_directive.rb +20 -0
  161. data/lib/openhab/yard/tags/group_directive.rb +24 -0
  162. data/lib/openhab/yard/tags/library.rb +3 -0
  163. data/lib/openhab/yard.rb +32 -0
  164. metadata +504 -0
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "dimmer_item"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Items
8
+ java_import org.openhab.core.library.items.ColorItem
9
+
10
+ #
11
+ # {ColorItem} represents a color values, e.g. for LED lights.
12
+ #
13
+ # Note that it inherits from {DimmerItem}, so you can call {#on}, {#off},
14
+ # {#on?}, {#off?}, etc. on it. Its state type is an {HSBType},
15
+ # which is stored as Hue, Saturation, and Brightness, but has easy
16
+ # helpers for working with RGB values of various forms.
17
+ #
18
+ # @example Sending commands
19
+ # HueBulb << "#ff0000" # send 'red' as a command
20
+ # HueBulb.on
21
+ # HueBulb.dim
22
+ #
23
+ # @example Inspect state
24
+ # HueBulb.on? # => true
25
+ # HueBulb.state.red # => 100%
26
+ # HueBulb.state.hue # => 0 °
27
+ # HueBulb.state.brightness # => 100%
28
+ # HueBulb.state.to_rgb # => [100%, 0%, 0%]
29
+ # HueBulb.state.rgb # => 16711680
30
+ # HueBulb.state.to_hex # => "0xff0000"
31
+ # HueBulb.state.on? # => true
32
+ # HueBulb.state.red.to_byte # => 255
33
+ # HueBulb.state.blue.to_byte # => 0
34
+ #
35
+ # @!attribute [r] state
36
+ # @return [HSBType, nil]
37
+ #
38
+ class ColorItem < DimmerItem
39
+ # Make sure to do the String => HSBType conversion in Ruby,
40
+ # where we add support for hex
41
+ # @!visibility private
42
+ def format_type(type)
43
+ return Types::HSBType.new(type) if type.respond_to?(:to_str)
44
+
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # @!parse ColorItem = OpenHAB::Core::Items::ColorItem
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "generic_item"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Items
8
+ java_import org.openhab.core.library.items.ContactItem
9
+
10
+ #
11
+ # A {ContactItem} can be used for sensors that return an "open" or
12
+ # "closed" as a state.
13
+ #
14
+ # This is useful for doors, windows, etc.
15
+ #
16
+ # @!attribute [r] state
17
+ # @return [OpenClosedType, nil]
18
+ #
19
+ # @example
20
+ # rule 'Log state of all doors on system startup' do
21
+ # on_start
22
+ # run do
23
+ # Doors.each do |door|
24
+ # case door.state
25
+ # when OPEN then logger.info("#{door.name} is Open")
26
+ # when CLOSED then logger.info("#{door.name} is Open")
27
+ # else logger.info("#{door.name} is not initialized")
28
+ # end
29
+ # end
30
+ # end
31
+ # end
32
+ #
33
+ class ContactItem < GenericItem
34
+ # @!method open?
35
+ # Check if the item state == {OPEN}
36
+ # @return [true,false]
37
+ #
38
+ # @example Log open contacts
39
+ # Contacts.select(&:open?).each { |contact| logger.info("Contact #{contact.name} is open")}
40
+
41
+ # @!method closed?
42
+ # Check if the item state == {CLOSED}
43
+ # @return [true,false]
44
+ #
45
+ # @example Log closed contacts
46
+ # Contacts.select(&:closed?).each { |contact| logger.info("Contact #{contact.name} is closed")}
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # @!parse ContactItem = OpenHAB::Core::Items::ContactItem
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "generic_item"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Items
8
+ java_import org.openhab.core.library.items.DateTimeItem
9
+
10
+ #
11
+ # A DateTimeItem stores a timestamp including a valid time zone.
12
+ #
13
+ # @!attribute [r] state
14
+ # @return [DateTimeType, nil]
15
+ #
16
+ # @example DateTime items can be updated and commanded with Ruby Time objects or Java ZonedDateTime objects
17
+ # Example_DateTimeItem << Time.now
18
+ # Example_DateTimeItem << ZonedDateTime.now
19
+ #
20
+ # @example Math operations (+ and -) are available to make calculations with time in a few different ways
21
+ # Example_DateTimeItem.state + 600 # Number of seconds
22
+ # Example_DateTimeItem.state - '01:15' # Subtracts 1h 15 min
23
+ # Example_DateTimeItem.state + 2.hours # Use the helper library's duration methods
24
+ #
25
+ # Example_DateTimeItem.state - Example_DateTimeItem2.state # Calculate the time difference, in seconds
26
+ # Example_DateTimeItem.state - '2021-01-01 15:40' # Calculates time difference
27
+ #
28
+ # @example Comparisons between different time objects can be performed
29
+ # Example_DateTimeItem.state == Example_DateTimeItem2.state # Equality, works across time zones
30
+ # Example_DateTimeItem.state > Date.parse('2021-01-31') # After midnight jan 31st 2021
31
+ # Example_DateTimeItem.state <= Time.now # Before or equal to now
32
+ # Example_DateTimeItem.state < LocalTime::NOON # Before noon
33
+ #
34
+ # @example LocalTime ranges created also work
35
+ # case Example_DateTimeItem.state
36
+ # when LocalTime.parse('00:00')...LocalTime.parse('08:00')
37
+ # logger.info('Example_DateTimeItem is between 00:00..08:00')
38
+ # when LocalTime.parse('08:00')...LocalTime.parse('16:00')
39
+ # logger.info('Example_DateTimeItem is between 08:00..16:00')
40
+ # when LocalTime.parse('16:00')..LocalTime.parse'23:59')
41
+ # logger.info('Example_DateTimeItem is between 16:00...23:59')
42
+ # end
43
+ #
44
+ class DateTimeItem < GenericItem
45
+ # Time types need formatted as ISO8601
46
+ # @!visibility private
47
+ def format_type(command)
48
+ return Types::DateTimeType.new(command) if command.is_a?(java.time.ZonedDateTime)
49
+
50
+ command = command.iso8601 if command.respond_to?(:iso8601)
51
+ super
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # @!parse DateTimeItem = OpenHAB::Core::Items::DateTimeItem
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "numeric_item"
4
+ require_relative "switch_item"
5
+
6
+ module OpenHAB
7
+ module Core
8
+ module Items
9
+ java_import org.openhab.core.library.items.DimmerItem
10
+
11
+ #
12
+ # A DimmerItem can be used as a switch (ON/OFF), but it also accepts
13
+ # percent values to reflect the dimmed state.
14
+ #
15
+ # @!attribute [r] state
16
+ # @return [PercentType, nil]
17
+ #
18
+ # @example
19
+ # DimmerOne << DimmerOne.state - 5
20
+ # DimmerOne << 100 - DimmerOne.state
21
+ #
22
+ # @example Turn on all dimmers in group
23
+ # Dimmers.members.each(&:on)
24
+ #
25
+ # @example Turn off all dimmers in group
26
+ # Dimmers.members.each(&:off)
27
+ #
28
+ # @example Turn on switches that are off
29
+ # Dimmers.select(&:off?).each(&:on)
30
+ #
31
+ # @example Turn off switches that are on
32
+ # Dimmers.select(&:on?).each(&:off)
33
+ #
34
+ # @example Dimmers can be selected in an enumerable with grep.
35
+ # items.grep(DimmerItem)
36
+ # .each { |dimmer| logger.info("#{dimmer.name} is a Dimmer") }
37
+ #
38
+ # @example Dimmers can also be used in case statements with ranges.
39
+ # items.grep(DimmerItem)
40
+ # .each do |dimmer|
41
+ # case dimmer.state
42
+ # when (0..50)
43
+ # logger.info("#{dimmer.name} is less than 50%")
44
+ # when (51..100)
45
+ # logger.info("#{dimmer.name} is greater than 50%")
46
+ # end
47
+ # end
48
+ #
49
+ # @example
50
+ # rule 'Dim a switch on system startup over 100 seconds' do
51
+ # on_start
52
+ # 100.times do
53
+ # run { DimmerSwitch.dim }
54
+ # delay 1.second
55
+ # end
56
+ # end
57
+ #
58
+ # @example
59
+ # rule 'Dim a switch on system startup by 5, pausing every second' do
60
+ # on_start
61
+ # 100.step(-5, 0) do |level|
62
+ # run { DimmerSwitch << level }
63
+ # delay 1.second
64
+ # end
65
+ # end
66
+ #
67
+ # @example
68
+ # rule 'Turn off any dimmers curently on at midnight' do
69
+ # every :day
70
+ # run do
71
+ # items.grep(DimmerItem)
72
+ # .select(&:on?)
73
+ # .each(&:off)
74
+ # end
75
+ # end
76
+ #
77
+ # @example
78
+ # rule 'Turn off any dimmers set to less than 50 at midnight' do
79
+ # every :day
80
+ # run do
81
+ # items.grep(DimmerItem)
82
+ # .select { |i| (1...50).cover?(i.state) }
83
+ # .each(&:off)
84
+ # end
85
+ # end
86
+ #
87
+ class DimmerItem < SwitchItem
88
+ include NumericItem
89
+
90
+ #
91
+ # Dim the dimmer
92
+ #
93
+ # @param [Integer] amount to dim by
94
+ # If 1 is the amount, the DECREASE command is sent, otherwise the
95
+ # current state - amount is sent as a command.
96
+ #
97
+ # @return [Integer] level target for dimmer
98
+ #
99
+ # @example
100
+ # DimmerOne.dim
101
+ # DimmerOne.dim(2)
102
+ #
103
+ def dim(amount = 1)
104
+ target = [state&.-(amount), 0].compact.max
105
+ command(target)
106
+ target
107
+ end
108
+
109
+ #
110
+ # Brighten the dimmer
111
+ #
112
+ # @param [Integer] amount to brighten by
113
+ # If 1 is the amount, the INCREASE command is sent, otherwise the
114
+ # current state + amount is sent as a command.
115
+ #
116
+ # @return [Integer] level target for dimmer
117
+ #
118
+ # @example
119
+ # DimmerOne.brighten
120
+ # DimmerOne.brighten(2)
121
+ #
122
+ def brighten(amount = 1)
123
+ target = [state&.+(amount), 100].compact.min
124
+ command(target)
125
+ target
126
+ end
127
+
128
+ # @!method increase
129
+ # Send the {INCREASE} command to the item
130
+ # @return [DimmerItem] `self`
131
+
132
+ # @!method decrease
133
+ # Send the {DECREASE} command to the item
134
+ # @return [DimmerItem] `self`
135
+
136
+ # raw numbers translate directly to PercentType, not a DecimalType
137
+ # @!visibility private
138
+ def format_type(command)
139
+ return Types::PercentType.new(command) if command.is_a?(Numeric)
140
+
141
+ super
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ # @!parse DimmerItem = OpenHAB::Core::Items::DimmerItem
@@ -0,0 +1,344 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Items
6
+ java_import org.openhab.core.items.GenericItem
7
+
8
+ #
9
+ # The abstract base class for all items.
10
+ #
11
+ # @see https://www.openhab.org/javadoc/latest/org/openhab/core/items/genericitem
12
+ #
13
+ # @!attribute [r] name
14
+ # The item's name.
15
+ # @return [String]
16
+ #
17
+ # @!attribute [r] label
18
+ # The item's descriptive label.
19
+ # @return [String, nil]
20
+ #
21
+ class GenericItem
22
+ # rubocop:disable Naming/MethodName these mimic Java fields, which are
23
+ # actually methods
24
+ class << self
25
+ # manually define this, since the Java side doesn't
26
+ # @!visibility private
27
+ def ACCEPTED_COMMAND_TYPES
28
+ [org.openhab.core.types.RefreshType.java_class].freeze
29
+ end
30
+
31
+ # manually define this, since the Java side doesn't
32
+ # @!visibility private
33
+ def ACCEPTED_DATA_TYPES
34
+ [org.openhab.core.types.UnDefType.java_class].freeze
35
+ end
36
+
37
+ # @!visibility private
38
+ #
39
+ # Override to support Proxy
40
+ #
41
+ def ===(other)
42
+ other.is_a?(self)
43
+ end
44
+ end
45
+ # rubocop:enable Naming/MethodName
46
+
47
+ # @!attribute [r] accepted_command_types
48
+ # @return [Array<Class>] An array of {Command}s that can be sent as commands to this item
49
+
50
+ # @!attribute [r] accepted_data_types
51
+ # @return [Array<Class>] An array of {State}s that can be sent as commands to this item
52
+
53
+ alias_method :hash, :hash_code
54
+
55
+ # @!attribute [r] raw_state
56
+ #
57
+ # Get the raw item state.
58
+ #
59
+ # The state of the item, including possibly {NULL} or {UNDEF}
60
+ #
61
+ # @return [State]
62
+ #
63
+ alias_method :raw_state, :state
64
+
65
+ #
66
+ # Send a command to this item
67
+ #
68
+ # @param [Command] command command to send to the item
69
+ # @return [self]
70
+ #
71
+ # @see DSL::Items::TimedCommand#command
72
+ #
73
+ def command(command)
74
+ command = format_command(command)
75
+ logger.trace "Sending Command #{command} to #{name}"
76
+ org.openhab.core.model.script.actions.BusEvent.sendCommand(self, command)
77
+ self
78
+ end
79
+
80
+ # not an alias to allow easier stubbing and overriding
81
+ def <<(command)
82
+ command(command)
83
+ end
84
+
85
+ # @!parse alias_method :<<, :command
86
+
87
+ #
88
+ # Send an update to this item
89
+ #
90
+ # @param [State] state
91
+ # @return [self]
92
+ #
93
+ def update(state)
94
+ state = format_update(state)
95
+ logger.trace "Sending Update #{state} to #{name}"
96
+ org.openhab.core.model.script.actions.BusEvent.postUpdate(self, state)
97
+ self
98
+ end
99
+
100
+ #
101
+ # Check if the item has a state (not {UNDEF} or {NULL})
102
+ #
103
+ # @return [true, false]
104
+ #
105
+ def state?
106
+ !raw_state.is_a?(Types::UnDefType)
107
+ end
108
+
109
+ #
110
+ # @!attribute [r] state
111
+ # @return [State, nil]
112
+ # OpenHAB item state if state is not {UNDEF} or {NULL}, nil otherwise.
113
+ # This makes it easy to use with the
114
+ # [Ruby safe navigation operator `&.`](https://ruby-doc.org/core-2.6/doc/syntax/calling_methods_rdoc.html)
115
+ # Use {#undef?} or {#null?} to check for those states.
116
+ #
117
+ def state
118
+ raw_state if state?
119
+ end
120
+
121
+ #
122
+ # The item's {#label} if one is defined, otherwise it's {#name}.
123
+ #
124
+ # @return [String]
125
+ #
126
+ def to_s
127
+ label || name
128
+ end
129
+
130
+ #
131
+ # @!attribute [r] groups
132
+ #
133
+ # Return all groups that this item is part of
134
+ #
135
+ # @return [Array<Group>] All groups that this item is part of
136
+ #
137
+ def groups
138
+ group_names.map { |name| EntityLookup.lookup_item(name) }.compact
139
+ end
140
+
141
+ # rubocop:disable Layout/LineLength
142
+
143
+ # @!attribute [r] metadata
144
+ # @return [Metadata::NamespaceHash]
145
+ #
146
+ # Access to the item's metadata.
147
+ #
148
+ # Both the return value of this method as well as the individual
149
+ # namespaces can be treated as Hashes.
150
+ #
151
+ # Examples assume the following items:
152
+ #
153
+ # ```xtend
154
+ # Switch Item1 { namespace1="value" [ config1="foo", config2="bar" ] }
155
+ # String StringItem1
156
+ # ```
157
+ #
158
+ # @example Check namespace's existence
159
+ # Item1.metadata["namespace"].nil?
160
+ # Item1.metadata.key?("namespace")
161
+ #
162
+ # @example Access item's metadata value
163
+ # Item1.metadata["namespace1"].value
164
+ #
165
+ # @example Access namespace1's configuration
166
+ # Item1.metadata["namespace1"]["config1"]
167
+ #
168
+ # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn"t exist
169
+ # Item1.metadata.dig("namespace1", "config1") # => "foo"
170
+ # Item1.metadata.dig("namespace2", "config1") # => nil
171
+ #
172
+ # @example Set item's metadata value, preserving its config
173
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
174
+ # Item1.metadata["namespace1"].value = "new value"
175
+ # # Item1's metadata after: {"namespace1"=>["new value", {"config1"=>"foo", "config2"=>"bar"]}}
176
+ #
177
+ # @example Set item's metadata config, preserving its value
178
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
179
+ # Item1.metadata["namespace1"].replace({ "scooby"=>"doo" })
180
+ # # Item1's metadata after: {"namespace1"=>["value", {scooby="doo"}]}
181
+ #
182
+ # @example Set a namespace to a new value and config in one line
183
+ # # Item1's metadata before: {"namespace1"=>"value", {"config1"=>"foo", "config2"=>"bar"}}
184
+ # Item1.metadata["namespace1"] = "new value", { "scooby"=>"doo" }
185
+ # # Item1's metadata after: {"namespace1"=>["new value", {scooby="doo"}]}
186
+ #
187
+ # @example Set item's metadata value and clear its previous config
188
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
189
+ # Item1.metadata["namespace1"] = "new value"
190
+ # # Item1's metadata after: {"namespace1"=>"value" }
191
+ #
192
+ # @example Set item's metadata config, set its value to nil, and wiping out previous config
193
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
194
+ # Item1.metadata["namespace1"] = { "newconfig"=>"value" }
195
+ # # Item1's metadata after: {"namespace1"=>{"config1"=>"foo", "config2"=>"bar"}}
196
+ #
197
+ # @example Update namespace1's specific configuration, preserving its value and other config
198
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
199
+ # Item1.metadata["namespace1"]["config1"] = "doo"
200
+ # # Item1's metadata will be: {"namespace1"=>["value", {"config1"=>"doo", "config2"=>"bar"}]}
201
+ #
202
+ # @example Add a new configuration to namespace1
203
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
204
+ # Item1.metadata["namespace1"]["config3"] = "boo"
205
+ # # Item1's metadata after: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar", config3="boo"}]}
206
+ #
207
+ # @example Delete a config
208
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
209
+ # Item1.metadata["namespace1"].delete("config2")
210
+ # # Item1's metadata after: {"namespace1"=>["value", {"config1"=>"foo"}]}
211
+ #
212
+ # @example Add a namespace and set it to a value
213
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
214
+ # Item1.metadata["namespace2"] = "qx"
215
+ # # Item1's metadata after: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}], "namespace2"=>"qx"}
216
+ #
217
+ # @example Add a namespace and set it to a value and config
218
+ # # Item1's metadata before: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
219
+ # Item1.metadata["namespace2"] = "qx", { "config1"=>"doo" }
220
+ # # Item1's metadata after: {"namespace1"=>["value", {"config1"=>"foo", "config2"=>"bar"}], "namespace2"=>["qx", {"config1"=>"doo"}]}
221
+ #
222
+ # @example Enumerate Item1's namespaces
223
+ # Item1.metadata.each { |namespace, metadata| logger.info("Item1's namespace: #{namespace}=#{metadata}") }
224
+ #
225
+ # @example Add metadata from a hash
226
+ # Item1.metadata.merge!({"namespace1"=>{"foo", {"config1"=>"baz"} ], "namespace2"=>{"qux", {"config"=>"quu"} ]})
227
+ #
228
+ # @example Merge Item2's metadata into Item1's metadata
229
+ # Item1.metadata.merge!(Item2.metadata)
230
+ #
231
+ # @example Delete a namespace
232
+ # Item1.metadata.delete("namespace1")
233
+ #
234
+ # @example Delete all metadata of the item
235
+ # Item1.metadata.clear
236
+ #
237
+ # @example Does this item have any metadata?
238
+ # Item1.metadata.any?
239
+ #
240
+ # @example Store another item's state
241
+ # StringItem1.update "TEST"
242
+ # Item1.metadata["other_state"] = StringItem1.state
243
+ #
244
+ # @example Store event's state
245
+ # rule "save event state" do
246
+ # changed StringItem1
247
+ # run { |event| Item1.metadata["last_event"] = event.was }
248
+ # end
249
+ #
250
+ # @example If the namespace already exists: Update the value of a namespace but preserve its config; otherwise create a new namespace with the given value and nil config.
251
+ # Item1.metadata["namespace"] = "value", Item1.metadata["namespace"]
252
+ #
253
+ # @example Copy another namespace
254
+ # # Item1's metadata before: {"namespace2"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
255
+ # Item1.metadata["namespace"] = Item1.metadata["namespace2"]
256
+ # # Item1's metadata after: {"namespace2"=>["value", {"config1"=>"foo", "config2"=>"bar"}], "namespace"=>["value", {"config1"=>"foo", "config2"=>"bar"}]}
257
+ #
258
+ def metadata
259
+ @metadata ||= Metadata::NamespaceHash.new(name)
260
+ end
261
+ # rubocop:enable Layout/LineLength
262
+
263
+ # Return the item's thing if this item is linked with a thing. If an item is linked to more than one thing,
264
+ # this method only returns the first thing.
265
+ #
266
+ # @return [Thing] The thing associated with this item or nil
267
+ def thing
268
+ all_linked_things.first
269
+ end
270
+ alias_method :linked_thing, :thing
271
+
272
+ # Returns all of the item's linked things.
273
+ #
274
+ # @return [Array<Thing>] An array of things or an empty array
275
+ def things
276
+ registry = OSGi.service("org.openhab.core.thing.link.ItemChannelLinkRegistry")
277
+ channels = registry.get_bound_channels(name).to_a
278
+ channels.map(&:thing_uid).uniq.map { |tuid| EntityLookup.lookup_thing(tuid) }.compact
279
+ end
280
+ alias_method :all_linked_things, :things
281
+
282
+ # @!method null?
283
+ # Check if the item state == {NULL}
284
+ # @return [true,false]
285
+
286
+ # @!method undef?
287
+ # Check if the item state == {UNDEF}
288
+ # @return [true,false]
289
+
290
+ # @!method refresh
291
+ # Send the {REFRESH} command to the item
292
+ # @return [GenericItem] `self`
293
+
294
+ # @!visibility private
295
+ def format_command(command)
296
+ command = format_type(command)
297
+ return command if command.is_a?(Types::Command)
298
+
299
+ command = command.to_s
300
+ org.openhab.core.types.TypeParser.parse_command(getAcceptedCommandTypes, command) || command
301
+ end
302
+
303
+ # @!visibility private
304
+ def format_update(state)
305
+ state = format_type(state)
306
+ return state if state.is_a?(Types::State)
307
+
308
+ state = state.to_s
309
+ org.openhab.core.types.TypeParser.parse_state(getAcceptedDataTypes, state) || state
310
+ end
311
+
312
+ # formats a {Types::Type} to send to the event bus
313
+ # @!visibility private
314
+ def format_type(type)
315
+ # actual Type types can be sent directly without conversion
316
+ # make sure to use Type, because this method is used for both
317
+ # #update and #command
318
+ return type if type.is_a?(Types::Type)
319
+
320
+ type.to_s
321
+ end
322
+
323
+ # @return [String]
324
+ def inspect
325
+ s = "#<OpenHAB::Core::Items::#{type}Item#{type_details} #{name} #{label.inspect} state=#{raw_state.inspect}"
326
+ s += " category=#{category.inspect}" if category
327
+ s += " tags=#{tags.to_a.inspect}" unless tags.empty?
328
+ s += " groups=#{group_names}" unless group_names.empty?
329
+ meta = metadata.to_h
330
+ s += " metadata=#{meta.inspect}" unless meta.empty?
331
+ "#{s}>"
332
+ end
333
+
334
+ private
335
+
336
+ # Allows sub-classes to append additional details to the type in an inspect string
337
+ # @return [String]
338
+ def type_details; end
339
+ end
340
+ end
341
+ end
342
+ end
343
+
344
+ # @!parse GenericItem = OpenHAB::Core::Items::GenericItem