openhab-scripting 5.5.0 → 5.6.1

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/audio.rb +5 -2
  3. data/lib/openhab/core/configuration.rb +70 -0
  4. data/lib/openhab/core/emulate_hash.rb +241 -0
  5. data/lib/openhab/core/events/abstract_event.rb +11 -0
  6. data/lib/openhab/core/events/timer_event.rb +48 -0
  7. data/lib/openhab/core/items/group_function.rb +37 -0
  8. data/lib/openhab/core/items/group_item.rb +10 -4
  9. data/lib/openhab/core/items/item.rb +31 -0
  10. data/lib/openhab/core/items/metadata/hash.rb +9 -179
  11. data/lib/openhab/core/items/metadata/namespace_hash.rb +38 -141
  12. data/lib/openhab/core/items/semantics/semantic_tag.rb +5 -0
  13. data/lib/openhab/core/items/semantics/tag_class_methods.rb +9 -0
  14. data/lib/openhab/core/items/semantics.rb +7 -3
  15. data/lib/openhab/core/rules/rule.rb +17 -4
  16. data/lib/openhab/core/things/links/provider.rb +1 -1
  17. data/lib/openhab/core/things/proxy.rb +2 -1
  18. data/lib/openhab/core/things/thing.rb +23 -0
  19. data/lib/openhab/core/types/date_time_type.rb +2 -1
  20. data/lib/openhab/core/types/open_closed_type.rb +2 -1
  21. data/lib/openhab/core/types/string_type.rb +1 -1
  22. data/lib/openhab/core/types/up_down_type.rb +2 -1
  23. data/lib/openhab/core/value_cache.rb +6 -5
  24. data/lib/openhab/core_ext/java/duration.rb +2 -1
  25. data/lib/openhab/core_ext/java/local_time.rb +8 -6
  26. data/lib/openhab/core_ext/java/month_day.rb +2 -1
  27. data/lib/openhab/core_ext/java/period.rb +1 -1
  28. data/lib/openhab/core_ext/ruby/numeric.rb +1 -0
  29. data/lib/openhab/dsl/items/builder.rb +13 -6
  30. data/lib/openhab/dsl/rules/automation_rule.rb +29 -5
  31. data/lib/openhab/dsl/rules/builder.rb +47 -22
  32. data/lib/openhab/dsl/rules/rule_triggers.rb +1 -1
  33. data/lib/openhab/dsl/rules/triggers/conditions/generic.rb +1 -1
  34. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +43 -16
  35. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +101 -96
  36. data/lib/openhab/dsl/things/builder.rb +8 -6
  37. data/lib/openhab/dsl/thread_local.rb +1 -0
  38. data/lib/openhab/dsl/timer_manager.rb +4 -4
  39. data/lib/openhab/dsl/version.rb +1 -1
  40. data/lib/openhab/dsl.rb +23 -4
  41. data/lib/openhab/osgi.rb +1 -1
  42. data/lib/openhab/rspec/karaf.rb +7 -4
  43. data/lib/openhab/rspec/openhab/core/actions.rb +0 -3
  44. metadata +13 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b21bcd2b958405fb4b4843435e3a6ffa14690af1b6f58139897982a7d55323f
4
- data.tar.gz: a1c258192db348813c49b94e21492771d9b2e7d6515e6aff0e04b5bba7786711
3
+ metadata.gz: 9d58174285c7861dfffd3bdb108f6d9c01af149a4f53aab9b9dd331be7f0f022
4
+ data.tar.gz: 6bdb6e115927aea3396ca05be97ecb1ee9d8afc9bc493689c32f7fcd19a7e71a
5
5
  SHA512:
