openhab-scripting 5.6.1 → 5.7.0

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: 86b3b636fb3b4c119d2ed6a5d6b81bedd731456c750d28f4e16f602d75778e7c
4
+ data.tar.gz: 673ed9dc1dfba2e38e1a57b01468c3a6d74a3a3fd0141c5bd9f51bc25d84e634
5
5
  SHA512:
6
- metadata.gz: 454fb750a412b8e153ce7df0320738b1f9729e1313d6d8e9aaaaa7c720c8c0cda7f704a35d78952705e7f21718551daae2c01e0dcf0b7e26c1fbfa2481d5ab6b
7
- data.tar.gz: 0a1e62ecb2bcce48a207bed5899bd0e7913492836a5c953a4b22756fa149b353ee8db229e3b5b71f48d503db1d7bfaa4f8baa94abe92469047b386ab3d438da6
6
+ metadata.gz: 5974cf573c9fe03b1cd8df81cd312a6be70e3175c1a157d19db5dee17db2ecf8afae6619b5a3f81f91a2fce1834c7c24f7fbc7a6bf3166e60106050892d4f9ca
7
+ data.tar.gz: 9cced687ace50ae3bcab50ee9ad421e9bd34cabf5338b7d927c4415f540148bf2f8033f8e72b43814a0b8a94ad399b3119a3b3ea953a1215fbc8be3e915a77f5
@@ -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: MainFloorThermostate_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: BasementThermostate_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
@@ -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
@@ -0,0 +1,942 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ #
6
+ # Contains the various builders for sitemap elements.
7
+ #
8
+ module Sitemaps
9
+ # @!visibility private
10
+ org.openhab.core.model.sitemap.sitemap.impl.SitemapImpl.alias_method :uid, :name
11
+
12
+ # Base sitemap builder DSL
13
+ class Builder
14
+ # @!visibility private
15
+ def initialize(provider)
16
+ @provider = provider
17
+ end
18
+
19
+ # (see SitemapBuilder#initialize)
20
+ # @yield Block executed in the context of a {SitemapBuilder}
21
+ # @return [SitemapBuilder]
22
+ # @!visibility public
23
+ def sitemap(name, label = nil, icon: nil, &block)
24
+ sitemap = SitemapBuilder.new(name, label, icon: icon)
25
+ sitemap.instance_eval_with_dummy_items(&block) if block
26
+ @provider.add(sitemap.build)
27
+ sitemap
28
+ end
29
+ end
30
+
31
+ # Base class for all widgets
32
+ # @see org.openhab.core.model.sitemap.sitemap.Widget
33
+ class WidgetBuilder
34
+ # rubocop:disable Layout/LineLength, Lint/MixedRegexpCaptureTypes
35
+ # These are copied directly out of UIComponentSitemapProvider.java
36
+ VISIBILITY_PATTERN = /(?<item>[A-Za-z]\w*)\s*(?<condition>==|!=|<=|>=|<|>)\s*(?<sign>\+|-)?(?<state>\S+)/.freeze
37
+ COLOR_PATTERN = /((?<item>[A-Za-z]\w*)?\s*((?<condition>==|!=|<=|>=|<|>)\s*(?<sign>\+|-)?(?<state>\S+))?\s*=)?\s*(?<arg>\S+)/.freeze
38
+ # rubocop:enable Layout/LineLength, Lint/MixedRegexpCaptureTypes
39
+ private_constant :VISIBILITY_PATTERN, :COLOR_PATTERN
40
+
41
+ # @return [String, nil]
42
+ attr_accessor :label
43
+ # The item whose state to show
44
+ # @return [String, Core::Items::Item, nil]
45
+ attr_accessor :item
46
+ # @return [String, nil]
47
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#icons
48
+ attr_accessor :icon
49
+ # Label color rules
50
+ # @return [Array<String>]
51
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#label-value-and-icon-colors
52
+ attr_reader :label_colors
53
+ # Value color rules
54
+ # @return [Array<String>]
55
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#label-value-and-icon-colors
56
+ attr_reader :value_colors
57
+ # Icon color rules
58
+ # @return [Array<String>]
59
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#label-value-and-icon-colors
60
+ attr_reader :icon_colors
61
+ # Visibility rules
62
+ # @return [Array<String>]
63
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#visibility
64
+ attr_reader :visibilities
65
+
66
+ # @param item [String, Core::Items::Item, nil] The item whose state to show (see {#item})
67
+ # @param label [String, nil] (see {#label})
68
+ # @param icon [String, nil] (see {#icon})
69
+ # @param label_color [String, Array<String>, nil] One or more label color rules (see {#label_color})
70
+ # @param value_color [String, Array<String>, nil] One or more value color rules (see {#value_color})
71
+ # @param icon_color [String, Array<String>, nil] One or more icon color rules (see {#icon_color})
72
+ # @param visibility [String, Array<String>, nil] One or more visibility rules (see {#visibility})
73
+ # @!visibility private
74
+ def initialize(type,
75
+ item: nil,
76
+ label: nil,
77
+ icon: nil,
78
+ label_color: nil,
79
+ value_color: nil,
80
+ icon_color: nil,
81
+ visibility: nil)
82
+ unless SitemapBuilder.factory.respond_to?("create_#{type}")
83
+ raise ArgumentError,
84
+ "#{type} is not a valid widget type"
85
+ end
86
+
87
+ @type = type
88
+ @item = item
89
+ @label = label
90
+ @icon = icon
91
+ @visibilities = []
92
+ @label_colors = []
93
+ @value_colors = []
94
+ @icon_colors = []
95
+
96
+ self.label_color(*label_color) if label_color
97
+ self.value_color(*value_color) if value_color
98
+ self.icon_color(*icon_color) if icon_color
99
+ self.visibility(*visibility) if visibility
100
+ end
101
+
102
+ # Adds one or more new rules for setting the label color
103
+ # @return [Array<String>] the current rules
104
+ def label_color(*rules)
105
+ @label_colors.concat(rules)
106
+ end
107
+
108
+ # Adds one or more new rules for setting the value color
109
+ # @return [Array<String>] the current rules
110
+ def value_color(*rules)
111
+ @value_colors.concat(rules)
112
+ end
113
+
114
+ # Adds one or more new rules for setting the icon color
115
+ # @return [Array<String>] the current rules
116
+ def icon_color(*rules)
117
+ @icon_colors.concat(rules)
118
+ end
119
+
120
+ # Adds one or more new visibility rules
121
+ # @return [Array<String>] the current rules
122
+ def visibility(*rules)
123
+ @visibilities.concat(rules)
124
+ end
125
+
126
+ # @!visibility private
127
+ def build
128
+ widget = SitemapBuilder.factory.send("create_#{@type}")
129
+ item = @item
130
+ item = item.name if item.respond_to?(:name)
131
+ widget.item = item if item
132
+ widget.label = @label
133
+ widget.icon = @icon
134
+
135
+ add_color(widget.label_color, label_colors) unless label_colors.empty?
136
+ add_color(widget.value_color, value_colors) unless value_colors.empty?
137
+ add_color(widget.icon_color, icon_colors) unless icon_colors.empty?
138
+
139
+ visibilities.each do |v|
140
+ unless (match = VISIBILITY_PATTERN.match(v))
141
+ raise ArgumentError, "Syntax error in visibility rule #{v.inspect}"
142
+ end
143
+
144
+ rule = SitemapBuilder.factory.create_visibility_rule
145
+ rule.item = match["item"]
146
+ rule.condition = match["condition"]
147
+ rule.sign = match["sign"]
148
+ rule.state = match["state"]
149
+ widget.visibility.add(rule)
150
+ end
151
+
152
+ widget
153
+ end
154
+
155
+ # @!visibility private
156
+ def inspect
157
+ s = +"#<OpenHAB::DSL::Sitemaps::#{@type.capitalize}Builder "
158
+ s << (instance_variables - [:@children]).map do |iv|
159
+ "#{iv}=#{instance_variable_get(iv).inspect}"
160
+ end.join(" ")
161
+ s << ">"
162
+ s.freeze
163
+ end
164
+
165
+ private
166
+
167
+ def add_color(widget_color, colors)
168
+ colors.each do |c|
169
+ unless (match = COLOR_PATTERN.match(c))
170
+ raise ArgumentError, "Syntax error in color rule #{c.inspect}"
171
+ end
172
+
173
+ rule = SitemapBuilder.factory.create_color_array
174
+ rule.item = match["item"]
175
+ rule.condition = match["condition"]
176
+ rule.sign = match["sign"]
177
+ rule.state = match["state"]
178
+ rule.arg = match["arg"]
179
+ widget_color.add(color)
180
+ end
181
+ end
182
+ end
183
+
184
+ # Builds a `Switch` element
185
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-switch
186
+ # @see org.openhab.core.model.sitemap.sitemap.Switch
187
+ class SwitchBuilder < WidgetBuilder
188
+ # Mappings from command to label
189
+ #
190
+ # Keys can be any {Core::Types::Command command}, values are strings.
191
+ # If an array is given, the same value is used for both command and label.
192
+ # @return [Hash, Array, nil]
193
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#mappings
194
+ attr_accessor :mappings
195
+
196
+ # (see WidgetBuilder#initialize)
197
+ # @!method initialize(item: nil, label: nil, icon: nil, mappings: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
198
+ # @param mappings [Hash, Array, nil] Mappings from command to label (see {SwitchBuilder#mappings})
199
+ # @!visibility private
200
+ def initialize(type, mappings: nil, **kwargs)
201
+ super(type, **kwargs)
202
+
203
+ @mappings = mappings
204
+ end
205
+
206
+ # @!visibility private
207
+ def build
208
+ widget = super
209
+ mappings&.each do |cmd, label|
210
+ mapping = SitemapBuilder.factory.create_mapping
211
+ mapping.cmd = cmd.to_s
212
+ mapping.label = label&.to_s || cmd.to_s
213
+ widget.mappings.add(mapping)
214
+ end
215
+ widget
216
+ end
217
+ end
218
+
219
+ # Builds a `Selection` element
220
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-selection
221
+ # @see org.openhab.core.model.sitemap.sitemap.Selection
222
+ class SelectionBuilder < SwitchBuilder
223
+ end
224
+
225
+ # Builds a `Setpoint` element
226
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-setpoint
227
+ # @see org.openhab.core.model.sitemap.sitemap.Setpoint
228
+ class SetpointBuilder < WidgetBuilder
229
+ # Allowed range of the value
230
+ # @return [Range, nil]
231
+ attr_accessor :range
232
+ # How far the value will change with each button press
233
+ # @return [Numeric, nil]
234
+ attr_accessor :step
235
+
236
+ # (see WidgetBuilder#initialize)
237
+ # @!method initialize(item: nil, label: nil, icon: nil, range: nil, step: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
238
+ # @param range [Range, nil] Allowed range of the value (see {SetpointBuilder#range})
239
+ # @param step [Numeric,nil] How far the value will change with each button press (see {SetpointBuilder#step})
240
+ # @!visibility private
241
+ def initialize(type, range: nil, step: nil, **kwargs)
242
+ super(type, **kwargs)
243
+
244
+ @range = range
245
+ @step = step
246
+ end
247
+
248
+ # @!visibility private
249
+ def build
250
+ widget = super
251
+ widget.min_value = range&.begin&.to_d
252
+ widget.max_value = range&.end&.to_d
253
+ widget.step = step&.to_d
254
+ widget
255
+ end
256
+ end
257
+
258
+ # Builds a `Slider` element
259
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-slider
260
+ # @see org.openhab.core.model.sitemap.sitemap.Slider
261
+ class SliderBuilder < SetpointBuilder
262
+ # How often to send requests (in seconds)
263
+ # @return [Numeric, nil]
264
+ attr_accessor :frequency
265
+ # A short press on the item toggles the item on or off
266
+ # @return [true, false, nil]
267
+ # @note This parameter only works on Android
268
+ attr_writer :switch
269
+
270
+ # (see SetpointBuilder#initialize)
271
+ # @!method initialize(item: nil, label: nil, icon: nil, range: nil, step: nil, switch: nil, frequency: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
272
+ # @param switch [true, false, nil]
273
+ # A short press on the item toggles the item on or off (see {SliderBuilder#switch=})
274
+ # @param frequency [Numeric, nil]
275
+ # How often to send requests (in seconds) (see {SliderBuilder#frequency})
276
+ # @!visibility private
277
+ def initialize(type, switch: nil, frequency: nil, **kwargs)
278
+ super(type, **kwargs)
279
+
280
+ @switch = switch
281
+ @frequency = frequency
282
+ end
283
+
284
+ # (see #switch=)
285
+ def switch?
286
+ @switch_enabled
287
+ end
288
+
289
+ # @!visibility private
290
+ def build
291
+ widget = super
292
+ widget.switch_enabled = switch?
293
+ widget.send_frequency = (frequency * 1000).to_i if frequency
294
+ widget
295
+ end
296
+ end
297
+
298
+ # Builds a `Video` element
299
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-video
300
+ # @see org.openhab.core.model.sitemap.sitemap.Video
301
+ class VideoBuilder < WidgetBuilder
302
+ # Valid {#encoding} values
303
+ VALID_ENCODINGS = %i[mjpeg hls].freeze
304
+
305
+ # @return [String, nil]
306
+ attr_accessor :url
307
+ # @return [:mjpeg, :hls, nil]
308
+ attr_reader :encoding
309
+
310
+ # (see WidgetBuilder#initialize)
311
+ # @!method initialize(item: nil, label: nil, icon: nil, url: nil, encoding: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
312
+ # @param [String, nil] url (see {VideoBuilder#url})
313
+ # @param [:mjpeg, :hls, nil] encoding (see {VideoBuilder#encoding})
314
+ # @!visibility private
315
+ def initialize(type, url: nil, encoding: nil, **kwargs)
316
+ super(type, **kwargs)
317
+
318
+ @url = url
319
+ self.encoding = encoding
320
+ end
321
+
322
+ def encoding=(value)
323
+ raise ArgumentError, "#{value} is not a valid encoding" if value && !VALID_ENCODINGS.include?(value)
324
+
325
+ @encoding = value
326
+ end
327
+
328
+ # @!visibility private
329
+ def build
330
+ widget = super
331
+ widget.url = url
332
+ widget.encoding = encoding&.to_s
333
+ widget
334
+ end
335
+ end
336
+
337
+ # Builds a `Chart` element
338
+ # See https://www.openhab.org/docs/ui/sitemaps.html#element-type-chart
339
+ # @see org.openhab.core.model.sitemap.sitemap.Chart
340
+ class ChartBuilder < WidgetBuilder
341
+ # Valid {#period} values
342
+ VALID_PERIODS = %i[h 4h 8h 12h D 2D 3D W 2W M 2M 4M Y].freeze
343
+
344
+ # The persistence service to use
345
+ # @return [String, nil]
346
+ attr_accessor :service
347
+ # How often to refresh the chart (in seconds)
348
+ # @return [Numeric, nil]
349
+ attr_accessor :refresh
350
+ # Time axis scale
351
+ # @return [:h, :"4h", :"8h", :"12h", :D, :"2D", :"3D", :W, :"2W", :M, :"2M", :"4M", :Y, nil]
352
+ attr_reader :period
353
+ # Always show the legend, never show the legend, or automatically show
354
+ # the legend if there is more than one series in the chart.
355
+ # @return [true, false, nil]
356
+ attr_writer :legend
357
+ # Show the value of a {Core::Items::GroupItem GroupItem} instead of
358
+ # showing a graph for each member (which is the default).
359
+ # @return [true, false, nil]
360
+ attr_writer :group
361
+ # Formatting string for values on the y axis.
362
+ # @return [String, nil]
363
+ # @example
364
+ # "#.##" # => formats a number with two decimals.
365
+ # @see https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/DecimalFormat.html DecimalFormat
366
+ attr_accessor :y_axis_pattern
367
+
368
+ # (see WidgetBuilder#initialize)
369
+ # @!method initialize(item: nil, label: nil, icon: nil, service: nil, refresh: nil, period: nil, legend: nil, group: nil, y_axis_pattern: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
370
+ # @param service [String, nil]
371
+ # The persistence service to use (see {ChartBuilder#service})
372
+ # @param refresh [Numeric, nil)]
373
+ # How often to refresh the chart (in seconds) (see {ChartBuilder#refresh})
374
+ # @param period [:h, :"4h", :"8h", :"12h", :D, :"2D", :"3D", :W, :"2W", :M, :"2M", :"4M", :Y, nil]
375
+ # Time axis scale (see {ChartBuilder#period})
376
+ # @param legend [true, false, nil]
377
+ # Always show the legend (see {ChartBuilder#legend=})
378
+ # @param group [true, false, nil]
379
+ # Show the value of a group item, instead of its members (see {ChartBuilder#group=})
380
+ # @param y_axis_pattern [String, nil]
381
+ # Formatting string for values on the y axis (see {ChartBuilder#y_axis_pattern})
382
+ # @!visibility private
383
+ def initialize(type,
384
+ service: nil,
385
+ refresh: nil,
386
+ period: nil,
387
+ legend: nil,
388
+ group: nil,
389
+ y_axis_pattern: nil,
390
+ **kwargs)
391
+ super(type, **kwargs)
392
+
393
+ @service = service
394
+ self.refresh = refresh
395
+ @period = period
396
+ @legend = legend
397
+ @group = group
398
+ @y_axis_pattern = y_axis_pattern
399
+ end
400
+
401
+ def period=(value)
402
+ value = value&.to_sym
403
+ raise ArgumentError, "#{value} is not a valid period" if value && !VALID_PERIODS.include?(value)
404
+
405
+ @period = value
406
+ end
407
+
408
+ # (see #legend=)
409
+ def legend?
410
+ @legend
411
+ end
412
+
413
+ # (see #group=)
414
+ def group?
415
+ @group
416
+ end
417
+
418
+ # @!visibility private
419
+ def build
420
+ widget = super
421
+ widget.service = service
422
+ widget.period = period&.to_s
423
+ widget.legend = legend?
424
+ widget.force_as_item = group?
425
+ widget.yaxis_decimal_pattern = y_axis_pattern
426
+ widget
427
+ end
428
+ end
429
+
430
+ # Builds a `Default` element
431
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-default
432
+ # @see org.openhab.core.model.sitemap.sitemap.Default
433
+ class DefaultBuilder < WidgetBuilder
434
+ # @return [Integer] The number of element rows to fill
435
+ attr_accessor :height
436
+
437
+ # (see WidgetBuilder#initialize)
438
+ # @!method initialize(item: nil, label: nil, icon: nil, height: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
439
+ # @param height [Integer] The number of element rows to fill (see {DefaultBuilder#height})
440
+ # @!visibility private
441
+ def initialize(type, height: nil, **kwargs)
442
+ super(type, **kwargs)
443
+
444
+ @height = height
445
+ end
446
+
447
+ # @!visibility private
448
+ def build
449
+ widget = super
450
+ widget.height = height
451
+ widget
452
+ end
453
+ end
454
+
455
+ # Builds a `Webview` element
456
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-webview
457
+ # @see org.openhab.core.model.sitemap.sitemap.Webview
458
+ class WebviewBuilder < DefaultBuilder
459
+ # @return [String, nil]
460
+ attr_accessor :url
461
+
462
+ # (see DefaultBuilder#initialize)
463
+ # @!method initialize(item: nil, label: nil, icon: nil, url: nil, height: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
464
+ # @param url [String, nil] (see {WebviewBuilder#url})
465
+ # @!visibility private
466
+ def initialize(type, url: nil, **kwargs)
467
+ super(type, **kwargs)
468
+
469
+ @url = url
470
+ end
471
+
472
+ # @!visibility private
473
+ def build
474
+ widget = super
475
+ widget.url = url
476
+ widget
477
+ end
478
+ end
479
+
480
+ # Builds a `Colorpicker` element
481
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-colorpicker
482
+ # @see org.openhab.core.model.sitemap.sitemap.Colorpicker
483
+ class ColorpickerBuilder < WidgetBuilder
484
+ # @return [Numeric, nil]
485
+ # How often to send requests (in seconds)
486
+ attr_accessor :frequency
487
+
488
+ # (see WidgetBuilder#initialize)
489
+ # @!method initialize(item: nil, label: nil, icon: nil, frequency: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
490
+ # @param frequency [Numeric, nil] How often to send requests (see {ColorpickerBuilder#frequency})
491
+ # @!visibility private
492
+ def initialize(type, frequency: nil, **kwargs)
493
+ super(type, **kwargs)
494
+
495
+ @frequency = frequency
496
+ end
497
+
498
+ # @!visibility private
499
+ def build
500
+ widget = super
501
+ widget.frequency = (frequency * 1000).to_i if frequency
502
+ widget
503
+ end
504
+ end
505
+
506
+ # Builds a `Mapview` element
507
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-mapview
508
+ # @see org.openhab.core.model.sitemap.sitemap.Mapview
509
+ class MapviewBuilder < DefaultBuilder
510
+ end
511
+
512
+ # Builds an `Input` element
513
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-input
514
+ # @see org.openhab.core.model.sitemap.sitemap.Input
515
+ class InputBuilder < WidgetBuilder
516
+ # Valid {#hint} values
517
+ VALID_HINTS = %i[text number date time datetime].freeze
518
+
519
+ # @return [:text, :number, :date, :time, :datetime, nil]
520
+ # Gives a hint to the user interface to use a widget adapted to a specific use
521
+ attr_reader :hint
522
+
523
+ # (see WidgetBuilder#initialize)
524
+ # @!method initialize(item: nil, label: nil, icon: nil, hint: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
525
+ # @param [:text, :number, :date, :time, :datetime, nil] hint
526
+ # Gives a hint to the user interface to use a widget adapted to a specific use (see {InputBuilder#hint})
527
+ # @!visibility private
528
+ def initialize(type, hint: nil, **kwargs)
529
+ super(type, **kwargs)
530
+
531
+ self.hint = hint
532
+ end
533
+
534
+ def hint=(value)
535
+ value = value&.to_sym
536
+ raise ArgumentError, "#{value.inspect} is not a valid hint" if value && !VALID_HINTS.include?(value)
537
+
538
+ @hint = value
539
+ end
540
+
541
+ # @!visibility private
542
+ def build
543
+ widget = super
544
+ widget.input_hint = hint&.to_s
545
+ widget
546
+ end
547
+ end
548
+
549
+ # Parent class for builders of widgets that can contain other widgets.
550
+ # @see org.openhab.core.model.sitemap.sitemap.LinkableWidget
551
+ class LinkableWidgetBuilder < WidgetBuilder
552
+ include Core::EntityLookup
553
+
554
+ # allow referring to items that don't exist yet
555
+ self.create_dummy_items = true
556
+
557
+ # @return [Array<WidgetBuilder>]
558
+ # @!visibility private
559
+ attr_reader :children
560
+
561
+ # @!parse
562
+ # # (see WidgetBuilder#initialize)
563
+ # # Create a new `Frame` element.
564
+ # # @yield Block executed in the context of a {FrameBuilder}
565
+ # # @return [FrameBuilder]
566
+ # # @!visibility public
567
+ # def frame(item: nil,
568
+ # label: nil,
569
+ # icon: nil,
570
+ # label_color: nil,
571
+ # value_color: nil,
572
+ # icon_color: nil,
573
+ # visibility: nil)
574
+ # end
575
+ #
576
+ # # (see WidgetBuilder#initialize)
577
+ # # Create a new `Text` element.
578
+ # # @yield Block executed in the context of a {TextBuilder}
579
+ # # @return [TextBuilder]
580
+ # # @!visibility public
581
+ # def text(item: nil,
582
+ # label: nil,
583
+ # icon: nil,
584
+ # label_color: nil,
585
+ # value_color: nil,
586
+ # icon_color: nil,
587
+ # visibility: nil)
588
+ # end
589
+ #
590
+ # # (see WidgetBuilder#initialize)
591
+ # # Create a new `Group` element.
592
+ # # @yield Block executed in the context of a {GroupBuilder}
593
+ # # @return [GroupBuilder]
594
+ # # @!visibility public
595
+ # def group(item: nil,
596
+ # label: nil,
597
+ # icon: nil,
598
+ # label_color: nil,
599
+ # value_color: nil,
600
+ # icon_color: nil,
601
+ # visibility: nil)
602
+ # end
603
+ #
604
+ # # (see ImageBuilder#initialize)
605
+ # # Create a new `Image` element.
606
+ # # @yield Block executed in the context of an {ImageBuilder}
607
+ # # @return [ImageBuilder]
608
+ # # @!visibility public
609
+ # def image(item: nil,
610
+ # label: nil,
611
+ # icon: nil,
612
+ # url: nil,
613
+ # refresh: nil,
614
+ # label_color: nil,
615
+ # value_color: nil,
616
+ # icon_color: nil,
617
+ # visibility: nil)
618
+ # end
619
+ #
620
+ # # (see VideoBuilder#initialize)
621
+ # # Create a new `Video` element.
622
+ # # @yield Block executed in the context of a {VideoBuilder}
623
+ # # @return [VideoBuilder]
624
+ # # @!visibility public
625
+ # def video(item: nil,
626
+ # label: nil,
627
+ # icon: nil,
628
+ # url: nil,
629
+ # encoding: nil,
630
+ # label_color: nil,
631
+ # value_color: nil,
632
+ # icon_color: nil,
633
+ # visibility: nil)
634
+ # end
635
+ #
636
+ # # (see ChartBuilder#initialize)
637
+ # # Create a new `Chart` element.
638
+ # # @yield Block executed in the context of a {ChartBuilder}
639
+ # # @return [ChartBuilder]
640
+ # # @!visibility public
641
+ # def chart(item: nil,
642
+ # label: nil,
643
+ # icon: nil,
644
+ # service: nil,
645
+ # refresh: nil,
646
+ # period: nil,
647
+ # legend: nil,
648
+ # group: nil,
649
+ # y_axis_pattern: nil,
650
+ # label_color: nil,
651
+ # value_color: nil,
652
+ # icon_color: nil,
653
+ # visibility: nil)
654
+ # end
655
+ #
656
+ # # (see WebviewBuilder#initialize)
657
+ # # Create a new `Webview` element.
658
+ # # @yield Block executed in the context of a {WebviewBuilder}
659
+ # # @return [WebviewBuilder]
660
+ # # @!visibility public
661
+ # def webview(item: nil,
662
+ # label: nil,
663
+ # icon: nil,
664
+ # url: nil,
665
+ # height: nil,
666
+ # label_color: nil,
667
+ # value_color: nil,
668
+ # icon_color: nil,
669
+ # visibility: nil)
670
+ # end
671
+ #
672
+ # # (see SwitchBuilder#initialize)
673
+ # # Create a new `Switch` element.
674
+ # # @yield Block executed in the context of a {SwitchBuilder}
675
+ # # @return [SwitchBuilder]
676
+ # # @!visibility public
677
+ # def switch(item: nil,
678
+ # label: nil,
679
+ # icon: nil,
680
+ # mappings: nil,
681
+ # label_color: nil,
682
+ # value_color: nil,
683
+ # icon_color: nil,
684
+ # visibility: nil)
685
+ # end
686
+ #
687
+ # # (see MapviewBuilder#initialize)
688
+ # # Create a new `Mapview` element.
689
+ # # @yield Block executed in the context of a {MapviewBuilder}
690
+ # # @return [MapviewBuilder]
691
+ # # @!visibility public
692
+ # def mapview(item: nil,
693
+ # label: nil,
694
+ # icon: nil,
695
+ # height: nil,
696
+ # label_color: nil,
697
+ # value_color: nil,
698
+ # icon_color: nil,
699
+ # visibility: nil)
700
+ # end
701
+ #
702
+ # # (see SliderBuilder#initialize)
703
+ # # Create a new `Slider` element.
704
+ # # @yield Block executed in the context of a {SliderBuilder}
705
+ # # @return [SliderBuilder]
706
+ # # @!visibility public
707
+ # def slider(item: nil,
708
+ # label: nil,
709
+ # icon: nil,
710
+ # range: nil,
711
+ # step: nil,
712
+ # switch: nil,
713
+ # frequency: nil,
714
+ # label_color: nil,
715
+ # value_color: nil,
716
+ # icon_color: nil,
717
+ # visibility: nil)
718
+ # end
719
+ #
720
+ # # (see SelectionBuilder#initialize)
721
+ # # Create a new `Selection` element.
722
+ # # @yield Block executed in the context of a {SelectionBuilder}
723
+ # # @return [SelectionBuilder]
724
+ # # @!visibility public
725
+ # def selection(item: nil,
726
+ # label: nil,
727
+ # icon: nil,
728
+ # mappings: nil,
729
+ # label_color: nil,
730
+ # value_color: nil,
731
+ # icon_color: nil,
732
+ # visibility: nil)
733
+ # end
734
+ #
735
+ # # (see InputBuilder#initialize)
736
+ # # Create a new `Input` element.
737
+ # # @yield Block executed in the context of an {InputBuilder}
738
+ # # @return [InputBuilder]
739
+ # # @since openHAB 4.0
740
+ # # @!visibility public
741
+ # def input(item: nil,
742
+ # label: nil,
743
+ # icon: nil,
744
+ # hint: nil,
745
+ # label_color: nil,
746
+ # value_color: nil,
747
+ # icon_color: nil,
748
+ # visibility: nil)
749
+ # end
750
+ #
751
+ # # (see SetpointBuilder#initialize)
752
+ # # Create a new `Setpoint` element.
753
+ # # @yield Block executed in the context of a {SetpointBuilder}
754
+ # # @return [SetpointBuilder]
755
+ # # @!visibility public
756
+ # def setpoint(item: nil,
757
+ # label: nil,
758
+ # icon: nil,
759
+ # range: nil,
760
+ # step: nil,
761
+ # label_color: nil,
762
+ # value_color: nil,
763
+ # icon_color: nil,
764
+ # visibility: nil)
765
+ # end
766
+ #
767
+ # # (see ColorpickerBuilder#initialize)
768
+ # # Create a new `Colorpicker` element.
769
+ # # @yield Block executed in the context of a {ColorpickerBuilder}
770
+ # # @return [ColorpickerBuilder]
771
+ # # @!visibility public
772
+ # def colorpicker(item: nil,
773
+ # label: nil,
774
+ # icon: nil,
775
+ # frequency: nil,
776
+ # label_color: nil,
777
+ # value_color: nil,
778
+ # icon_color: nil,
779
+ # visibility: nil)
780
+ # end
781
+ #
782
+ # # (see DefaultBuilder#initialize)
783
+ # # Create a new `Default` element.
784
+ # # @yield Block executed in the context of a {DefaultBuilder}
785
+ # # @return [DefaultBuilder]
786
+ # # @!visibility public
787
+ # def default(item: nil,
788
+ # label: nil,
789
+ # icon: nil,
790
+ # height: nil,
791
+ # label_color: nil,
792
+ # value_color: nil,
793
+ # icon_color: nil,
794
+ # visibility: nil)
795
+ # end
796
+ #
797
+
798
+ %i[frame
799
+ text
800
+ group
801
+ image
802
+ video
803
+ chart
804
+ webview
805
+ switch
806
+ mapview
807
+ slider
808
+ selection
809
+ input
810
+ setpoint
811
+ colorpicker
812
+ default].each do |method|
813
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
814
+ def #{method}(*args, **kwargs, &block) # def frame(*args, **kwargs, &block)
815
+ widget = #{method.capitalize}Builder.new(#{method.inspect}, # widget = FrameBuilder.new(:frame,
816
+ *args, # *args,
817
+ **kwargs) # **kwargs)
818
+ widget.instance_eval_with_dummy_items(&block) if block # widget.instance_eval_with_dummy_items(&block) if block
819
+ children << widget # children << widget
820
+ widget # widget
821
+ end # end
822
+ RUBY
823
+ end
824
+
825
+ # (see WidgetBuilder#initialize)
826
+ # @!method initialize(item: nil, label: nil, icon: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
827
+ # @!visibility private
828
+ def initialize(*, **)
829
+ super
830
+
831
+ @children = []
832
+ end
833
+
834
+ # @!visibility private
835
+ def build
836
+ widget = super
837
+
838
+ children.each do |child|
839
+ widget.children.add(child.build)
840
+ end
841
+
842
+ widget
843
+ end
844
+ end
845
+
846
+ # Builds a `Text` element
847
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-text
848
+ # @see org.openhab.core.model.sitemap.sitemap.Text
849
+ class TextBuilder < LinkableWidgetBuilder
850
+ end
851
+
852
+ # Builds a `Group` element
853
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-group
854
+ # @see org.openhab.core.model.sitemap.sitemap.Group
855
+ class GroupBuilder < LinkableWidgetBuilder
856
+ end
857
+
858
+ # Builds an `Image` element
859
+ #
860
+ # {WidgetBuilder#item item} can refer to either an
861
+ # {Core::Items::ImageItem ImageItem} whose state is the raw data of the
862
+ # image, or a {Core::Items::StringItem StringItem} whose state is a URL
863
+ # that points to an image.
864
+ #
865
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-image
866
+ # @see org.openhab.core.model.sitemap.sitemap.Image
867
+ class ImageBuilder < LinkableWidgetBuilder
868
+ # @return [String, nil]
869
+ # The default URL for the image, if there is no associated item, or
870
+ # if the associated item's state is not a URL
871
+ attr_accessor :url
872
+ # @return [Numeric, nil] How often to refresh the image (in seconds)
873
+ attr_accessor :refresh
874
+
875
+ # (see LinkableWidgetBuilder#initialize)
876
+ # @!method initialize(item: nil, label: nil, icon: nil, url: nil, refresh: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
877
+ # @param url [String, nil] The URL for the image (see {ImageBuilder#url})
878
+ # @param refresh [Numeric, nil] How often to refresh the image (see {ImageBuilder#refresh})
879
+ # @!visibility private
880
+ def initialize(type, url: nil, refresh: nil, **kwargs)
881
+ super(type, **kwargs)
882
+
883
+ @url = url
884
+ @refresh = refresh
885
+ end
886
+
887
+ # @!visibility private
888
+ def build
889
+ widget = super
890
+ widget.url = url
891
+ widget.refresh = (refresh * 1_000).to_i if refresh
892
+ widget
893
+ end
894
+ end
895
+
896
+ # Builds a `Frame` element
897
+ # @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-frame
898
+ # @see org.openhab.core.model.sitemap.sitemap.Frame
899
+ class FrameBuilder < LinkableWidgetBuilder
900
+ end
901
+
902
+ # Builds a `Sitemap`
903
+ # @see https://www.openhab.org/docs/ui/sitemaps.html
904
+ # @see org.openhab.core.model.sitemap.sitemap.Sitemap
905
+ class SitemapBuilder < LinkableWidgetBuilder
906
+ class << self
907
+ # @!visibility private
908
+ def factory
909
+ org.openhab.core.model.sitemap.sitemap.SitemapFactory.eINSTANCE
910
+ end
911
+ end
912
+
913
+ # @return [String]
914
+ attr_accessor :name
915
+
916
+ private :label_colors, :value_colors, :icon_colors, :visibilities
917
+
918
+ undef_method :item, :item=
919
+ undef_method :label_color
920
+ undef_method :value_color
921
+ undef_method :icon_color
922
+ undef_method :visibility
923
+ undef_method :method_missing, :respond_to_missing?
924
+
925
+ # @param name [String]
926
+ # @param label [String, nil]
927
+ # @param icon [String, nil]
928
+ # @!visibility private
929
+ def initialize(name, label = nil, icon: nil)
930
+ super(:sitemap, label: label, icon: icon)
931
+
932
+ @name = name
933
+ end
934
+
935
+ # @!visibility private
936
+ def build
937
+ super.tap { |sitemap| sitemap.name = name }
938
+ end
939
+ end
940
+ end
941
+ end
942
+ end
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.6.1"
7
+ VERSION = "5.7.0"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -214,6 +214,11 @@ module OpenHAB
214
214
  Core::Items::Registry.instance
