openhab-scripting 4.32.7 → 4.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/openhab/core/thread_local.rb +1 -1
- data/lib/openhab/dsl/items/ensure.rb +9 -7
- data/lib/openhab/dsl/items/timed_command.rb +1 -1
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +47 -6
- data/lib/openhab/dsl/timers/reentrant_timer.rb +1 -1
- data/lib/openhab/dsl/timers/timer.rb +90 -95
- data/lib/openhab/dsl/timers.rb +3 -1
- data/lib/openhab/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f374040f733839953804416c74c3690e1c9643143c1af746218528d7e1da50f
|
4
|
+
data.tar.gz: 5db466d2078bd40e3c47dd699296e9da8270a8c292d1ada94f67c3ff7dd8762f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0200afe739c2e8a3f4dccc02dd138b3946b610276186baeb1ae729633e5be359e466b0046e3c2c8151124968d94d918e7fbde72e22f3994996832d379f30a817
|
7
|
+
data.tar.gz: b9f109a2ee3665319110ee3354bba1efa9d5cbebe31634ca0b78e84aaea39ad3a07dc96ac5a744b52eda4dc19cd8c890abd6a53c2d5181eaa13f14f9afd9760a
|
@@ -18,7 +18,7 @@ module OpenHAB
|
|
18
18
|
# @param [Hash] values Keys and values to set for running thread, if hash is nil no values are set
|
19
19
|
#
|
20
20
|
def self.thread_local(**values)
|
21
|
-
old_values = values.
|
21
|
+
old_values = values.to_h { |key, _value| [key, Thread.current[key]] }
|
22
22
|
values.each { |key, value| Thread.current[key] = value }
|
23
23
|
logger.trace "Executing block with thread local context: #{values} - old context: #{old_values}"
|
24
24
|
yield
|
@@ -50,15 +50,17 @@ module OpenHAB
|
|
50
50
|
# If +ensure_states+ is active (by block or chained method), then
|
51
51
|
# check if this item is in the command's state before actually
|
52
52
|
# sending the command
|
53
|
-
|
54
|
-
|
53
|
+
%i[command update].each do |ensured_method|
|
54
|
+
define_method(ensured_method) do |command|
|
55
|
+
return super(command) unless Thread.current[:ensure_states]
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
logger.trace do
|
58
|
+
"#{name} ensure #{command}, format_type_pre: #{format_type_pre(command)}, current state: #{state}"
|
59
|
+
end
|
60
|
+
return if state == format_type_pre(command)
|
60
61
|
|
61
|
-
|
62
|
+
super(command)
|
63
|
+
end
|
62
64
|
end
|
63
65
|
alias << command
|
64
66
|
end
|
@@ -145,7 +145,7 @@ module OpenHAB
|
|
145
145
|
include OpenHAB::Log
|
146
146
|
include OpenHAB::Core::ThreadLocal
|
147
147
|
|
148
|
-
def initialize(timed_command_details, semaphore, &block) # rubocop:disable
|
148
|
+
def initialize(timed_command_details, semaphore, &block) # rubocop:disable Metrics/MethodLength
|
149
149
|
super()
|
150
150
|
@semaphore = semaphore
|
151
151
|
@timed_command_details = timed_command_details
|
@@ -13,16 +13,19 @@ module OpenHAB
|
|
13
13
|
#
|
14
14
|
# Create a rule that executes at the specified interval
|
15
15
|
#
|
16
|
-
# @param [Object] value Symbol or
|
16
|
+
# @param [Object] value String, Symbol, Duration, or MonthDay to execute this rule
|
17
17
|
# @param [Object] at TimeOfDay or String representing TimeOfDay in which to execute rule
|
18
18
|
# @param [Object] attach object to be attached to the trigger
|
19
19
|
#
|
20
20
|
#
|
21
21
|
def every(value, at: nil, attach: nil)
|
22
|
+
return every(MonthDay.parse(value), at: at, attach: attach) if value.is_a? String
|
23
|
+
|
22
24
|
cron_expression = case value
|
23
25
|
when Symbol then Cron.from_symbol(value, at)
|
24
26
|
when Java::JavaTime::Duration then Cron.from_duration(value, at)
|
25
|
-
|
27
|
+
when Java::JavaTime::MonthDay then Cron.from_monthday(value, at)
|
28
|
+
else raise ArgumentError, 'Unknown interval'
|
26
29
|
end
|
27
30
|
cron(cron_expression, attach: attach)
|
28
31
|
end
|
@@ -32,8 +35,18 @@ module OpenHAB
|
|
32
35
|
#
|
33
36
|
# @param [String] expression OpenHAB style cron expression
|
34
37
|
# @param [Object] attach object to be attached to the trigger
|
38
|
+
# @param [Hash] elements cron expression elements (second, minute, hour, dom, month, dow, year)
|
35
39
|
#
|
36
|
-
def cron(expression, attach: nil)
|
40
|
+
def cron(expression = nil, attach: nil, **fields)
|
41
|
+
if fields.any?
|
42
|
+
raise ArgumentError, 'Cron elements cannot be used with a cron expression' if expression
|
43
|
+
|
44
|
+
cron_expression = Cron.from_fields(fields)
|
45
|
+
return cron(cron_expression, attach: attach)
|
46
|
+
end
|
47
|
+
|
48
|
+
raise ArgumentError, 'Missing cron expression or elements' unless expression
|
49
|
+
|
37
50
|
cron = Cron.new(rule_triggers: @rule_triggers)
|
38
51
|
cron.trigger(config: { 'cronExpression' => expression }, attach: attach)
|
39
52
|
end
|
@@ -59,7 +72,8 @@ module OpenHAB
|
|
59
72
|
hour: '*',
|
60
73
|
dom: '?',
|
61
74
|
month: '*',
|
62
|
-
dow: '?'
|
75
|
+
dow: '?',
|
76
|
+
year: '*'
|
63
77
|
}.freeze
|
64
78
|
private_constant :CRON_EXPRESSION_MAP
|
65
79
|
|
@@ -96,7 +110,7 @@ module OpenHAB
|
|
96
110
|
#
|
97
111
|
# Create a cron map from a duration
|
98
112
|
#
|
99
|
-
# @param [
|
113
|
+
# @param [Java::JavaTime::Duration] duration
|
100
114
|
# @param [Object] at TimeOfDay or String representing time of day
|
101
115
|
#
|
102
116
|
# @return [Hash] map describing cron expression
|
@@ -107,6 +121,20 @@ module OpenHAB
|
|
107
121
|
map_to_cron(duration_to_map(duration))
|
108
122
|
end
|
109
123
|
|
124
|
+
#
|
125
|
+
# Create a cron map from a MonthDay
|
126
|
+
#
|
127
|
+
# @param [Java::JavaTime::MonthDay] month_day
|
128
|
+
# @param [Object] at TimeOfDay or String representing time of day
|
129
|
+
#
|
130
|
+
# @return [Hash] map describing cron expression
|
131
|
+
#
|
132
|
+
def self.from_monthday(monthday, at)
|
133
|
+
expression_map = EXPRESSION_MAP[:day].merge(month: monthday.month_value, dom: monthday.day_of_month)
|
134
|
+
expression_map = at_condition(expression_map, at) if at
|
135
|
+
map_to_cron(expression_map)
|
136
|
+
end
|
137
|
+
|
110
138
|
#
|
111
139
|
# Create a cron map from a symbol
|
112
140
|
#
|
@@ -121,6 +149,19 @@ module OpenHAB
|
|
121
149
|
map_to_cron(expression_map)
|
122
150
|
end
|
123
151
|
|
152
|
+
#
|
153
|
+
# Create a cron map from cron elements
|
154
|
+
#
|
155
|
+
# @param [Hash] elements Cron fields (second, minute, hour, dom, month, dow, year)
|
156
|
+
#
|
157
|
+
# @return [Hash] map describing cron expression
|
158
|
+
#
|
159
|
+
def self.from_fields(fields)
|
160
|
+
fields = fields.transform_values { |value| value.to_s.gsub(/\s+/, '') }
|
161
|
+
expression_map = CRON_EXPRESSION_MAP.merge(fields)
|
162
|
+
map_to_cron(expression_map)
|
163
|
+
end
|
164
|
+
|
124
165
|
#
|
125
166
|
# Map cron expression to to cron string
|
126
167
|
#
|
@@ -129,7 +170,7 @@ module OpenHAB
|
|
129
170
|
# @return [String] OpenHAB cron string
|
130
171
|
#
|
131
172
|
def self.map_to_cron(map)
|
132
|
-
%i[second minute hour dom month dow].map { |field| map.fetch(field) }.join(' ')
|
173
|
+
%i[second minute hour dom month dow year].map { |field| map.fetch(field) }.join(' ')
|
133
174
|
end
|
134
175
|
|
135
176
|
#
|
@@ -8,114 +8,109 @@ require 'openhab/core/thread_local'
|
|
8
8
|
|
9
9
|
module OpenHAB
|
10
10
|
module DSL
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
module Timers
|
15
|
-
java_import org.openhab.core.model.script.actions.ScriptExecution
|
16
|
-
java_import java.time.ZonedDateTime
|
11
|
+
java_import org.openhab.core.model.script.actions.ScriptExecution
|
12
|
+
java_import java.time.ZonedDateTime
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
14
|
+
# Ruby wrapper for OpenHAB Timer
|
15
|
+
# This class implements delegator to delegate methods to the OpenHAB timer
|
16
|
+
#
|
17
|
+
# @author Brian O'Connell
|
18
|
+
# @since 2.0.0
|
19
|
+
class Timer < SimpleDelegator
|
20
|
+
include OpenHAB::Log
|
21
|
+
include OpenHAB::Core::ThreadLocal
|
22
|
+
extend Forwardable
|
27
23
|
|
28
|
-
|
24
|
+
def_delegator :@timer, :has_terminated, :terminated?
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
#
|
27
|
+
# Create a new Timer Object
|
28
|
+
#
|
29
|
+
# @param [Duration] duration Duration until timer should fire
|
30
|
+
# @param [Block] block Block to execute when timer fires
|
31
|
+
#
|
32
|
+
# rubocop: disable Metrics/MethodLength
|
33
|
+
def initialize(duration:, thread_locals: {}, &block)
|
34
|
+
@duration = duration
|
35
|
+
@thread_locals = thread_locals
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
# A semaphore is used to prevent a race condition in which calling the block from the timer thread
|
38
|
+
# occurs before the @timer variable can be set resulting in @timer being nil
|
39
|
+
semaphore = Mutex.new
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
41
|
+
semaphore.synchronize do
|
42
|
+
@timer = ScriptExecution.createTimer(
|
43
|
+
ZonedDateTime.now.plus(to_duration(@duration)), timer_block(semaphore, &block)
|
44
|
+
)
|
45
|
+
@rule_timers = Thread.current[:rule_timers]
|
46
|
+
super(@timer)
|
47
|
+
Timers.timer_manager.add(self)
|
53
48
|
end
|
54
|
-
|
49
|
+
end
|
50
|
+
# rubocop: enable Metrics/MethodLength
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
52
|
+
#
|
53
|
+
# Reschedule timer
|
54
|
+
#
|
55
|
+
# @param [Duration] duration
|
56
|
+
#
|
57
|
+
# @return [Timer] Rescheduled timer instances
|
58
|
+
#
|
59
|
+
def reschedule(duration = nil)
|
60
|
+
duration ||= @duration
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
Timers.timer_manager.add(self)
|
63
|
+
@timer.reschedule(ZonedDateTime.now.plus(to_duration(duration)))
|
64
|
+
end
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
66
|
+
#
|
67
|
+
# Cancel timer
|
68
|
+
#
|
69
|
+
# @return [Boolean] True if cancel was successful, false otherwise
|
70
|
+
#
|
71
|
+
def cancel
|
72
|
+
Timers.timer_manager.delete(self)
|
73
|
+
@timer.cancel
|
74
|
+
end
|
79
75
|
|
80
|
-
|
76
|
+
private
|
81
77
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
78
|
+
#
|
79
|
+
# Constructs a block to execute timer within
|
80
|
+
#
|
81
|
+
# @param [Semaphore] semaphore to obtain before executing
|
82
|
+
#
|
83
|
+
# @return [Proc] Block for timer to execute
|
84
|
+
#
|
85
|
+
def timer_block(semaphore)
|
86
|
+
proc {
|
87
|
+
semaphore.synchronize do
|
88
|
+
Timers.timer_manager.delete(self)
|
89
|
+
thread_local(@thread_locals) do
|
90
|
+
yield(self)
|
96
91
|
end
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
#
|
101
|
-
# Convert argument to a duration
|
102
|
-
#
|
103
|
-
# @param [Java::JavaTimeTemporal::TemporalAmount, #to_f, #to_i, nil] duration Duration
|
104
|
-
#
|
105
|
-
# @raise if duration cannot be used for a timer
|
106
|
-
#
|
107
|
-
# @return Argument converted to seconds if it responds to #to_f or #to_i, otherwise duration unchanged
|
108
|
-
#
|
109
|
-
def to_duration(duration)
|
110
|
-
if duration.nil? || duration.is_a?(Java::JavaTimeTemporal::TemporalAmount)
|
111
|
-
duration
|
112
|
-
elsif duration.respond_to?(:to_f)
|
113
|
-
duration.to_f.seconds
|
114
|
-
elsif duration.respond_to?(:to_i)
|
115
|
-
duration.to_i.seconds
|
116
|
-
else
|
117
|
-
raise ArgumentError, "Supplied argument '#{duration}' cannot be converted to a duration"
|
118
92
|
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Convert argument to a duration
|
98
|
+
#
|
99
|
+
# @param [Java::JavaTimeTemporal::TemporalAmount, #to_f, #to_i, nil] duration Duration
|
100
|
+
#
|
101
|
+
# @raise if duration cannot be used for a timer
|
102
|
+
#
|
103
|
+
# @return Argument converted to seconds if it responds to #to_f or #to_i, otherwise duration unchanged
|
104
|
+
#
|
105
|
+
def to_duration(duration)
|
106
|
+
if duration.nil? || duration.is_a?(Java::JavaTimeTemporal::TemporalAmount)
|
107
|
+
duration
|
108
|
+
elsif duration.respond_to?(:to_f)
|
109
|
+
duration.to_f.seconds
|
110
|
+
elsif duration.respond_to?(:to_i)
|
111
|
+
duration.to_i.seconds
|
112
|
+
else
|
113
|
+
raise ArgumentError, "Supplied argument '#{duration}' cannot be converted to a duration"
|
119
114
|
end
|
120
115
|
end
|
121
116
|
end
|
data/lib/openhab/dsl/timers.rb
CHANGED
@@ -36,8 +36,10 @@ module OpenHAB
|
|
36
36
|
thread_locals ||= {}
|
37
37
|
return Timers.reentrant_timer(duration: duration, thread_locals: thread_locals, id: id, &block) if id
|
38
38
|
|
39
|
-
Timer.new(duration: duration, thread_locals: thread_locals, &block)
|
39
|
+
OpenHAB::DSL::Timer.new(duration: duration, thread_locals: thread_locals, &block)
|
40
40
|
end
|
41
|
+
# An alias for +after+
|
42
|
+
alias create_timer after
|
41
43
|
|
42
44
|
#
|
43
45
|
# Provdes access to the hash for mapping timer ids to the set of active timers associated with that id
|
data/lib/openhab/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openhab-scripting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.34.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian O'Connell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|