openhab-scripting 2.14.1 → 2.14.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openhab.rb +3 -0
- data/lib/openhab/core/dsl/actions.rb +1 -1
- data/lib/openhab/core/dsl/entities.rb +41 -4
- data/lib/openhab/core/dsl/gems.rb +1 -1
- data/lib/openhab/core/dsl/group.rb +3 -1
- data/lib/openhab/core/dsl/items/items.rb +3 -1
- data/lib/openhab/core/dsl/items/number_item.rb +151 -50
- data/lib/openhab/core/dsl/items/string_item.rb +21 -3
- data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +66 -42
- data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +2 -1
- data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +2 -1
- data/lib/openhab/core/dsl/property.rb +15 -4
- data/lib/openhab/core/dsl/rule/automation_rule.rb +348 -0
- data/lib/openhab/core/dsl/rule/guard.rb +43 -6
- data/lib/openhab/core/dsl/rule/rule.rb +80 -367
- data/lib/openhab/core/dsl/rule/rule_config.rb +153 -0
- data/lib/openhab/core/dsl/rule/triggers/changed.rb +145 -0
- data/lib/openhab/core/dsl/rule/{channel.rb → triggers/channel.rb} +22 -8
- data/lib/openhab/core/dsl/rule/triggers/command.rb +106 -0
- data/lib/openhab/core/dsl/rule/{cron.rb → triggers/cron.rb} +36 -14
- data/lib/openhab/core/dsl/rule/triggers/trigger.rb +126 -0
- data/lib/openhab/core/dsl/rule/triggers/updated.rb +100 -0
- data/lib/openhab/core/dsl/time_of_day.rb +50 -24
- data/lib/openhab/core/dsl/timers.rb +2 -6
- data/lib/openhab/core/dsl/types/quantity.rb +106 -69
- data/lib/openhab/core/log.rb +3 -8
- data/lib/openhab/core/startup_delay.rb +1 -0
- data/lib/openhab/osgi.rb +7 -0
- data/lib/openhab/version.rb +1 -1
- metadata +10 -6
- data/lib/openhab/core/dsl/rule/item.rb +0 -203
- data/lib/openhab/core/dsl/rule/triggers.rb +0 -77
@@ -11,7 +11,7 @@ module OpenHAB
|
|
11
11
|
#
|
12
12
|
# Cron type rules
|
13
13
|
#
|
14
|
-
module
|
14
|
+
module Triggers
|
15
15
|
java_import org.openhab.core.automation.util.TriggerBuilder
|
16
16
|
java_import org.openhab.core.config.core.Configuration
|
17
17
|
|
@@ -58,18 +58,12 @@ module OpenHAB
|
|
58
58
|
#
|
59
59
|
#
|
60
60
|
def every(value, at: nil)
|
61
|
-
case value
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
raise ArgumentError, '"at" cannot be used with duration' if at
|
68
|
-
|
69
|
-
cron(map_to_cron(duration_to_map(value)))
|
70
|
-
else
|
71
|
-
raise ArgumentExpression, 'Unknown interval' unless expression_map
|
72
|
-
end
|
61
|
+
cron_expression = case value
|
62
|
+
when Symbol then cron_from_symbol(value, at)
|
63
|
+
when Java::JavaTime::Duration then cron_from_duration(value, at)
|
64
|
+
else raise ArgumentExpression, 'Unknown interval'
|
65
|
+
end
|
66
|
+
cron(cron_expression)
|
73
67
|
end
|
74
68
|
|
75
69
|
#
|
@@ -83,6 +77,34 @@ module OpenHAB
|
|
83
77
|
|
84
78
|
private
|
85
79
|
|
80
|
+
#
|
81
|
+
# Create a cron map from a duration
|
82
|
+
#
|
83
|
+
# @param [java::time::Duration] duration
|
84
|
+
# @param [Object] at TimeOfDay or String representing time of day
|
85
|
+
#
|
86
|
+
# @return [Hash] map describing cron expression
|
87
|
+
#
|
88
|
+
def cron_from_duration(duration, at)
|
89
|
+
raise ArgumentError, '"at" cannot be used with duration' if at
|
90
|
+
|
91
|
+
map_to_cron(duration_to_map(duration))
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Create a cron map from a symbol
|
96
|
+
#
|
97
|
+
# @param [Symbol] symbol
|
98
|
+
# @param [Object] at TimeOfDay or String representing time of day
|
99
|
+
#
|
100
|
+
# @return [Hash] map describing cron expression created from symbol
|
101
|
+
#
|
102
|
+
def cron_from_symbol(symbol, at)
|
103
|
+
expression_map = EXPRESSION_MAP[symbol]
|
104
|
+
expression_map = at_condition(expression_map, at) if at
|
105
|
+
map_to_cron(expression_map)
|
106
|
+
end
|
107
|
+
|
86
108
|
#
|
87
109
|
# Map cron expression to to cron string
|
88
110
|
#
|
@@ -126,7 +148,7 @@ module OpenHAB
|
|
126
148
|
#
|
127
149
|
def at_condition(expression_map, at_time)
|
128
150
|
if at_time
|
129
|
-
tod =
|
151
|
+
tod = at_time.is_a?(TimeOfDay) ? at_time : TimeOfDay.parse(at_time)
|
130
152
|
expression_map = expression_map.merge(hour: tod.hour, minute: tod.minute, second: tod.second)
|
131
153
|
end
|
132
154
|
expression_map
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
require 'java'
|
5
|
+
|
6
|
+
module OpenHAB
|
7
|
+
module Core
|
8
|
+
module DSL
|
9
|
+
module Rule
|
10
|
+
#
|
11
|
+
# Module holds rule triggers
|
12
|
+
#
|
13
|
+
module Triggers
|
14
|
+
#
|
15
|
+
# Create a trigger for a thing
|
16
|
+
#
|
17
|
+
# @param [Thing] thing to create trigger for
|
18
|
+
# @param [Trigger] trigger to map with thing
|
19
|
+
# @param [State] to for thing
|
20
|
+
# @param [State] from state of thing
|
21
|
+
#
|
22
|
+
# @return [Array] Trigger and config for thing
|
23
|
+
#
|
24
|
+
def trigger_for_thing(thing, trigger, to = nil, from = nil)
|
25
|
+
config = { 'thingUID' => thing.uid.to_s }
|
26
|
+
config['status'] = trigger_state_from_symbol(to).to_s if to
|
27
|
+
config['previousStatus'] = trigger_state_from_symbol(from).to_s if from
|
28
|
+
[trigger, config]
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# converts object to upcase string if its a symbol
|
33
|
+
#
|
34
|
+
# @param [sym] sym potential symbol to convert
|
35
|
+
#
|
36
|
+
# @return [String] Upcased symbol as string
|
37
|
+
#
|
38
|
+
def trigger_state_from_symbol(sym)
|
39
|
+
sym.to_s.upcase if (sym.is_a? Symbol) || sym
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Append a trigger to the list of triggeres
|
44
|
+
#
|
45
|
+
# @param [String] type of trigger to create
|
46
|
+
# @param [Map] config map describing trigger configuration
|
47
|
+
#
|
48
|
+
# @return [Trigger] OpenHAB trigger
|
49
|
+
#
|
50
|
+
def append_trigger(type, config)
|
51
|
+
logger.trace("Creating trigger of type #{type} for #{config}")
|
52
|
+
trigger = Trigger.trigger(type: type, config: config)
|
53
|
+
@triggers << trigger
|
54
|
+
trigger
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Class for creating and managing triggers
|
59
|
+
#
|
60
|
+
class Trigger
|
61
|
+
java_import org.openhab.core.automation.util.TriggerBuilder
|
62
|
+
java_import org.openhab.core.config.core.Configuration
|
63
|
+
|
64
|
+
# @return [String] A channel event trigger
|
65
|
+
CHANNEL_EVENT = 'core.ChannelEventTrigger'
|
66
|
+
|
67
|
+
# @return [String] A thing status Change trigger
|
68
|
+
THING_CHANGE = 'core.ThingStatusChangeTrigger'
|
69
|
+
|
70
|
+
# @return [String] A thing status update trigger
|
71
|
+
THING_UPDATE = 'core.ThingStatusUpdateTrigger'
|
72
|
+
|
73
|
+
# @return [String] An item command trigger
|
74
|
+
ITEM_COMMAND = 'core.ItemCommandTrigger'
|
75
|
+
|
76
|
+
# @return [String] An item state update trigger
|
77
|
+
ITEM_STATE_UPDATE = 'core.ItemStateUpdateTrigger'
|
78
|
+
|
79
|
+
# @return [String] An item state change trigger
|
80
|
+
ITEM_STATE_CHANGE = 'core.ItemStateChangeTrigger'
|
81
|
+
|
82
|
+
# @return [String] A group state change trigger for items in the group
|
83
|
+
GROUP_STATE_CHANGE = 'core.GroupStateChangeTrigger'
|
84
|
+
|
85
|
+
# @return [String] A group state update trigger for items in the group
|
86
|
+
GROUP_STATE_UPDATE = 'core.GroupStateUpdateTrigger'
|
87
|
+
|
88
|
+
# @return [String] A group command trigger for items in the group
|
89
|
+
GROUP_COMMAND = 'core.GroupCommandTrigger'
|
90
|
+
|
91
|
+
# @return [String] A time of day trigger
|
92
|
+
TIME_OF_DAY = 'timer.TimeOfDayTrigger'
|
93
|
+
|
94
|
+
# @return [String] A cron trigger
|
95
|
+
CRON = 'timer.GenericCronTrigger'
|
96
|
+
|
97
|
+
#
|
98
|
+
# Create a trigger
|
99
|
+
#
|
100
|
+
# @param [String] type of trigger
|
101
|
+
# @param [Map] config map
|
102
|
+
#
|
103
|
+
# @return [OpenHAB Trigger] configured by type and supplied config
|
104
|
+
#
|
105
|
+
def self.trigger(type:, config:)
|
106
|
+
TriggerBuilder.create
|
107
|
+
.with_id(uuid)
|
108
|
+
.with_type_uid(type)
|
109
|
+
.with_configuration(Configuration.new(config))
|
110
|
+
.build
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Generate a UUID for triggers
|
115
|
+
#
|
116
|
+
# @return [String] UUID
|
117
|
+
#
|
118
|
+
def self.uuid
|
119
|
+
SecureRandom.uuid
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'core/log'
|
4
|
+
|
5
|
+
module OpenHAB
|
6
|
+
module Core
|
7
|
+
module DSL
|
8
|
+
module Rule
|
9
|
+
#
|
10
|
+
# Module holds rule triggers
|
11
|
+
#
|
12
|
+
module Triggers
|
13
|
+
include Logging
|
14
|
+
|
15
|
+
#
|
16
|
+
# Create a trigger when item, group or thing is updated
|
17
|
+
#
|
18
|
+
# @param [Array] items array to trigger on updated
|
19
|
+
# @param [State] to to match for tigger
|
20
|
+
#
|
21
|
+
# @return [Trigger] Trigger for updated entity
|
22
|
+
#
|
23
|
+
def updated(*items, to: nil)
|
24
|
+
items.flatten.each do |item|
|
25
|
+
logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
|
26
|
+
[to].flatten.each do |to_state|
|
27
|
+
trigger, config = create_update_trigger(item, to_state)
|
28
|
+
append_trigger(trigger, config)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
#
|
36
|
+
# Create a trigger for updates
|
37
|
+
#
|
38
|
+
# @param [Object] item Type of item [Group,Thing,Item] to create update trigger for
|
39
|
+
# @param [State] to_state state restriction on trigger
|
40
|
+
#
|
41
|
+
# @return [Array<Hash,String>] first element is a String specifying trigger type
|
42
|
+
# second element is a Hash configuring trigger
|
43
|
+
#
|
44
|
+
def create_update_trigger(item, to_state)
|
45
|
+
case item
|
46
|
+
when GroupItems then group_update(item, to_state)
|
47
|
+
when Thing then thing_update(item, to_state)
|
48
|
+
else item_update(item, to_state)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Create an update trigger for an item
|
54
|
+
#
|
55
|
+
# @param [Item] item to create trigger for
|
56
|
+
# @param [State] to_state optional state restriction for target
|
57
|
+
#
|
58
|
+
# @return [Array<Hash,String>] first element is a String specifying trigger type
|
59
|
+
# second element is a Hash configuring trigger
|
60
|
+
#
|
61
|
+
def item_update(item, to_state)
|
62
|
+
config = { 'itemName' => item.name }
|
63
|
+
config['state'] = to_state.to_s unless to_state.nil?
|
64
|
+
trigger = Trigger::ITEM_STATE_UPDATE
|
65
|
+
[trigger, config]
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Create an update trigger for a group
|
70
|
+
#
|
71
|
+
# @param [Item] item to create trigger for
|
72
|
+
# @param [State] to_state optional state restriction for target
|
73
|
+
#
|
74
|
+
# @return [Array<Hash,String>] first element is a String specifying trigger type
|
75
|
+
# second element is a Hash configuring trigger
|
76
|
+
#
|
77
|
+
def group_update(item, to_state)
|
78
|
+
config = { 'groupName' => item.group.name }
|
79
|
+
config['state'] = to_state.to_s unless to_state.nil?
|
80
|
+
trigger = Trigger::GROUP_STATE_UPDATE
|
81
|
+
[trigger, config]
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Create an update trigger for a thing
|
86
|
+
#
|
87
|
+
# @param [Thing] thing to create trigger for
|
88
|
+
# @param [State] to_state optional state restriction for target
|
89
|
+
#
|
90
|
+
# @return [Array<Hash,String>] first element is a String specifying trigger type
|
91
|
+
# second element is a Hash configuring trigger
|
92
|
+
#
|
93
|
+
def thing_update(thing, to_state)
|
94
|
+
trigger_for_thing(thing, Trigger::THING_UPDATE, to_state)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -50,7 +50,8 @@ module OpenHAB
|
|
50
50
|
|
51
51
|
# Constructs a TimeOfDay representing the time when called
|
52
52
|
# @since 0.0.1
|
53
|
-
# @param [String] string representation of TimeOfDay. Valid formats include "HH:MM:SS", "HH:MM",
|
53
|
+
# @param [String] string representation of TimeOfDay. Valid formats include "HH:MM:SS", "HH:MM",
|
54
|
+
# "H:MM", "HH", "H", "H:MM am"
|
54
55
|
# @return [TimeOfDay] object created by parsing supplied string
|
55
56
|
def self.parse(string)
|
56
57
|
format = /(am|pm)$/i.match?(string) ? 'h[:mm[:ss]][ ]a' : 'H[:mm[:ss]]'
|
@@ -67,10 +68,13 @@ module OpenHAB
|
|
67
68
|
# @option opts [Number] :m Minute of the day, defaults to 0
|
68
69
|
# @option opts [Number] :s Second of the day, defaults to 0
|
69
70
|
# @return [TimeOfDay] representing time when method was invoked
|
71
|
+
# rubocop: disable Naming/MethodParameterName
|
72
|
+
# This method has a better feel with short parameter names
|
70
73
|
def initialize(h: 0, m: 0, s: 0)
|
71
74
|
@local_time = LocalTime.of(h, m, s)
|
72
75
|
freeze
|
73
76
|
end
|
77
|
+
# rubocop: enable Naming/MethodParameterName
|
74
78
|
|
75
79
|
# Returns true if the time falls within a range
|
76
80
|
def between?(range)
|
@@ -100,14 +104,16 @@ module OpenHAB
|
|
100
104
|
|
101
105
|
# Returns the string representation of the TimeOfDay
|
102
106
|
# @since 0.0.1
|
103
|
-
# @return [String] in any of the following formats depending on time representation HH:mm, HH:mm:ss,
|
107
|
+
# @return [String] in any of the following formats depending on time representation HH:mm, HH:mm:ss,
|
108
|
+
# HH:mm:ss.SSS, HH:mm:ss.SSSSSS, HH:mm:ss.SSSSSSSSS
|
104
109
|
def to_s
|
105
110
|
@local_time.to_s
|
106
111
|
end
|
107
112
|
|
108
113
|
# Compares one TimeOfDay to another
|
109
114
|
# @since 0.0.1
|
110
|
-
# @return [Number, nil] -1,0,1 if other TimeOfDay is less than, equal to, or greater than this TimeOfDay
|
115
|
+
# @return [Number, nil] -1,0,1 if other TimeOfDay is less than, equal to, or greater than this TimeOfDay
|
116
|
+
# or nil if an object other than TimeOfDay is provided
|
111
117
|
def <=>(other)
|
112
118
|
case other
|
113
119
|
when TimeOfDay
|
@@ -143,28 +149,36 @@ module OpenHAB
|
|
143
149
|
# @since 2.4.0
|
144
150
|
# @return [Number, nil] -1,0,1 if other is less than, equal to, or greater than this TimeOfDay
|
145
151
|
def <=>(other)
|
146
|
-
other_second_of_day =
|
147
|
-
when TimeOfDay
|
148
|
-
adjust_second_of_day(other.local_time.to_second_of_day)
|
149
|
-
when String
|
150
|
-
adjust_second_of_day(TimeOfDay.parse(other).local_time.to_second_of_day)
|
151
|
-
when Time
|
152
|
-
adjust_second_of_day(TimeOfDay.new(h: other.hour, m: other.min,
|
153
|
-
s: other.sec).local_time.to_second_of_day)
|
154
|
-
when TimeOfDayRangeElement
|
155
|
-
other.sod
|
156
|
-
else
|
157
|
-
raise ArgumentError, 'Supplied argument cannot be converted into Time Of Day Object'
|
158
|
-
end
|
159
|
-
|
152
|
+
other_second_of_day = to_second_of_day(other)
|
160
153
|
logger.trace do
|
161
|
-
"SOD(#{sod})
|
154
|
+
"SOD(#{sod}) "\
|
155
|
+
"other SOD(#{other_second_of_day}) "\
|
156
|
+
"Other Class (#{other.class}) "\
|
157
|
+
"Result (#{sod <=> other_second_of_day})"
|
162
158
|
end
|
163
159
|
sod <=> other_second_of_day
|
164
160
|
end
|
165
161
|
|
166
162
|
private
|
167
163
|
|
164
|
+
#
|
165
|
+
# Convert object to the seconds of a day they reprsent
|
166
|
+
#
|
167
|
+
# @param [Object] object TimeofDay,String,Time, or TimeOfDayRangeElement to convert
|
168
|
+
#
|
169
|
+
# @return [Integer] seconds of day represented by supplied object
|
170
|
+
#
|
171
|
+
def to_second_of_day(object)
|
172
|
+
case object
|
173
|
+
when TimeOfDay then adjust_second_of_day(object.local_time.to_second_of_day)
|
174
|
+
when String then adjust_second_of_day(TimeOfDay.parse(object).local_time.to_second_of_day)
|
175
|
+
when Time then adjust_second_of_day(TimeOfDay.new(h: object.hour, m: object.min,
|
176
|
+
s: object.sec).local_time.to_second_of_day)
|
177
|
+
when TimeOfDayRangeElement then object.sod
|
178
|
+
else raise ArgumentError, 'Supplied argument cannot be converted into Time Of Day Object'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
168
182
|
def adjust_second_of_day(second_of_day)
|
169
183
|
second_of_day += NUM_SECONDS_IN_DAY if second_of_day < @range_begin
|
170
184
|
second_of_day
|
@@ -175,14 +189,13 @@ module OpenHAB
|
|
175
189
|
# to see if they are within the range
|
176
190
|
# @since 2.4.0
|
177
191
|
# @return Range object representing a TimeOfDay Range
|
192
|
+
module_function
|
193
|
+
|
178
194
|
def between(range)
|
179
195
|
raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
|
180
196
|
|
181
|
-
start = range.begin
|
182
|
-
ending = range.end
|
183
|
-
|
184
|
-
start = TimeOfDay.parse(start) if start.is_a? String
|
185
|
-
ending = TimeOfDay.parse(ending) if ending.is_a? String
|
197
|
+
start = to_time_of_day(range.begin)
|
198
|
+
ending = to_time_of_day(range.end)
|
186
199
|
|
187
200
|
start_sod = start.local_time.to_second_of_day
|
188
201
|
ending_sod = ending.local_time.to_second_of_day
|
@@ -192,7 +205,20 @@ module OpenHAB
|
|
192
205
|
ending_range = TimeOfDayRangeElement.new(sod: ending_sod, range_begin: start_sod)
|
193
206
|
range.exclude_end? ? (start_range...ending_range) : (start_range..ending_range)
|
194
207
|
end
|
195
|
-
|
208
|
+
|
209
|
+
#
|
210
|
+
# Convert object to TimeOfDay object
|
211
|
+
#
|
212
|
+
# @param [Object] object TimeOfDay or String to be converted
|
213
|
+
#
|
214
|
+
# @return [TimeOfDay] TimeOfDay created from supplied object
|
215
|
+
#
|
216
|
+
private_class_method def to_time_of_day(object)
|
217
|
+
case object
|
218
|
+
when String then TimeOfDay.parse(object)
|
219
|
+
else object
|
220
|
+
end
|
221
|
+
end
|
196
222
|
|
197
223
|
MIDNIGHT = TimeOfDay.midnight
|
198
224
|
NOON = TimeOfDay.noon
|
@@ -39,15 +39,11 @@ module OpenHAB
|
|
39
39
|
# occurs before the @timer variable can be set resulting in @timer being nil
|
40
40
|
semaphore = Mutex.new
|
41
41
|
|
42
|
-
|
43
|
-
semaphore.synchronize do
|
44
|
-
block.call(self)
|
45
|
-
end
|
46
|
-
end
|
42
|
+
timer_block = proc { semaphore.synchronize { block.call(self) } }
|
47
43
|
|
48
44
|
semaphore.synchronize do
|
49
45
|
@timer = ScriptExecution.createTimer(
|
50
|
-
ZonedDateTime.now.plus(@duration),
|
46
|
+
ZonedDateTime.now.plus(@duration), timer_block
|
51
47
|
)
|
52
48
|
super(@timer)
|
53
49
|
end
|