openhab-scripting 5.22.1 → 5.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openhab/core/actions/notification.rb +7 -2
- data/lib/openhab/core/items/group_item.rb +1 -1
- data/lib/openhab/core/types/time_series.rb +57 -16
- data/lib/openhab/dsl/items/timed_command.rb +51 -8
- data/lib/openhab/dsl/rules/builder.rb +32 -6
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +41 -13
- data/lib/openhab/dsl/sitemaps/builder.rb +304 -72
- data/lib/openhab/dsl/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55ff8734004f7befde1f1d3bb27560cfc8c5dbb7287f8dbb5e19a50fadec0d23
|
4
|
+
data.tar.gz: dba9276e8b4845e1b265973440aa0e036da3137176ba44c5c256ddfcd5dad227
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c4692d9a8ce6104b511e1475e01fcae49f0fda6bdf04f498c26b023237f8332e87166cbdc5e2754f1375b4e2cbf31f70c706e68beda3657d6f09b28d37b59bf
|
7
|
+
data.tar.gz: 133e78f26b440c5ffbb628ee323d56d2e4b4e74c1a65762cec75818f7ebfe5eeda4275e7cd6157fb68d90d551c5e2b4c984016c149abf222dc1917428f4c7e49
|
@@ -29,8 +29,11 @@ module OpenHAB
|
|
29
29
|
# @param on_click [String, nil] The action to be performed when the user clicks on the notification.
|
30
30
|
# Specified using the {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax
|
31
31
|
# action syntax}.
|
32
|
-
# @param attachment [String, nil] The URL of the media attachment to be displayed with the notification.
|
33
|
-
# This
|
32
|
+
# @param attachment [String, Item, nil] The URL of the media attachment to be displayed with the notification.
|
33
|
+
# This can either be a fully qualified URL, prefixed with
|
34
|
+
# `http://` or `https://` and reachable by the client device,
|
35
|
+
# a relative path on the user's openHAB instance starting with `/`,
|
36
|
+
# or an image item.
|
34
37
|
# @param buttons [Array<String>, Hash<String, String>, nil] Buttons to include in the notification.
|
35
38
|
# - In array form, each element is specified as `Title=$action`, where `$action` follows the
|
36
39
|
# {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax action syntax}.
|
@@ -94,6 +97,8 @@ module OpenHAB
|
|
94
97
|
buttons = buttons.map { |title, action| "#{title}=#{action}" } if buttons.is_a?(Hash)
|
95
98
|
raise ArgumentError, "buttons must contain (0..3) elements." unless (0..3).cover?(buttons.size)
|
96
99
|
|
100
|
+
attachment = "item:#{attachment.name}" if attachment.is_a?(Item) && attachment.image_item?
|
101
|
+
|
97
102
|
args.push(title&.to_s,
|
98
103
|
id&.to_s,
|
99
104
|
on_click&.to_s,
|
@@ -146,7 +146,7 @@ module OpenHAB
|
|
146
146
|
base_item.format_type(command)
|
147
147
|
end
|
148
148
|
|
149
|
-
%w[color contact date_time dimmer image location number player rollershutter string switch].each do |type|
|
149
|
+
%w[call color contact date_time dimmer image location number player rollershutter string switch].each do |type|
|
150
150
|
type_class = type.gsub(/(^[a-z]|_[a-z])/) { |letter| letter[-1].upcase }
|
151
151
|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
152
152
|
def #{type}_item? # def date_time_item?
|
@@ -4,6 +4,7 @@
|
|
4
4
|
return unless OpenHAB::Core.version >= OpenHAB::Core::V4_1
|
5
5
|
|
6
6
|
require "forwardable"
|
7
|
+
require "openhab/core/lazy_array"
|
7
8
|
|
8
9
|
module OpenHAB
|
9
10
|
module Core
|
@@ -30,7 +31,7 @@ module OpenHAB
|
|
30
31
|
# @see DSL::Rules::BuilderDSL#time_series_updated #time_series_updated rule trigger
|
31
32
|
#
|
32
33
|
class TimeSeries
|
33
|
-
|
34
|
+
include LazyArray
|
34
35
|
|
35
36
|
# @!attribute [r] policy
|
36
37
|
# Returns the persistence policy of this series.
|
@@ -81,12 +82,19 @@ module OpenHAB
|
|
81
82
|
"size=#{size}>"
|
82
83
|
end
|
83
84
|
|
85
|
+
# Explicit conversion to Array
|
86
|
+
#
|
87
|
+
# @return [Array]
|
88
|
+
def to_a
|
89
|
+
get_states.to_array.to_a.freeze
|
90
|
+
end
|
91
|
+
|
84
92
|
#
|
85
93
|
# Returns the content of this series.
|
86
94
|
# @return [Array<org.openhab.core.types.TimeSeries.Entry>]
|
87
95
|
#
|
88
96
|
def states
|
89
|
-
|
97
|
+
to_a
|
90
98
|
end
|
91
99
|
|
92
100
|
# rename raw methods so we can overwrite them
|
@@ -100,29 +108,62 @@ module OpenHAB
|
|
100
108
|
#
|
101
109
|
# @note This method returns self so it can be chained, unlike the Java version.
|
102
110
|
#
|
103
|
-
# @param [Instant, #to_zoned_date_time, #to_instant]
|
111
|
+
# @param [Instant, #to_zoned_date_time, #to_instant] timestamp An instant for the given state.
|
104
112
|
# @param [State, String, Numeric] state The State at the given timestamp.
|
105
113
|
# If a String is given, it will be converted to {StringType}.
|
106
114
|
# If a {Numeric} is given, it will be converted to {DecimalType}.
|
107
115
|
# @return [self]
|
108
116
|
# @raise [ArgumentError] if state is not a {State}, String or {Numeric}
|
109
117
|
#
|
110
|
-
def add(
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
when State then state
|
115
|
-
when String then StringType.new(state)
|
116
|
-
when Numeric then DecimalType.new(state)
|
117
|
-
else
|
118
|
-
raise ArgumentError, "state must be a State, String or Numeric, but was #{state.class}"
|
119
|
-
end
|
120
|
-
add_instant(instant, state)
|
118
|
+
def add(timestamp, state)
|
119
|
+
timestamp = to_instant(timestamp)
|
120
|
+
state = format_state(state)
|
121
|
+
add_instant(timestamp, state)
|
121
122
|
self
|
122
123
|
end
|
123
124
|
|
124
|
-
#
|
125
|
-
|
125
|
+
#
|
126
|
+
# Appends an entry to self, returns self
|
127
|
+
#
|
128
|
+
# @param [Array<Instant, State>] entry a two-element array with the timestamp and state.
|
129
|
+
# The timestamp can be an {Instant} or any object that responds to #to_zoned_date_time.
|
130
|
+
# @return [self]
|
131
|
+
#
|
132
|
+
# @example Append an entry
|
133
|
+
# time_series << [Time.at(2), 2]
|
134
|
+
#
|
135
|
+
def <<(entry)
|
136
|
+
raise ArgumentError, "entry must be an Array, but was #{entry.class}" unless entry.respond_to?(:to_ary)
|
137
|
+
|
138
|
+
entry = entry.to_ary
|
139
|
+
raise ArgumentError, "entry must be an Array of size 2, but was #{entry.size}" unless entry.size == 2
|
140
|
+
|
141
|
+
add(entry[0], entry[1])
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def to_instant(timestamp)
|
147
|
+
if timestamp.is_a?(Instant)
|
148
|
+
timestamp
|
149
|
+
elsif timestamp.respond_to?(:to_instant)
|
150
|
+
timestamp.to_instant
|
151
|
+
elsif timestamp.respond_to?(:to_zoned_date_time)
|
152
|
+
timestamp.to_zoned_date_time.to_instant
|
153
|
+
else
|
154
|
+
raise ArgumentError, "timestamp must be an Instant, or convertible to one, but was #{timestamp.class}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def format_state(state)
|
159
|
+
case state
|
160
|
+
when State then state
|
161
|
+
when String then StringType.new(state)
|
162
|
+
when Numeric then DecimalType.new(state)
|
163
|
+
else
|
164
|
+
raise ArgumentError, "state must be a State, String or Numeric, but was #{state.class}"
|
165
|
+
end
|
166
|
+
end
|
126
167
|
end
|
127
168
|
end
|
128
169
|
end
|
@@ -64,6 +64,29 @@ module OpenHAB
|
|
64
64
|
def cancelled?
|
65
65
|
resolution == :cancelled
|
66
66
|
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Reschedule the timed command.
|
70
|
+
#
|
71
|
+
# If the timed command was cancelled, this will also resume it.
|
72
|
+
#
|
73
|
+
# @param [java.time.temporal.TemporalAmount, #to_zoned_date_time, Proc, nil] time
|
74
|
+
# When to reschedule the timer for. If unspecified, the original time is used.
|
75
|
+
# @return [void]
|
76
|
+
#
|
77
|
+
def reschedule(time = nil)
|
78
|
+
self.resolution = nil
|
79
|
+
timer.reschedule(time)
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Resume a cancelled timed command to its original expiration time.
|
84
|
+
#
|
85
|
+
# @return [void]
|
86
|
+
#
|
87
|
+
def resume
|
88
|
+
self.resolution = nil
|
89
|
+
end
|
67
90
|
end
|
68
91
|
|
69
92
|
@timed_commands = java.util.concurrent.ConcurrentHashMap.new
|
@@ -82,7 +105,13 @@ module OpenHAB
|
|
82
105
|
#
|
83
106
|
# @note If a block is provided, and the timer is canceled because the
|
84
107
|
# item changed state while it was waiting, the block will still be
|
85
|
-
# executed.
|
108
|
+
# executed. The timed command can be reinstated by calling {TimedCommandDetails#resume #resume} or
|
109
|
+
# {TimedCommandDetails#reschedule #reschedule}.
|
110
|
+
#
|
111
|
+
# If the timer expired, the timed command can be rescheduled from inside the block by calling
|
112
|
+
# {TimedCommandDetails#reschedule #reschedule}.
|
113
|
+
#
|
114
|
+
# Be sure to check {TimedCommandDetails#expired? #expired?}
|
86
115
|
# and/or {TimedCommandDetails#cancelled? #cancelled?} to determine why
|
87
116
|
# the block was called.
|
88
117
|
#
|
@@ -181,25 +210,30 @@ module OpenHAB
|
|
181
210
|
end
|
182
211
|
|
183
212
|
# Creates the timer to handle changing the item state when timer expires or invoking user supplied block
|
184
|
-
# @param [
|
213
|
+
# @param [TimedCommandDetails] timed_command_details details about the timed command
|
185
214
|
# @return [Timer] Timer
|
186
215
|
def timed_command_timer(timed_command_details, duration)
|
187
216
|
DSL.after(duration) do
|
188
217
|
timed_command_details.mutex.synchronize do
|
189
218
|
logger.trace "Timed command expired - #{timed_command_details}"
|
190
|
-
DSL.rules.remove(timed_command_details.rule_uid)
|
191
219
|
timed_command_details.resolution = :expired
|
192
220
|
case timed_command_details.on_expire
|
193
221
|
when Proc
|
194
222
|
logger.trace "Invoking block #{timed_command_details.on_expire} after timed command for #{name} expired"
|
195
223
|
timed_command_details.on_expire.call(timed_command_details)
|
224
|
+
if timed_command_details.resolution.nil?
|
225
|
+
logger.trace { "Block rescheduled the timer to #{timed_command_details.timer.execution_time}" }
|
226
|
+
end
|
196
227
|
when Core::Types::UnDefType
|
197
228
|
update(timed_command_details.on_expire)
|
198
229
|
else
|
199
230
|
command(timed_command_details.on_expire)
|
200
231
|
end
|
232
|
+
if timed_command_details.resolution
|
233
|
+
DSL.rules.remove(timed_command_details.rule_uid)
|
234
|
+
TimedCommand.timed_commands.delete(timed_command_details.item)
|
235
|
+
end
|
201
236
|
end
|
202
|
-
TimedCommand.timed_commands.delete(timed_command_details.item)
|
203
237
|
end
|
204
238
|
end
|
205
239
|
|
@@ -250,17 +284,26 @@ module OpenHAB
|
|
250
284
|
def execute(_mod = nil, inputs = nil)
|
251
285
|
ThreadLocal.thread_local(**@thread_locals) do
|
252
286
|
@timed_command_details.mutex.synchronize do
|
253
|
-
logger.trace
|
254
|
-
|
287
|
+
logger.trace do
|
288
|
+
"Canceling implicit timer #{@timed_command_details.timer} for " \
|
289
|
+
"#{@timed_command_details.item.name} because of received event #{inputs}"
|
290
|
+
end
|
291
|
+
original_execution_time = @timed_command_details.timer.execution_time
|
255
292
|
@timed_command_details.timer.cancel
|
256
|
-
DSL.rules
|
293
|
+
DSL.rules[@timed_command_details.rule_uid].disable
|
257
294
|
@timed_command_details.resolution = :cancelled
|
258
295
|
if @timed_command_details.on_expire.is_a?(Proc)
|
259
296
|
logger.trace "Executing user supplied block on timed command cancelation"
|
260
297
|
@timed_command_details.on_expire.call(@timed_command_details)
|
261
298
|
end
|
299
|
+
if @timed_command_details.resolution
|
300
|
+
DSL.rules.remove(@timed_command_details.rule_uid)
|
301
|
+
TimedCommand.timed_commands.delete(@timed_command_details.item)
|
302
|
+
else
|
303
|
+
DSL.rules[@timed_command_details.rule_uid].enable
|
304
|
+
@timed_command_details.timer.reschedule(original_execution_time)
|
305
|
+
end
|
262
306
|
end
|
263
|
-
TimedCommand.timed_commands.delete(@timed_command_details.item)
|
264
307
|
rescue Exception => e
|
265
308
|
raise if defined?(::RSpec)
|
266
309
|
|
@@ -1278,6 +1278,8 @@ module OpenHAB
|
|
1278
1278
|
#
|
1279
1279
|
# The `event` passed to run blocks will be a {Core::Events::TimerEvent}.
|
1280
1280
|
#
|
1281
|
+
# For a more complex schedule, use {cron}.
|
1282
|
+
#
|
1281
1283
|
# @param [String,
|
1282
1284
|
# Duration,
|
1283
1285
|
# java.time.MonthDay,
|
@@ -1294,8 +1296,8 @@ module OpenHAB
|
|
1294
1296
|
# :thursday,
|
1295
1297
|
# :friday,
|
1296
1298
|
# :saturday,
|
1297
|
-
# :sunday]
|
1298
|
-
# When to execute rule.
|
1299
|
+
# :sunday] values
|
1300
|
+
# When to execute rule. Multiple day-of-week can be specified. Otherwise, only one value is allowed.
|
1299
1301
|
# @param [LocalTime, String, Core::Items::DateTimeItem, nil] at What time of day to execute rule
|
1300
1302
|
# If `value` is `:day`, `at` can be a {Core::Items::DateTimeItem DateTimeItem}, and
|
1301
1303
|
# the trigger will run every day at the (time only portion of) current state of the
|
@@ -1304,6 +1306,7 @@ module OpenHAB
|
|
1304
1306
|
# @return [void]
|
1305
1307
|
#
|
1306
1308
|
# @see at
|
1309
|
+
# @see cron
|
1307
1310
|
#
|
1308
1311
|
# @example
|
1309
1312
|
# rule "Daily" do
|
@@ -1363,15 +1366,38 @@ module OpenHAB
|
|
1363
1366
|
# run { logger.info "Happy Valentine's Day!" }
|
1364
1367
|
# end
|
1365
1368
|
#
|
1366
|
-
|
1367
|
-
|
1369
|
+
# @example Multiple day-of-week
|
1370
|
+
# rule "Weekend" do
|
1371
|
+
# every :saturday, :sunday, at: "10:00"
|
1372
|
+
# run { logger.info "It's the weekend!" }
|
1373
|
+
# end
|
1374
|
+
#
|
1375
|
+
def every(*values, at: nil, attach: nil)
|
1376
|
+
raise ArgumentError, "Missing values" if values.empty?
|
1377
|
+
|
1378
|
+
if Cron.all_dow_symbols?(values)
|
1379
|
+
@ruby_triggers << [:every, values.join(", "), { at: at }]
|
1380
|
+
return cron(Cron.from_dow_symbols(values, at), attach: attach)
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
if values.size != 1
|
1384
|
+
raise ArgumentError,
|
1385
|
+
"Multiple values are only allowed for day-of-week. " \
|
1386
|
+
"Otherwise only one value is allowed, given: #{values.size}"
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
value = values.first
|
1390
|
+
value = java.time.MonthDay.parse(value.to_str) if value.respond_to?(:to_str)
|
1368
1391
|
|
1369
1392
|
@ruby_triggers << [:every, value, { at: at }]
|
1370
1393
|
|
1371
1394
|
if value == :day && at.is_a?(Item)
|
1372
|
-
|
1395
|
+
# @!deprecated OH 3.4 - attachments are supported in OH 4.0+
|
1396
|
+
if Core.version <= Core::V4_0 && !attach.nil?
|
1397
|
+
raise ArgumentError, "Attachments are not supported with dynamic datetime triggers in openHAB 3.x"
|
1398
|
+
end
|
1373
1399
|
|
1374
|
-
return trigger("timer.DateTimeTrigger", itemName: at.name, timeOnly: true)
|
1400
|
+
return trigger("timer.DateTimeTrigger", itemName: at.name, timeOnly: true, attach: attach)
|
1375
1401
|
end
|
1376
1402
|
|
1377
1403
|
cron_expression = case value
|
@@ -50,8 +50,13 @@ module OpenHAB
|
|
50
50
|
}.freeze
|
51
51
|
private_constant :DAY_OF_WEEK_MAP
|
52
52
|
|
53
|
+
DAY_OF_WEEK = DAY_OF_WEEK_MAP.keys.freeze
|
54
|
+
private_constant :DAY_OF_WEEK
|
55
|
+
|
53
56
|
# @return [Hash] Converts the DAY_OF_WEEK_MAP to map used by Cron Expression
|
54
|
-
DAY_OF_WEEK_EXPRESSION_MAP = DAY_OF_WEEK_MAP.transform_values
|
57
|
+
DAY_OF_WEEK_EXPRESSION_MAP = DAY_OF_WEEK_MAP.transform_values do |v|
|
58
|
+
CRON_EXPRESSION_MAP.merge(second: 0, minute: 0, hour: 0, dow: v)
|
59
|
+
end.freeze
|
55
60
|
private_constant :DAY_OF_WEEK_EXPRESSION_MAP
|
56
61
|
|
57
62
|
# @return [Hash] Create a set of cron expressions based on different time intervals
|
@@ -76,7 +81,7 @@ module OpenHAB
|
|
76
81
|
# @param [Duration] duration
|
77
82
|
# @param [Object] at LocalTime or String representing time of day
|
78
83
|
#
|
79
|
-
# @return [
|
84
|
+
# @return [String] cron expression
|
80
85
|
#
|
81
86
|
def self.from_duration(duration, at)
|
82
87
|
raise ArgumentError, '"at" cannot be used with duration' if at
|
@@ -90,7 +95,7 @@ module OpenHAB
|
|
90
95
|
# @param [MonthDay] monthday a {MonthDay} object
|
91
96
|
# @param [Object] at LocalTime or String representing time of day
|
92
97
|
#
|
93
|
-
# @return [
|
98
|
+
# @return [String] cron expression
|
94
99
|
#
|
95
100
|
def self.from_monthday(monthday, at)
|
96
101
|
expression_map = EXPRESSION_MAP[:day].merge(month: monthday.month_value, dom: monthday.day_of_month)
|
@@ -104,7 +109,7 @@ module OpenHAB
|
|
104
109
|
# @param [Symbol] symbol
|
105
110
|
# @param [Object] at LocalTime or String representing time of day
|
106
111
|
#
|
107
|
-
# @return [
|
112
|
+
# @return [String] cron expression created from symbol
|
108
113
|
#
|
109
114
|
def self.from_symbol(symbol, at)
|
110
115
|
expression_map = EXPRESSION_MAP[symbol]
|
@@ -112,12 +117,38 @@ module OpenHAB
|
|
112
117
|
map_to_cron(expression_map)
|
113
118
|
end
|
114
119
|
|
120
|
+
#
|
121
|
+
# Checks if all symbols are day-of-week symbols
|
122
|
+
#
|
123
|
+
# @param [Array<Symbol>] symbols
|
124
|
+
#
|
125
|
+
# @return [Boolean] true if all symbols are day-of-week symbols
|
126
|
+
#
|
127
|
+
def self.all_dow_symbols?(symbols)
|
128
|
+
(symbols & DAY_OF_WEEK) == symbols
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Create a cron map from a list of day-of-week symbols
|
133
|
+
#
|
134
|
+
# @param [Symbol] symbols
|
135
|
+
# @param [Object] at LocalTime or String representing time of day
|
136
|
+
#
|
137
|
+
# @return [String] cron expression created from symbols
|
138
|
+
#
|
139
|
+
def self.from_dow_symbols(symbols, at)
|
140
|
+
dow = DAY_OF_WEEK_MAP.fetch_values(*symbols).join(",")
|
141
|
+
expression_map = CRON_EXPRESSION_MAP.merge(dow: dow, hour: 0, minute: 0, second: 0)
|
142
|
+
expression_map = at_condition(expression_map, at) if at
|
143
|
+
map_to_cron(expression_map)
|
144
|
+
end
|
145
|
+
|
115
146
|
#
|
116
147
|
# Create a cron map from cron elements
|
117
148
|
#
|
118
149
|
# @param [Hash] fields Cron fields (second, minute, hour, dom, month, dow, year)
|
119
150
|
#
|
120
|
-
# @return [
|
151
|
+
# @return [String] cron expression
|
121
152
|
#
|
122
153
|
def self.from_fields(fields)
|
123
154
|
extra_fields = fields.keys - CRON_EXPRESSION_MAP.keys
|
@@ -190,17 +221,14 @@ module OpenHAB
|
|
190
221
|
#
|
191
222
|
# If an at time is provided, parse that and merge the new fields into the expression.
|
192
223
|
#
|
193
|
-
# @param [
|
194
|
-
# @param [
|
224
|
+
# @param [Hash] expression_map
|
225
|
+
# @param [LocalTime,String] at_time
|
195
226
|
#
|
196
|
-
# @return [
|
227
|
+
# @return [Hash] expression map with at time merged in
|
197
228
|
#
|
198
229
|
def self.at_condition(expression_map, at_time)
|
199
|
-
|
200
|
-
|
201
|
-
expression_map = expression_map.merge(hour: tod.hour, minute: tod.minute, second: tod.second)
|
202
|
-
end
|
203
|
-
expression_map
|
230
|
+
tod = at_time.is_a?(LocalTime) ? at_time : LocalTime.parse(at_time)
|
231
|
+
expression_map.merge(hour: tod.hour, minute: tod.minute, second: tod.second)
|
204
232
|
end
|
205
233
|
|
206
234
|
#
|
@@ -9,7 +9,32 @@ module OpenHAB
|
|
9
9
|
# @!visibility private
|
10
10
|
org.openhab.core.model.sitemap.sitemap.impl.SitemapImpl.alias_method :uid, :name
|
11
11
|
|
12
|
-
#
|
12
|
+
#
|
13
|
+
# A sitemap builder allows you to dynamically create openHAB sitemaps at runtime.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# sitemaps.build do
|
17
|
+
# sitemap "demo", label: "My home automation" do
|
18
|
+
# frame label: "Date" do
|
19
|
+
# text item: Date
|
20
|
+
# end
|
21
|
+
# frame label: "Demo" do
|
22
|
+
# switch item: Lights, icon: "light"
|
23
|
+
# text item: LR_Temperature, label: "Livingroom [%.1f °C]"
|
24
|
+
# group item: Heating
|
25
|
+
# text item: LR_Multimedia_Summary, label: "Multimedia [%s]", static_icon: "video" do
|
26
|
+
# selection item: LR_TV_Channel,
|
27
|
+
# mappings: { 0 => "off", 1 => "DasErste", 2 => "BBC One", 3 => "Cartoon Network" }
|
28
|
+
# slider item: LR_TV_Volume
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# @see https://www.openhab.org/docs/ui/sitemaps.html
|
35
|
+
# @see OpenHAB::DSL.sitemaps
|
36
|
+
# @see OpenHAB::Core::Sitemaps::Provider#build sitemaps.build
|
37
|
+
#
|
13
38
|
class Builder
|
14
39
|
# @!visibility private
|
15
40
|
def initialize(provider, builder_proxy, update:)
|
@@ -698,88 +723,92 @@ module OpenHAB
|
|
698
723
|
end
|
699
724
|
end
|
700
725
|
|
701
|
-
# Builds a `
|
702
|
-
#
|
703
|
-
#
|
704
|
-
#
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
726
|
+
# Builds a `Button` element
|
727
|
+
#
|
728
|
+
# This element can only exist within a `Buttongrid` element.
|
729
|
+
#
|
730
|
+
# @since openHAB 4.2
|
731
|
+
# @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-button
|
732
|
+
# @see org.openhab.core.model.sitemap.sitemap.Button
|
733
|
+
class ButtonBuilder < WidgetBuilder
|
734
|
+
# The row in which the button is placed
|
735
|
+
# @return [Integer]
|
736
|
+
attr_accessor :row
|
737
|
+
|
738
|
+
# The column in which the button is placed
|
739
|
+
# @return [Integer]
|
740
|
+
attr_accessor :column
|
741
|
+
|
742
|
+
# The command to send when the button is pressed
|
743
|
+
# @return [String, Command]
|
744
|
+
attr_accessor :click
|
745
|
+
|
746
|
+
# The command to send when the button is released
|
747
|
+
# @return [String, Command, nil]
|
748
|
+
attr_accessor :release
|
749
|
+
|
750
|
+
# Whether the button is stateless
|
751
|
+
# @return [true, false, nil]
|
752
|
+
attr_writer :stateless
|
709
753
|
|
710
754
|
# (see WidgetBuilder#initialize)
|
711
|
-
# @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil,
|
712
|
-
# @param [
|
713
|
-
#
|
714
|
-
#
|
715
|
-
#
|
716
|
-
#
|
717
|
-
#
|
718
|
-
#
|
719
|
-
#
|
720
|
-
# @
|
721
|
-
#
|
722
|
-
# sitemaps.build do
|
723
|
-
# sitemap "remote", label: "TV Remote Control" do
|
724
|
-
# buttongrid item: LivingRoom_TV_RCButton, buttons: [
|
725
|
-
# [1, 1, "BACK", "Back", "f7:return"],
|
726
|
-
# [1, 2, "HOME", "Menu", "material:apps"],
|
727
|
-
# [1, 3, "YELLOW", "Search", "f7:search"],
|
728
|
-
# [2, 2, "UP", "Up", "f7:arrowtriangle_up"],
|
729
|
-
# [4, 2, "DOWN", "Down", "f7:arrowtriangle_down"],
|
730
|
-
# [3, 1, "LEFT", "Left", "f7:arrowtriangle_left"],
|
731
|
-
# [3, 3, "RIGHT", "Right", "f7:arrowtriangle_right"],
|
732
|
-
# [3, 2, "ENTER", "Enter", "material:adjust"]
|
733
|
-
# ]
|
734
|
-
# end
|
735
|
-
# end
|
755
|
+
# @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, row:, column:, click:, release: nil, stateless: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
|
756
|
+
# @param [Integer] row
|
757
|
+
# The row in which the button is placed (see {ButtonBuilder#row})
|
758
|
+
# @param [Integer] column
|
759
|
+
# The column in which the button is placed (see {ButtonBuilder#column})
|
760
|
+
# @param [String, Command] click
|
761
|
+
# The command to send when the button is pressed (see {ButtonBuilder#click})
|
762
|
+
# @param [String, Command, nil] release
|
763
|
+
# The command to send when the button is released (see {ButtonBuilder#release})
|
764
|
+
# @param [true, false, nil] stateless
|
765
|
+
# Whether the button is stateless (see {ButtonBuilder#stateless=})
|
736
766
|
#
|
737
|
-
# @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-buttongrid
|
738
767
|
# @!visibility private
|
739
|
-
def initialize(
|
740
|
-
|
741
|
-
|
742
|
-
|
768
|
+
def initialize(builder_proxy,
|
769
|
+
row:,
|
770
|
+
column:,
|
771
|
+
click:,
|
772
|
+
release: nil,
|
773
|
+
stateless: nil,
|
774
|
+
**kwargs,
|
775
|
+
&block)
|
776
|
+
|
777
|
+
super(:button, builder_proxy, **kwargs, &block)
|
778
|
+
|
779
|
+
@row = row
|
780
|
+
@column = column
|
781
|
+
@click = click
|
782
|
+
@release = release
|
783
|
+
@stateless = stateless
|
743
784
|
end
|
744
785
|
|
745
|
-
#
|
746
|
-
|
747
|
-
|
748
|
-
# @param [Array<int, int, Command, String, String>] button the button to add
|
749
|
-
# @return [Array<Array<int, int, Command, String, String>>] the current buttons
|
750
|
-
#
|
751
|
-
def button(button)
|
752
|
-
validate_button(button)
|
753
|
-
@buttons << button
|
786
|
+
# (see #stateless=)
|
787
|
+
def stateless?
|
788
|
+
@stateless
|
754
789
|
end
|
755
790
|
|
756
791
|
# @!visibility private
|
757
792
|
def build
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
793
|
+
if Core.version >= Core::V4_2
|
794
|
+
super.tap do |widget|
|
795
|
+
widget.row = row
|
796
|
+
widget.column = column
|
797
|
+
widget.cmd = click.to_s
|
798
|
+
widget.release_cmd = release.to_s unless release.nil?
|
799
|
+
widget.stateless = stateless? unless @stateless.nil?
|
800
|
+
end
|
801
|
+
else
|
802
|
+
# @deprecated OH 4.1
|
803
|
+
# in OH 4.1, the button is a property of the Buttongrid, not a widget
|
804
|
+
SitemapBuilder.factory.create_button.tap do |button|
|
805
|
+
button.row = row
|
806
|
+
button.column = column
|
807
|
+
button.cmd = click.to_s
|
808
|
+
button.label = label
|
809
|
+
button.icon = icon if icon
|
810
|
+
end
|
772
811
|
end
|
773
|
-
|
774
|
-
widget
|
775
|
-
end
|
776
|
-
|
777
|
-
private
|
778
|
-
|
779
|
-
def validate_button(button)
|
780
|
-
return if (4..5).cover?(button.size)
|
781
|
-
|
782
|
-
raise ArgumentError, "Invalid button: '#{button.inspect}'. It must be an array with (4..5) elements"
|
783
812
|
end
|
784
813
|
end
|
785
814
|
|
@@ -1169,6 +1198,209 @@ module OpenHAB
|
|
1169
1198
|
class FrameBuilder < LinkableWidgetBuilder
|
1170
1199
|
end
|
1171
1200
|
|
1201
|
+
# Builds a `Buttongrid` element
|
1202
|
+
# @since openHAB 4.1
|
1203
|
+
# @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-buttongrid
|
1204
|
+
# @see org.openhab.core.model.sitemap.sitemap.Buttongrid
|
1205
|
+
class ButtongridBuilder < LinkableWidgetBuilder
|
1206
|
+
REQUIRED_BUTTON_ARGS = %i[row column click].freeze
|
1207
|
+
private_constant :REQUIRED_BUTTON_ARGS
|
1208
|
+
|
1209
|
+
# @!deprecated OH 4.1 in OH 4.1, Buttongrid is not a LinkableWidget.
|
1210
|
+
# Pretend that the buttons property is its children so we can add to it in LinkableWidgetBuilder#build
|
1211
|
+
if (Core::V4_1...Core::V4_2).cover?(Core.version)
|
1212
|
+
java_import org.openhab.core.model.sitemap.sitemap.Buttongrid
|
1213
|
+
module Buttongrid
|
1214
|
+
def children
|
1215
|
+
buttons
|
1216
|
+
end
|
1217
|
+
end
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
# (see WidgetBuilder#initialize)
|
1221
|
+
# @!method initialize(item: nil, label: nil, icon: nil, static_icon: nil, buttons: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
|
1222
|
+
# @param [Array<Array<int, int, Command, String, String>>] buttons An array of buttons to display.
|
1223
|
+
# Each element can be a hash with keyword arguments (see {Sitemaps::ButtongridBuilder#button}),
|
1224
|
+
# or an array with the following elements:
|
1225
|
+
# - row: 1-12
|
1226
|
+
# - column: 1-12
|
1227
|
+
# - click: The command to send when the button is pressed
|
1228
|
+
# - label: The label to display on the button (optional)
|
1229
|
+
# - icon: The icon to display on the button (optional)
|
1230
|
+
#
|
1231
|
+
# @example Create a buttongrid with buttons as an argument
|
1232
|
+
# # This creates a buttongrid to emulate a TV remote control
|
1233
|
+
# sitemaps.build do
|
1234
|
+
# sitemap "remote", label: "TV Remote Control" do
|
1235
|
+
# buttongrid item: LivingRoom_TV_RCButton, buttons: [
|
1236
|
+
# [1, 1, "BACK", "Back", "f7:return"],
|
1237
|
+
# [1, 2, "HOME", "Menu", "material:apps"],
|
1238
|
+
# [1, 3, "YELLOW", "Search", "f7:search"],
|
1239
|
+
# [2, 2, "UP", "Up", "f7:arrowtriangle_up"],
|
1240
|
+
# [4, 2, "DOWN", "Down", "f7:arrowtriangle_down"],
|
1241
|
+
# [3, 1, "LEFT", "Left", "f7:arrowtriangle_left"],
|
1242
|
+
# [3, 3, "RIGHT", "Right", "f7:arrowtriangle_right"],
|
1243
|
+
#
|
1244
|
+
# # Using keyword arguments:
|
1245
|
+
# {row: 3, column: 2, click: "ENTER", label: "Enter", icon: "material:adjust" }
|
1246
|
+
# ]
|
1247
|
+
# end
|
1248
|
+
# end
|
1249
|
+
#
|
1250
|
+
# @example Create a buttongrid with button widgets
|
1251
|
+
# sitemaps.build do
|
1252
|
+
# sitemap "remote", label: "TV Remote Control" do
|
1253
|
+
# buttongrid item: LivingRoom_TV_RCButton do
|
1254
|
+
# button 1, 1, click: "BACK", icon: "f7:return"
|
1255
|
+
# button 1, 2, click: "HOME", icon: "material:apps"
|
1256
|
+
# button 1, 3, click: "YELLOW", icon: "f7:search"
|
1257
|
+
# button 2, 2, click: "UP", icon: "f7:arrowtriangle_up"
|
1258
|
+
# button 4, 2, click: "DOWN", icon: "f7:arrowtriangle_down"
|
1259
|
+
# button 3, 1, click: "LEFT", icon: "f7:arrowtriangle_left"
|
1260
|
+
# button 3, 3, click: "RIGHT", icon: "f7:arrowtriangle_right"
|
1261
|
+
# button 3, 2, click: "ENTER", icon: "material:adjust"
|
1262
|
+
# end
|
1263
|
+
#
|
1264
|
+
# # The following buttons use widget features introduced in openHAB 4.2+
|
1265
|
+
# buttongrid item: LivingRoom_Curtain do
|
1266
|
+
# button 1, 1, click: "up", release: "stop", icon: "f7:arrowtriangle_up"
|
1267
|
+
# button 2, 1, click: "down", release: "stop", icon: "f7:arrowtriangle_up"
|
1268
|
+
# end
|
1269
|
+
# end
|
1270
|
+
# end
|
1271
|
+
#
|
1272
|
+
# @see https://www.openhab.org/docs/ui/sitemaps.html#element-type-buttongrid
|
1273
|
+
# @!visibility private
|
1274
|
+
def initialize(type, builder_proxy, buttons: [], **kwargs, &block)
|
1275
|
+
super(type, builder_proxy, **kwargs, &block)
|
1276
|
+
|
1277
|
+
# Put the buttons given in the constructor before those added in the block
|
1278
|
+
# We can't do this before calling the super constructor because `children` is initialized there
|
1279
|
+
children.slice!(0..).then do |buttons_from_block|
|
1280
|
+
buttons.each do |b|
|
1281
|
+
if b.is_a?(Array)
|
1282
|
+
button(*b)
|
1283
|
+
else
|
1284
|
+
button(**b)
|
1285
|
+
end
|
1286
|
+
end
|
1287
|
+
children.concat(buttons_from_block)
|
1288
|
+
end
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
#
|
1292
|
+
# @!method button(row = nil, column = nil, click = nil, label = nil, icon = nil, item: nil, label: nil, icon: nil, static_icon: nil, row:, column:, click:, release: nil, stateless: nil, label_color: nil, value_color: nil, icon_color: nil, visibility: nil)
|
1293
|
+
# Adds a button inside the buttongrid
|
1294
|
+
#
|
1295
|
+
# - In openHAB 4.1, buttons are direct properties of the buttongrid.
|
1296
|
+
# Only `row`, `column`, `click`, `label` (optional), and `icon` (optional) are used.
|
1297
|
+
# All the other parameters are ignored.
|
1298
|
+
# All the buttons will send commands to the same item assigned to the buttongrid.
|
1299
|
+
#
|
1300
|
+
# - In openHAB 4.2+, buttons are widgets within the containing buttongrid, and they
|
1301
|
+
# support all the parameters listed in the method signature such as
|
1302
|
+
# `release`, `label_color`, `visibility`, etc.
|
1303
|
+
# Each Button element has an item associated with that button.
|
1304
|
+
# When an item is not specified for the button, it will default to the containing buttongrid's item.
|
1305
|
+
#
|
1306
|
+
# This method supports positional arguments and/or keyword arguments.
|
1307
|
+
# Their use can be mixed, however, the keyword arguments will override the positional arguments
|
1308
|
+
# when both are specified.
|
1309
|
+
#
|
1310
|
+
# @param (see ButtonBuilder#initialize)
|
1311
|
+
# @return [ButtonBuilder]
|
1312
|
+
#
|
1313
|
+
# @example Adding buttons to a buttongrid with positional arguments
|
1314
|
+
# sitemaps.build do
|
1315
|
+
# sitemap "remote" do
|
1316
|
+
# buttongrid item: RCButton do
|
1317
|
+
# button 1, 1, "BACK", "Back", "f7:return"
|
1318
|
+
# button 1, 2, "HOME", "Menu", "material:apps"
|
1319
|
+
# button 1, 3, "YELLOW", "Search", "f7:search"
|
1320
|
+
# button 2, 2, "UP", "Up", "f7:arrowtriangle_up"
|
1321
|
+
# button 4, 2, "DOWN", "Down", "f7:arrowtriangle_down"
|
1322
|
+
# button 3, 1, "LEFT", "Left", "f7:arrowtriangle_left"
|
1323
|
+
# button 3, 3, "RIGHT", "Right", "f7:arrowtriangle_right"
|
1324
|
+
# button 3, 2, "ENTER", "Enter", "material:adjust"
|
1325
|
+
# end
|
1326
|
+
# end
|
1327
|
+
# end
|
1328
|
+
#
|
1329
|
+
# @example Adding buttons to a buttongrid with keyword arguments
|
1330
|
+
# sitemaps.build do
|
1331
|
+
# sitemap "remote" do
|
1332
|
+
# buttongrid item: RCButton do
|
1333
|
+
# # These buttons will use the default item assigned to the buttongrid (RCButton)
|
1334
|
+
# button row: 1, column: 1, click: "BACK", icon: "f7:return"
|
1335
|
+
# button row: 1, column: 2, click: "HOME", icon: "material:apps"
|
1336
|
+
# button row: 1, column: 3, click: "YELLOW", icon: "f7:search"
|
1337
|
+
# button row: 2, column: 2, click: "UP", icon: "f7:arrowtriangle_up"
|
1338
|
+
# button row: 4, column: 2, click: "DOWN", icon: "f7:arrowtriangle_down"
|
1339
|
+
# button row: 3, column: 1, click: "LEFT", icon: "f7:arrowtriangle_left"
|
1340
|
+
# button row: 3, column: 3, click: "RIGHT", icon: "f7:arrowtriangle_right"
|
1341
|
+
# button row: 3, column: 2, click: "ENTER", icon: "material:adjust"
|
1342
|
+
# end
|
1343
|
+
# end
|
1344
|
+
# end
|
1345
|
+
#
|
1346
|
+
# @example Mixing positional and keyword arguments
|
1347
|
+
# sitemaps.build do
|
1348
|
+
# sitemap "remote" do
|
1349
|
+
# buttongrid item: RCButton do
|
1350
|
+
# button 1, 1, click: "BACK", icon: "f7:return"
|
1351
|
+
# button 1, 2, click: "HOME", icon: "material:apps"
|
1352
|
+
# button 1, 3, click: "YELLOW", icon: "f7:search"
|
1353
|
+
# button 2, 2, click: "UP", icon: "f7:arrowtriangle_up"
|
1354
|
+
# button 4, 2, click: "DOWN", icon: "f7:arrowtriangle_down"
|
1355
|
+
# button 3, 1, click: "LEFT", icon: "f7:arrowtriangle_left"
|
1356
|
+
# button 3, 3, click: "RIGHT", icon: "f7:arrowtriangle_right"
|
1357
|
+
# button 3, 2, click: "ENTER", icon: "material:adjust"
|
1358
|
+
# end
|
1359
|
+
# end
|
1360
|
+
# end
|
1361
|
+
#
|
1362
|
+
# @example openHAB 4.2+ supports assigning different items to buttons, along with additional features
|
1363
|
+
# sitemaps.build do
|
1364
|
+
# sitemap "remote" do
|
1365
|
+
# buttongrid item: RCButton do
|
1366
|
+
# button 1, 1, click: "BACK", icon: "f7:return"
|
1367
|
+
# button 1, 2, click: "HOME", icon: "material:apps"
|
1368
|
+
# button 1, 3, click: "YELLOW", icon: "f7:search", icon_color: "yellow"
|
1369
|
+
# button 2, 2, click: "UP", icon: "f7:arrowtriangle_up"
|
1370
|
+
# button 4, 2, click: "DOWN", icon: "f7:arrowtriangle_down"
|
1371
|
+
# button 3, 1, click: "LEFT", icon: "f7:arrowtriangle_left"
|
1372
|
+
# button 3, 3, click: "RIGHT", icon: "f7:arrowtriangle_right"
|
1373
|
+
# button 3, 2, click: "ENTER", icon: "material:adjust", icon_color: "red"
|
1374
|
+
#
|
1375
|
+
# # These buttons will use the specified item, only supported in openHAB 4.2+
|
1376
|
+
# button 4, 3, click: ON, static_icon: "switch-off", visibility: "TVPower!=ON", item: TVPower
|
1377
|
+
# button 4, 3, click: OFF, static_icon: "switch-on", visibility: "TVPower==ON", item: TVPower
|
1378
|
+
# end
|
1379
|
+
# end
|
1380
|
+
# end
|
1381
|
+
#
|
1382
|
+
def button(row = nil, column = nil, click = nil, label = nil, icon = nil, **kwargs, &block)
|
1383
|
+
args = [row, column, click, label, icon].compact
|
1384
|
+
|
1385
|
+
args = args.first if args.first.is_a?(Array)
|
1386
|
+
kwargs = %i[row column click label icon].zip(args).to_h.compact.merge(kwargs)
|
1387
|
+
|
1388
|
+
missing_args = (REQUIRED_BUTTON_ARGS - kwargs.keys).compact
|
1389
|
+
unless missing_args.empty?
|
1390
|
+
args = kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")
|
1391
|
+
missing_args = missing_args.map(&:to_s).join(", ")
|
1392
|
+
raise ArgumentError, "button(#{args}) missing required parameters: #{missing_args}"
|
1393
|
+
end
|
1394
|
+
|
1395
|
+
kwargs[:item] ||= item if item # default to the buttongrid's item
|
1396
|
+
kwargs[:label] ||= kwargs[:click].to_s
|
1397
|
+
|
1398
|
+
ButtonBuilder.new(@builder_proxy, **kwargs, &block).tap do |b|
|
1399
|
+
children << b
|
1400
|
+
end
|
1401
|
+
end
|
1402
|
+
end
|
1403
|
+
|
1172
1404
|
# Builds a `Sitemap`
|
1173
1405
|
# @see https://www.openhab.org/docs/ui/sitemaps.html
|
1174
1406
|
# @see org.openhab.core.model.sitemap.sitemap.Sitemap
|
data/lib/openhab/dsl/version.rb
CHANGED
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.
|
4
|
+
version: 5.23.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: 2024-07-
|
13
|
+
date: 2024-07-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -490,7 +490,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
490
490
|
- !ruby/object:Gem::Version
|
491
491
|
version: '0'
|
492
492
|
requirements: []
|
493
|
-
rubygems_version: 3.5.
|
493
|
+
rubygems_version: 3.5.16
|
494
494
|
signing_key:
|
495
495
|
specification_version: 4
|
496
496
|
summary: JRuby Helper Libraries for openHAB Scripting
|