openhab-scripting 5.6.1 → 5.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d58174285c7861dfffd3bdb108f6d9c01af149a4f53aab9b9dd331be7f0f022
4
- data.tar.gz: 6bdb6e115927aea3396ca05be97ecb1ee9d8afc9bc493689c32f7fcd19a7e71a
3
+ metadata.gz: 951ad54507dbf4b297d59534c124c21bbf6f6b7a02e4c3fa967a5290aac9968e
4
+ data.tar.gz: d4b33c4b8cdf237c6bdc1c2b99b87459f913f2d787423f261677d469d9629df3
5
5
  SHA512:
6
- metadata.gz: 454fb750a412b8e153ce7df0320738b1f9729e1313d6d8e9aaaaa7c720c8c0cda7f704a35d78952705e7f21718551daae2c01e0dcf0b7e26c1fbfa2481d5ab6b
7
- data.tar.gz: 0a1e62ecb2bcce48a207bed5899bd0e7913492836a5c953a4b22756fa149b353ee8db229e3b5b71f48d503db1d7bfaa4f8baa94abe92469047b386ab3d438da6
6
+ metadata.gz: f26471513aca95dcb0266ffca7176ee57980cbea404c8290c095642c4851954e4d870232507cbea34c6b6c4a940da84d6681944ee039199c3fcc766bdd64a598
7
+ data.tar.gz: 0c6e9e9cf72ee4a1935c399c235256144b0c6fbbb7bc0eb3f07a81405f3e52cc0193a1856ec910212f963c37208cb29191bbe90d143bf822bfc2c987828de47d
@@ -3,6 +3,17 @@
3
3
  module OpenHAB
4
4
  module Core
5
5
  module Actions
6
+ #
7
+ # The HTTP actions allow you to send HTTP requests and receive the response.
8
+ #
9
+ # @example
10
+ # # Send a GET request
11
+ # headers = {
12
+ # "User-Agent": "JRuby/1.2.3", # enclose in quotes if the key contains dashes
13
+ # Accept: "application/json",
14
+ # }
15
+ # response = HTTP.send_http_get_request("http://example.com/list", headers: headers)
16
+ #
6
17
  # @see https://www.openhab.org/docs/configuration/actions.html#http-actions HTTP Actions
7
18
  class HTTP
8
19
  class << self
@@ -10,7 +21,8 @@ module OpenHAB
10
21
  # Sends an HTTP GET request and returns the result as a String.
11
22
  #
12
23
  # @param [String] url
13
- # @param [Hash<String, String>] headers
24
+ # @param [Hash<String, String>, Hash<Symbol, String>] headers
25
+ # A hash of headers to send with the request. Symbolic keys will be converted to strings.
14
26
  # @param [Duration, int, nil] timeout Timeout (in milliseconds, if given as an Integer)
15
27
  # @return [String] the response body
16
28
  # @return [nil] if an error occurred
@@ -19,7 +31,7 @@ module OpenHAB
19
31
  timeout ||= 5_000
20
32
  timeout = timeout.to_millis if timeout.is_a?(Duration)
21
33
 
22
- sendHttpGetRequest(url, headers, timeout)
34
+ sendHttpGetRequest(url, headers.transform_keys(&:to_s), timeout)
23
35
  end
24
36
 
25
37
  #
@@ -28,7 +40,8 @@ module OpenHAB
28
40
  # @param [String] url
29
41
  # @param [String] content_type
30
42
  # @param [String] content
31
- # @param [Hash<String, String>] headers
43
+ # @param [Hash<String, String>, Hash<Symbol, String>] headers
44
+ # A hash of headers to send with the request. Symbolic keys will be converted to strings.
32
45
  # @param [Duration, int, nil] timeout Timeout (in milliseconds, if given as an Integer)
33
46
  # @return [String] the response body
34
47
  # @return [nil] if an error occurred
@@ -37,7 +50,7 @@ module OpenHAB
37
50
  timeout ||= 1_000
38
51
  timeout = timeout.to_millis if timeout.is_a?(Duration)
39
52
 
