openhab-scripting 4.32.7 → 4.34.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/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
|