openhab-scripting 2.14.1 → 2.14.2
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.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
|