6
- metadata.gz: 81fd4bfaa0f3cb1907622938750dc0eabcc51b0d46d8ad39fd63282ad6118771f79b38a72fc10ffaa19f0037564d1adb710c7da0b981dad37f9cdf9b6f665cfd
7
- data.tar.gz: 1b30d461514d2f952e71e3ce7325dd5582fa386ca21723458b725378f6f78880f96bf5693a03aeb64d8a70775830979fe6d8f732c67076abaf9fd687e0ff4948
6
+ metadata.gz: 454fb750a412b8e153ce7df0320738b1f9729e1313d6d8e9aaaaa7c720c8c0cda7f704a35d78952705e7f21718551daae2c01e0dcf0b7e26c1fbfa2481d5ab6b
7
+ data.tar.gz: 0a1e62ecb2bcce48a207bed5899bd0e7913492836a5c953a4b22756fa149b353ee8db229e3b5b71f48d503db1d7bfaa4f8baa94abe92469047b386ab3d438da6
@@ -23,8 +23,11 @@ module OpenHAB
23
23
  #
24
24
  def play_sound(filename, sink: nil, volume: nil)
25
25
  volume = PercentType.new(volume) unless volume.is_a?(PercentType) || volume.nil?
26
- java_send :playSound, [java.lang.String, java.lang.String, PercentType.java_class],
27
- sink, filename.to_s, volume
26
+ java_send :playSound,
27
+ [java.lang.String, java.lang.String, PercentType.java_class],
28
+ sink,
29
+ filename.to_s,
30
+ volume
28
31
  end
29
32
 