40
- sendHttpPutRequest(url, content_type, content, headers, timeout)
53
+ sendHttpPutRequest(url, content_type, content, headers.transform_keys(&:to_s), timeout)
41
54
  end
42
55
 
43
56
  #
@@ -46,7 +59,8 @@ module OpenHAB
46
59
  # @param [String] url
47
60
  # @param [String] content_type
48
61
  # @param [String] content
49
- # @param [Hash<String, String>] headers
62
+ # @param [Hash<String, String>, Hash<Symbol, String>] headers
63
+ # A hash of headers to send with the request. Symbolic keys will be converted to strings.
50
64
  # @param [Duration, int, nil] timeout Timeout (in milliseconds, if given as an Integer)
51
65
  # @return [String] the response body
52
66
  # @return [nil] if an error occurred
@@ -55,14 +69,16 @@ module OpenHAB
55
69
  timeout ||= 1_000
56
70
  timeout = timeout.to_millis if timeout.is_a?(Duration)
57
71
 
58
- sendHttpPostRequest(url, content_type, content, headers, timeout)
72
+ sendHttpPostRequest(url, content_type, content, headers.transform_keys(&:to_s), timeout)
59
73
  end
60
74
 
61
75
  #
62
76
  # Sends an HTTP DELETE request and returns the result as a String.
63
77
  #
64
78
  # @param [String] url
65
- # @param [Hash<String, String>] headers
79
+ # @param [Hash<String, String>, Hash<Symbol, String>] headers
80
+ # A hash of headers to send with the request. Keys are strings or symbols, values are strings.
81
+ # Underscores in symbolic keys are replaced with dashes.
66
82
  # @param [Duration, int, nil] timeout Timeout (in milliseconds, if given as an Integer)
67
83
  # @return [String] the response body
68
84
  # @return [nil] if an error occurred
@@ -71,7 +87,7 @@ module OpenHAB
71
87
  timeout ||= 1_000
72
88
  timeout = timeout.to_millis if timeout.is_a?(Duration)
73
89
 
74
- sendHttpDeleteRequest(url, headers, timeout)
90
+ sendHttpDeleteRequest(url, headers.transform_keys(&:to_s), timeout)
75
91
  end
76
92
  end
77
93
  end
@@ -48,7 +48,7 @@ module OpenHAB
48
48
  # @yield Block executed in the context of a {DSL::Items::Builder}
49
49
  # @return [Object] The return value of the block.
50
50
  #
51
- # (see Items::Builder)
51
+ # @see DSL::Items::Builder
52
52
  #
53
53
  def build(preferred_provider = nil, &block)
54
54
  DSL::Items::BaseBuilderDSL.new(preferred_provider).instance_eval_with_dummy_items(&block)
@@ -262,7 +262,7 @@ module OpenHAB
262
262
  # @deprecated OH3.4 cannot add a tag
263
263
  # this not in the class << self block above because YARD doesn't figure out
264
264
  # it's a class method with the conditional
265
- if Provider.registry || org.openhab.core.semantics.SemanticTags.respond_to?(:add)
265
+ if Provider.registry
266
266
  class << self
267
267
  #
268
268
  # Adds custom semantic tags.
@@ -311,25 +311,16 @@ module OpenHAB
311
311
  synonyms = Array.wrap(synonyms).map { |s| s.to_s.strip }
312
312
 
313
313
  tags.map do |name, parent|
314
- # @deprecated OH4.0.0.M4 missing registry
315
- if Provider.registry
316
- parent = lookup(parent) unless parent.is_a?(SemanticTag)
317
- next if lookup(name)
318
- next unless parent
319
-
320
- new_tag = org.openhab.core.semantics.SemanticTagImpl.new("#{parent.uid}_#{name}",
321
- label,
322
- description,
323
- synonyms)
324
- Provider.instance.add(new_tag)
325
- lookup(name)
326
- else
327
- parent_is_tag = parent.respond_to?(:java_class) && parent.java_class < Tag.java_class
328
- parent = parent_is_tag ? parent.java_class : parent.to_s
329
- org.openhab.core.semantics.SemanticTags
330
- .add(name.to_s, parent, label, synonyms.join(","), description)
331
- &.then { lookup(name) }
332
- end
314
+ parent = lookup(parent) unless parent.is_a?(SemanticTag)
315
+ next if lookup(name)
316
+ next unless parent
317
+
318
+ new_tag = org.openhab.core.semantics.SemanticTagImpl.new("#{parent.uid}_#{name}",
319
+ label,
320
+ description,
321
+ synonyms)
322
+ Provider.instance.add(new_tag)
323
+ lookup(name)
333
324
  end.compact
