openhab-scripting 5.6.1 → 5.7.1

Sign up to get free protection for your applications and to get access to all the features.
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