30
33
  #
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require_relative "emulate_hash"
5
+
6
+ module OpenHAB
7
+ module Core
8
+ java_import org.openhab.core.config.core.Configuration
9
+
10
+ #
11
+ # {Configuration} represents openHAB's {org.openhab.core.config.core.Configuration} data
12
+ # with the full interface of {::Hash}.
13
+ #
14
+ # All keys are converted to strings.
15
+ #
16
+ class Configuration
17
+ include EmulateHash
18
+ extend Forwardable
19
+
20
+ alias_method :to_map, :properties
21
+ private :to_map
22
+
23
+ # @!visibility private
24
+ def [](key)
25
+ get(key.to_s)
26
+ end
27
+
28
+ # @!visibility private
29
+ def store(key, value)
30
+ put(key.to_s, value)
31
+ end
32
+
33
+ # @!visibility private
34
+ def delete(key)
35
+ key = key.to_s
36
+ return yield(key) if block_given? && !key?(key)
37
+
38
+ remove(key)
39
+ end
40
+
41
+ # @!visibility private
42
+ def key?(key)
43
+ contains_key(key.to_s)
44
+ end
45
+
46
+ # @!visibility private
47
+ def replace(new_pairs)
48
+ set_properties(new_pairs.to_h.transform_keys(&:to_s))
49
+ self
50
+ end
51
+
52
+ # @!visibility private
53
+ alias_method :keys, :key_set
54
+
55
+ # @!visibility private
56
+ def dup
57
+ self.class.new(self)
58
+ end
59
+
60
+ # @!visibility private
61
+ def ==(other)
62
+ if !other.is_a?(self.class) && other.respond_to?(:to_hash)
63
+ return to_hash == other.to_hash.transform_keys(&:to_s)
64
+ end
65
+
66
+ equals(other)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,241 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ #
8
+ # Make a class acts like a Ruby Hash that supports indifferent keys.
9
+ #
10
+ # Methods that accepts keys will convert symbolic keys to string keys, but only shallowly.
11
+ # This key indifference does not extend to Hash return values, however.
12
+ # Hash return values will behave like a normal Hash
13
+ # which treats symbolic and string keys differently.
14
+ #
15
+ # The including class must implement at least:
16
+ # - `#to_map` to provide the hash-like data
17
+ # - `#replace`
18
+ # - `#store`
19
+ # - Other methods and mutators as applicable to the underlying storage.
20
+ #
21
+ module EmulateHash
22
+ include Enumerable
23
+ extend Forwardable
24
+
25
+ # Methods delegated to to_map
26
+ DELEGATED_METHODS = %i[>
27
+ >=
28
+ <
29
+ <=
30
+ ==
31
+ any?
32
+ compact
33
+ deconstruct_keys
34
+ transform_keys
35
+ to_hash
36
+ length
37
+ size
38
+ compare_by_identity?
39
+ each
40
+ each_key
41
+ each_pair
42
+ each_value
43
+ equals
44
+ empty?
45
+ filter
46
+ flatten
47
+ has_value?
48
+ invert
49
+ key
50
+ keys
51
+ rassoc
52
+ reject
53
+ select
54
+ shift
55
+ to_a
56
+ to_h
57
+ to_hash
58
+ transform_keys
59
+ transform_values
60
+ value?
61
+ values].freeze
62
+ private_constant :DELEGATED_METHODS
63
+
64
+ def_delegators :to_map, *DELEGATED_METHODS
65
+
66
+ def_delegator :to_h, :inspect
67
+
68
+ # @!visibility private
69
+ alias_method :to_s, :inspect
70
+
71
+ # @!visibility private
72
+ def except(*keys)
73
+ to_map.except(*keys.map(&:to_s))
74
+ end
75
+
76
+ # @!visibility private
77
+ def key?(key)
78
+ to_map.key?(key.to_s)
79
+ end
80
+ alias_method :has_key?, :key?
81
+ alias_method :include?, :key?
82
+
83
+ #
84
+ # @see https://ruby-doc.org/core/Hash.html#method-i-merge
85
+ #
86
+ # java.util.Map#merge is incompatible to Ruby's, but JRuby provides #ruby_merge for it
87
+ #
88
+ # @!visibility private
89
+ def merge(*others, &block)
90
+ return self if others.empty?
91
+
92
+ others.map! { |hash| hash.transform_keys(&:to_s) }
93
+ map = to_map
94
+ if map.respond_to?(:ruby_merge)
95
+ map.ruby_merge(*others, &block)
96
+ else
97
+ # fall back to #merge in case #to_map returns a Ruby Hash
98
+ map.merge(*others, &block)
99
+ end
100
+ end
101
+
102
+ # @!visibility private
103
+ def merge!(*others, &block)
104
+ return self if others.empty?
105
+
106
+ replace(merge(*others, &block))
107
+ end
108
+ alias_method :update, :merge!
109
+
110
+ # @!visibility private
111
+ def replace
112
+ raise NotImplementedError
113
+ end
114
+
115
+ # @!visibility private
116
+ def slice(*keys)
117
+ to_map.slice(*keys.map(&:to_s))
118
+ end
119
+
120
+ # @!visibility private
121
+ def fetch(key, *default, &block)
122
+ to_map.fetch(key.to_s, *default, &block)
123
+ end
124
+
125
+ # @!visibility private
126
+ def [](key)
127
+ fetch(key, nil)
128
+ end
129
+
130
+ # @!visibility private
131
+ def store(key, value)
132
+ raise NotImplementedError
133
+ end
134
+
135
+ # @!visibility private
136
+ def []=(key, value)
137
+ store(key, value)
138
+ end
139
+
140
+ # @!visibility private
141
+ def assoc(key)
142
+ to_map.assoc(key.to_s)
143
+ end
144
+
145
+ # @!visibility private
146
+ def clear
147
+ replace({})
148
+ end
149
+
150
+ # @!visibility private
151
+ def dig(key, *keys)
152
+ to_map.dig(key.to_s, *keys)
153
+ end
154
+
155
+ # @!visibility private
156
+ def compact!
157
+ to_h.compact!&.then { |r| replace(r) }
158
+ end
159
+
160
+ # @!visibility private
161
+ def delete_if(&block)
162
+ raise NotImplementedError unless block
163
+
164
+ replace(to_h.delete_if(&block))
165
+ end
166
+
167
+ # @!visibility private
168
+ def keep_if(&block)
169
+ select!(&block)
170
+ self
171
+ end
172
+
173
+ # @!visibility private
174
+ def select!(&block)
175
+ raise NotImplementedError unless block
176
+
177
+ to_h.select!(&block)&.then { |r| replace(r) }
178
+ end
179
+ alias_method :filter!, :select!
180
+
181
+ # @!visibility private
182
+ def reject!(&block)
183
+ raise NotImplementedError unless block
184
+
185
+ to_h.reject!(&block)&.then { |r| replace(r) }
186
+ end
187
+
188
+ # @!visibility private
189
+ def fetch_values(*keys, &block)
190
+ to_map.fetch_values(*keys.map(&:to_s), &block)
191
+ end
192
+
193
+ # @!visibility private
194
+ def transform_keys!(*args, &block)
195
+ replace(transform_keys(*args, &block))
196
+ end
197
+
198
+ # @!visibility private
199
+ def transform_values!(&block)
200
+ raise NotImplementedError unless block
201
+
202
+ replace(transform_values(&block))
203
+ end
204
+
205
+ # @!visibility private
206
+ def values_at(*keys)
207
+ to_map.values_at(*keys.map(&:to_s))
208
+ end
209
+
210
+ # @!visibility private
211
+ def compare_by_identity
212
+ raise NotImplementedError
213
+ end
214
+
215
+ # @!visibility private
216
+ def default=(*)
217
+ raise NotImplementedError
218
+ end
219
+
220
+ # @!visibility private
221
+ def default_proc=(*)
222
+ raise NotImplementedError
223
+ end
224
+
225
+ # @!visibility private
226
+ def default(*)
227
+ nil
228
+ end
229
+
230
+ # @!visibility private
231
+ def default_proc
232
+ nil
233
+ end
234
+
235
+ # @!visibility private
236
+ def to_proc
237
+ ->(k) { self[k] }
238
+ end
239
+ end
240
+ end
241
+ end
@@ -12,6 +12,17 @@ module OpenHAB
12
12
 