334
325
  end
335
326
  end
@@ -44,6 +44,7 @@ module OpenHAB
44
44
 
45
45
  # Known supported provider types
46
46
  # @return [Array<Symbol>]
47
+ # @!visibility private
47
48
  KNOWN_TYPES = %i[items metadata things links].freeze
48
49
 
49
50
  class << self
@@ -223,7 +224,6 @@ module OpenHAB
223
224
  def initialize(unload_priority: nil)
224
225
  super()
225
226
  @elements = java.util.concurrent.ConcurrentHashMap.new
226
- # @deprecated OH3.4 safe navigation only required for missing Semantics registry
227
227
  self.class.registry&.add_provider(self)
228
228
  ScriptHandling.script_unloaded(priority: unload_priority) { unregister }
229
229
  end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ #
8
+ # Contains sitemap related classes.
9
+ #
10
+ module Sitemaps
11
+ #
12
+ # Provides sitemaps created in Ruby to openHAB
13
+ #
14
+ class Provider < Core::Provider
15
+ PREFIX = "jruby_"
16
+ SUFFIX = ".sitemap"
17
+ private_constant :PREFIX, :SUFFIX
18
+
19
+ class << self
20
+ # @!visibility private
21
+ def registry
22
+ nil
23
+ end
24
+ end
25
+
26
+ include org.openhab.core.model.sitemap.SitemapProvider
27
+
28
+ # @!visibility private
29
+ alias_method :getSitemap, :get
30
+
31
+ # rubocop:disable Naming/MethodName
32
+
33
+ # @!visibility private
34
+ def getSitemapNames
35
+ @elements.key_set
36
+ end
37
+
38
+ # @!visibility private
39
+ def addModelChangeListener(listener)
40
+ @listeners.add(listener)
41
+ end
42
+
43
+ # @!visibility private
44
+ def removeModelChangeListener(listener)
45
+ @listeners.remove(listener)
46
+ end
47
+
48
+ # rubocop:enable Naming/MethodName
49
+
50
+ # @!visibility private
51
+ def unregister
52
+ @registration.unregister
53
+ end
54
+
55
+ # rubocop:disable Layout/LineLength
56
+
57
+ #
58
+ # Enter the Sitemap Builder DSL.
59
+ #
60
+ # @yield Block executed in the context of a {DSL::Sitemaps::Builder}
61
+ # @return [void]
62
+ #
63
+ # @see DSL::Sitemaps::Builder
64
+ #
65
+ # @example
66
+ # sitemaps.build do
67
+ # sitemap "default", "My Residence" do
68
+ # frame label: "Control" do
69
+ # text label: "Climate", icon: "if:mdi:home-thermometer-outline" do
70
+ # frame label: "Main Floor" do
71
+ # text item: MainFloor_AmbTemp
72
+ # switch item: MainFloorThermostat_TargetMode, label: "Mode", mappings: %w[off auto cool heat]
73
+ # setpoint item: MainFloorThermostat_SetPoint, label: "Set Point", visibility: "MainFloorThermostat_TargetMode!=off"
74
+ # end
75
+ # frame label: "Basement" do
76
+ # text item: Basement_AmbTemp
77
+ # switch item: BasementThermostat_TargetMode, label: "Mode", mappings: { OFF: "off", COOL: "cool", HEAT: "heat" }
78
+ # setpoint item: BasementThermostat_SetPoint, label: "Set Point", visibility: "BasementThermostat_TargetMode!=off"
79
+ # end
80
+ # end
81
+ # end
82
+ # end
83
+ # end
84
+ #
85
+ def build(&block)
86
+ DSL::Sitemaps::Builder.new(self).instance_eval(&block)
87
+ end
88
+ # rubocop:enable Layout/LineLength
89
+
90
+ # For use in specs
91
+ # @!visibility private
92
+ def clear
93
+ elements = @elements
94
+ @elements = java.util.concurrent.ConcurrentHashMap.new
95
+ elements.each_value do |v|
96
+ notify_listeners_about_removed_element(v)
97
+ end
98
+ end
99
+
100
+ #
101
+ # Remove a sitemap.
102
+ #
103
+ # @param [String] sitemap_name
104
+ # @return [Boolean] If a sitemap was removed
105
+ def remove(sitemap_name)
106
+ super("#{PREFIX}#{sitemap_name}#{SUFFIX}")
107
+ end
108
+
109
+ private
110
+
111
+ def initialize
112
+ super
113
+ @listeners = java.util.concurrent.CopyOnWriteArraySet.new
114
+
115
+ @registration = OSGi.register_service(self, org.openhab.core.model.sitemap.SitemapProvider)
116
+ end
117
+
118
+ def notify_listeners_about_added_element(element)
119
+ @listeners.each { |l| l.model_changed(element.name, org.openhab.core.model.core.EventType::ADDED) }
120
+ end
121
+
122
+ def notify_listeners_about_removed_element(element)
123
+ @listeners.each { |l| l.model_changed(element.name, org.openhab.core.model.core.EventType::REMOVED) }
124
+ end
125
+
126
+ def notify_listeners_about_updated_element(element)
127
+ @listeners.each { |l| l.model_changed(element.name, org.openhab.core.model.core.EventType::MODIFIED) }
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -49,7 +49,8 @@ module OpenHAB
49
49
  @id = id