215
215
  end
216
216
 
217
+ # @return [Core::Sitemaps::Provider]
218
+ def sitemaps
219
+ Core::Sitemaps::Provider.instance
220
+ end
221
+
217
222
  #
218
223
  # Get all things known to openHAB
219
224
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.1
4
+ version: 5.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-09-12 00:00:00.000000000 Z
13
+ date: 2023-09-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -442,6 +442,7 @@ files:
442
442
  - lib/openhab/core/rules/rule.rb
443
443
  - lib/openhab/core/rules/tagged_array.rb
444
444
  - lib/openhab/core/script_handling.rb
445
+ - lib/openhab/core/sitemaps/provider.rb
445
446
  - lib/openhab/core/things.rb
446
447
  - lib/openhab/core/things/channel.rb
447
448
  - lib/openhab/core/things/channel_uid.rb
@@ -530,6 +531,7 @@ files:
530
531
  - lib/openhab/dsl/rules/triggers/trigger.rb
531
532
  - lib/openhab/dsl/rules/triggers/updated.rb
532
533
  - lib/openhab/dsl/rules/triggers/watch/watch_handler.rb
534
+ - lib/openhab/dsl/sitemaps/builder.rb
533
535
  - lib/openhab/dsl/things/builder.rb
534
536
  - lib/openhab/dsl/thread_local.rb
535
537
  - lib/openhab/dsl/timer_manager.rb