13
13
  # @return [String]
14
14
  alias_method :inspect, :to_s
15
+
16
+ #
17
+ # Returns the event payload as a Hash.
18
+ #
19
+ # @return [Hash, nil] The payload object parsed by JSON. The keys are symbolized.
20
+ # `nil` when the payload is empty.
21
+ #
22
+ def payload
23
+ require "json"
24
+ @payload ||= JSON.parse(get_payload, symbolize_names: true) unless get_payload.empty?
25
+ end
15
26
  end
16
27
  end
17
28
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Events
6
+ # @deprecated OH3.4 this guard is not needed on OH4
7
+ if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
8
+ java_import org.openhab.core.automation.events.TimerEvent
9
+
10
+ #
11
+ # Adds methods to core openHAB TimerEvent to make it more natural in Ruby
12
+ #
13
+ # This event can be triggered by a `DateTimeTrigger`, `cron`, or `TimeOfDay` trigger.
14
+ #
15
+ # @since openHAB 4.0
16
+ #
17
+ class TimerEvent < AbstractEvent
18
+ #
19
+ # @!attribute [r] cron_expression
20
+ # @return [String, nil] The cron expression that triggered this event.
21
+ # `nil` when this event wasn't triggered by a cron trigger.
22
+ #
23
+ def cron_expression
24
+ payload&.[](:cronExpression)
25
+ end
26
+
27
+ #
28
+ # @!attribute [r] item
29
+ # @return [Item, nil] The DateTime item that triggered this event.
30
+ # `nil` when this event wasn't triggered by a DateTimeItem trigger.
31
+ #
32
+ def item
33
+ payload&.[](:itemName)&.then { |item_name| EntityLookup.lookup_item(item_name) }
34
+ end
35
+
36
+ #
37
+ # @!attribute [r] time
38
+ # @return [LocalTime, nil] The configured time for this TimeOfDay trigger event.
39
+ # `nil` when this event wasn't triggered by a TimeOfDay trigger.
40
+ #
41
+ def time
42
+ payload&.[](:time)&.then { |time| LocalTime.parse(time) }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Items
6
+ java_import org.openhab.core.items.GroupFunction
7
+
8
+ #
9
+ # Adds `#to_s` and `#inspect` to group function.
10
+ #
11
+ # @example
12
+ # # Group:SWITCH:OR(ON,OFF) Switches
13
+ # logger.info "The Switches group function is: #{Switches.function}" # => "OR"
14
+ # logger.info "The Switches group function: #{Switches.function.inspect}" # => "OR(ON,OFF)"
15
+ #
16
+ module GroupFunction
17
+ #
18
+ # Returns the group function as an uppercase string
19
+ # @return [String]
20
+ #
21
+ def to_s
22
+ self.class.simple_name.upcase
23
+ end
24
+
25
+ #
26
+ # Returns the group function and its parameters as a string
27
+ # @return [String]
28
+ #
29
+ def inspect
30
+ params = parameters.map(&:inspect).join(",")
31
+ params = "(#{params})" unless params.empty?
32
+ "#{self}#{params}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -143,16 +143,22 @@ module OpenHAB
143
143
  base_item.format_type(command)