50
50
  @thread_locals = thread_locals
51
51
  @block = block
52
- @timer = ScriptExecution.create_timer(1.minute.from_now) { execute }
52
+ timer_identifier = block.source_location.join(":")
53
+ @timer = ScriptExecution.create_timer(timer_identifier, 1.minute.from_now) { execute }
53
54
  reschedule!(@time)
54
55
  end
55
56
 
@@ -174,25 +174,30 @@ module OpenHAB
174
174
  add: :+,
175
175
  subtract: :-
176
176
  }.each do |java_op, ruby_op|
177
- convert = "self.class.new(other, DSL.unit(dimension) || unit)"
177
+ convert = "self.class.new(other, thread_unit)"
178
178
 
179
179
  class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
180
180
  # def +(other)
181
181
  # logger.trace("#{self} + #{other} (#{other.class})")
182
182
  # if other.is_a?(QuantityType)
183
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
184
+ # elsif (thread_unit = DSL.unit(dimension))
185
+ # if other.is_a?(DecimalType)
186
+ # other = other.to_big_decimal
187
+ # add_quantity(self.class.new(other, thread_unit))
188
+ # elsif other.is_a?(java.math.BigDecimal)
189
+ # add_quantity(self.class.new(other, thread_unit))
190
+ # elsif other.respond_to?(:to_d)
191
+ # other = other.to_d.to_java
192
+ # add_quantity(self.class.new(other, thread_unit))
193
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
194
+ # lhs + rhs
195
+ # else
196
+ # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
197
+ # end
194
198
  # else
195
- # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
199
+ # raise TypeError,
200
+ # "#{self.class} can only be added with another #{self.class} outside a unit block"
196
201
  # end
197
202
  # end
198
203
  <<~RUBY, __FILE__, __LINE__ + 1
@@ -200,18 +205,23 @@ module OpenHAB
200
205
  logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
201
206
  if other.is_a?(QuantityType)
202
207
  #{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
208
+ elsif (thread_unit = DSL.unit(dimension))
209
+ if other.is_a?(DecimalType)
210
+ other = other.to_big_decimal
211
+ #{java_op}_quantity(#{convert})
212
+ elsif other.is_a?(java.math.BigDecimal)
213
+ #{java_op}_quantity(#{convert})
214
+ elsif other.respond_to?(:to_d)
215
+ other = other.to_d.to_java
216
+ #{java_op}_quantity(#{convert})
217
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
218
+ lhs #{ruby_op} rhs
219
+ else
220
+ raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
221
+ end
213
222
  else
214
- raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
223
+ raise TypeError,
224
+ "\#{self.class} can only be #{java_op}ed with another \#{self.class} outside a unit block"
215
225
  end
216
226
  end
217
227
  RUBY
@@ -243,13 +253,13 @@ module OpenHAB
243
253
  def #{ruby_op}(other)
244
254
  logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
245
255
  if other.is_a?(QuantityType)
246
- #{java_op}_quantity(other)
256
+ #{java_op}_quantity(other).unitize
247
257
  elsif other.is_a?(DecimalType)
248
- #{java_op}(other.to_big_decimal)
258
+ #{java_op}(other.to_big_decimal).unitize
249
259
  elsif other.is_a?(java.math.BigDecimal)
250
- #{java_op}(other)
260
+ #{java_op}(other).unitize
251
261
  elsif other.respond_to?(:to_d)
252
- #{java_op}(other.to_d.to_java)
262
+ #{java_op}(other.to_d.to_java).unitize
253
263
  elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
254
264
  lhs #{ruby_op} rhs
255
265
  else
@@ -262,7 +272,7 @@ module OpenHAB
262
272
 
263
273
  # if it's a dimensionless quantity, change the unit to match other_unit
264
274
  # @!visibility private
265
- def unitize(other_unit = unit)
275
+ def unitize(other_unit = unit, relative: false)
266
276
  # prefer converting to the thread-specified unit if there is one
267
277
  other_unit = DSL.unit(dimension) || other_unit
268
278
  logger.trace("Converting #{self} to #{other_unit}")
@@ -273,7 +283,7 @@ module OpenHAB
273
283
  when other_unit
274
284
  self
275
285
  else
276
- to_unit(other_unit)
286
+ relative ? to_unit_relative(other_unit) : to_unit(other_unit)
277
287
  end
278
288
  end
279
289
 
@@ -288,16 +298,16 @@ module OpenHAB
288
298
 
289
299
  private
290
300
 
291
- # do addition directly against a QuantityType while ensuring we unitize
292
- # both sides
301
+ # do addition directly against a QuantityType while ensuring we unitize both sides
293
302
  def add_quantity(other)
294
- unitize(other.unit).add(other.unitize(unit))
303
+ self_unit = (unit == Units::ONE && DSL.unit(other.dimension)) || unit
304
+ unitize(self_unit).add(other.unitize(relative: true))
295
305
  end
296
306
 
297
- # do subtraction directly against a QuantityType while ensuring we
298
- # unitize both sides
307
+ # do subtraction directly against a QuantityType while ensuring we unitize both sides
299
308
  def subtract_quantity(other)
300
- unitize(other.unit).subtract(other.unitize(unit))
309
+ self_unit = (unit == Units::ONE && DSL.unit(other.dimension)) || unit
310
+ unitize(self_unit).subtract(other.unitize(relative: true))
301
311
  end
302
312
 
303
313
  # do multiplication directly against a QuantityType while ensuring
@@ -1592,12 +1592,15 @@ module OpenHAB
1592
1592
  end
1593
1593
 
1594
1594
  #
1595
- # Creates a trigger based on the time stored in a {DateTimeItem}
1595
+ # Creates a trigger based on the date and time stored in a {DateTimeItem}
1596
1596
  #
1597
- # The trigger will dynamically update any time the state of the item
1598
- # changes. If the item is {NULL} or {UNDEF}, the trigger will not run.
1597
+ # The trigger will dynamically update whenever the state of the item changes.
1598
+ # If the item is {NULL} or {UNDEF}, the trigger will not run.
1599
1599
  #
1600
- # @param [Item, String, Symbol] item The item (or it's name)
1600
+ # To trigger just on the time portion of the item, use {every} instead, e.g.
1601
+ # `every :day, at: MyDateTimeItem`.
1602
+ #
1603
+ # @param [Item, String, Symbol] item The item (or its name)
1601
1604
  # @return [void]
1602
1605
  #
1603
1606
  # @example