144
144
  end
145
145
 
146
+ %w[color contact date_time dimmer image location number player rollershutter string switch].each do |type|
147
+ type_class = type.gsub(/(^[a-z]|_[a-z])/) { |letter| letter[-1].upcase }
148
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
149
+ def #{type}_item? # def date_time_item?
150
+ base_item&.is_a?(#{type_class}Item) # base_item&.is_a?(DateTimeItem)
151
+ end # end
152
+ RUBY
153
+ end
154
+
146
155
  private
147
156
 
148
157
  # Add base type and function details
149
158
  def type_details
150
159
  r = ""
151
160
  r += ":#{base_item.type}#{base_item.__send__(:type_details)}" if base_item
152
- if function && (fn = function.class.java_class.simple_name.upcase) != "EQUALITY"
153
- r += ":#{fn}"
154
- r += "(#{function.parameters.map(&:inspect).join(",")})" unless function.parameters.empty?
155
- end
161
+ r += ":#{function.inspect}" if function && function.to_s != "EQUALITY"
156
162
  r
157
163
  end
158
164
 
@@ -18,6 +18,22 @@ module OpenHAB
18
18
  def ===(other)
19
19
  other.is_a?(self)
20
20
  end
21
+
22
+ private
23
+
24
+ # @!macro def_type_predicate
25
+ # @!method $1_item?
26
+ # Check if the item is a $1 item.
27
+ # @note If the item is a group item, it will also return true if the base item is a $1 item.
28
+ # @return [true,false]
29
+ def def_type_predicate(type)
30
+ type_class = type.to_s.gsub(/(^[a-z]|_[a-z])/) { |letter| letter[-1].upcase }
31
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
32
+ def #{type}_item? # def date_time_item?
33
+ is_a?(#{type_class}Item) # is_a?(DateTimeItem)
34
+ end # end
35
+ RUBY
36
+ end
21
37
  end
22
38
 
23
39
  # @!attribute [r] name
@@ -270,6 +286,21 @@ module OpenHAB
270
286
  Provider.registry.provider_for(self)
271
287
  end
272
288
 
289
+ def_type_predicate(:color)
290
+ def_type_predicate(:contact)
291
+ def_type_predicate(:date_time)
292
+ # @note Color items are also considered dimmer items.
293
+ def_type_predicate(:dimmer)
294
+ def_type_predicate(:group)
295
+ def_type_predicate(:image)
296
+ def_type_predicate(:location)
297
+ def_type_predicate(:number)
298
+ def_type_predicate(:player)
299
+ def_type_predicate(:rollershutter)
300
+ def_type_predicate(:string)
301
+ # @note Color and dimmer items are also considered switch items.
302
+ def_type_predicate(:switch)
303
+
273
304
  private
274
305
 
275
306
  # Allows sub-classes to append additional details to the type in an inspect string