openhab-jrubyscripting 5.0.0.rc1 → 5.0.0.rc3
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/entity_lookup.rb +1 -12
- data/lib/openhab/core/items/generic_item.rb +15 -7
- data/lib/openhab/core/items/metadata/hash.rb +81 -39
- data/lib/openhab/core/items/metadata/namespace_hash.rb +17 -19
- data/lib/openhab/core/items/metadata/provider.rb +48 -0
- data/lib/openhab/core/items/persistence.rb +2 -0
- data/lib/openhab/core/items/provider.rb +40 -0
- data/lib/openhab/core/items/proxy.rb +10 -0
- data/lib/openhab/core/items/registry.rb +16 -7
- data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
- data/lib/openhab/core/items/state_storage.rb +3 -3
- data/lib/openhab/core/profile_factory.rb +3 -1
- data/lib/openhab/core/provider.rb +223 -0
- data/lib/openhab/core/registry.rb +30 -0
- data/lib/openhab/core/rules/provider.rb +25 -0
- data/lib/openhab/core/rules/registry.rb +76 -0
- data/lib/openhab/core/rules/rule.rb +150 -0
- data/lib/openhab/core/rules.rb +25 -0
- data/lib/openhab/core/script_handling.rb +50 -0
- data/lib/openhab/core/things/links/provider.rb +40 -0
- data/lib/openhab/core/things/provider.rb +25 -0
- data/lib/openhab/core/things/proxy.rb +10 -0
- data/lib/openhab/core/things/registry.rb +25 -2
- data/lib/openhab/core/timer.rb +17 -7
- data/lib/openhab/core/types/quantity_type.rb +5 -2
- data/lib/openhab/core/types.rb +1 -1
- data/lib/openhab/core.rb +3 -30
- data/lib/openhab/core_ext/java/class.rb +34 -0
- data/lib/openhab/core_ext/java/list.rb +436 -0
- data/lib/openhab/core_ext/java/local_time.rb +2 -1
- data/lib/openhab/core_ext/java/map.rb +66 -0
- data/lib/openhab/core_ext/java/month.rb +2 -1
- data/lib/openhab/core_ext/java/zoned_date_time.rb +1 -2
- data/lib/openhab/core_ext/ruby/date.rb +2 -0
- data/lib/openhab/core_ext/ruby/date_time.rb +53 -0
- data/lib/openhab/core_ext/ruby/time.rb +88 -86
- data/lib/openhab/dsl/events/watch_event.rb +1 -1
- data/lib/openhab/dsl/items/builder.rb +38 -100
- data/lib/openhab/dsl/items/ensure.rb +6 -2
- data/lib/openhab/dsl/items/timed_command.rb +10 -11
- data/lib/openhab/dsl/rules/automation_rule.rb +36 -13
- data/lib/openhab/dsl/rules/builder.rb +126 -8
- data/lib/openhab/dsl/rules/name_inference.rb +0 -5
- data/lib/openhab/dsl/rules/terse.rb +1 -2
- data/lib/openhab/dsl/rules/triggers/changed.rb +7 -4
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +17 -53
- data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +0 -3
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +1 -1
- data/lib/openhab/dsl/rules/triggers/trigger.rb +1 -1
- data/lib/openhab/dsl/rules/triggers/updated.rb +7 -3
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
- data/lib/openhab/dsl/rules.rb +0 -21
- data/lib/openhab/dsl/script_handling.rb +0 -49
- data/lib/openhab/dsl/things/builder.rb +8 -31
- data/lib/openhab/dsl/thread_local.rb +3 -2
- data/lib/openhab/dsl/timer_manager.rb +16 -8
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/dsl.rb +137 -120
- data/lib/openhab/log.rb +3 -3
- data/lib/openhab/rspec/example_group.rb +42 -0
- data/lib/openhab/rspec/helpers.rb +33 -27
- data/lib/openhab/rspec/hooks.rb +17 -23
- data/lib/openhab/rspec/karaf.rb +45 -27
- data/lib/openhab/rspec/mocks/synchronous_executor.rb +11 -4
- data/lib/openhab/rspec/mocks/timer.rb +7 -1
- data/lib/openhab/rspec/suspend_rules.rb +4 -2
- metadata +30 -3
- data/lib/openhab/rspec/mocks/metadata_provider.rb +0 -75
@@ -16,7 +16,7 @@ module OpenHAB
|
|
16
16
|
# @param [Config] config Rule configuration
|
17
17
|
#
|
18
18
|
# Constructor sets a number of variables, no further decomposition necessary
|
19
|
-
def initialize(config
|
19
|
+
def initialize(config)
|
20
20
|
# Metrics disabled because only setters are called or defaults set.
|
21
21
|
super()
|
22
22
|
set_name(config.name)
|
@@ -29,8 +29,13 @@ module OpenHAB
|
|
29
29
|
@guard = config.guard
|
30
30
|
@between = config.between && DSL.between(config.between)
|
31
31
|
@trigger_conditions = config.trigger_conditions
|
32
|
+
@trigger_conditions.each_value do |condition|
|
33
|
+
condition.rule = self if condition.respond_to?(:rule=)
|
34
|
+
end
|
32
35
|
@attachments = config.attachments
|
33
36
|
@thread_locals = ThreadLocal.persist
|
37
|
+
@cleanup_hooks = Set.new
|
38
|
+
@listener = nil
|
34
39
|
end
|
35
40
|
|
36
41
|
#
|
@@ -48,19 +53,37 @@ module OpenHAB
|
|
48
53
|
process_queue(create_queue(inputs), mod, inputs)
|
49
54
|
end
|
50
55
|
rescue Exception => e
|
56
|
+
raise if defined?(::RSpec)
|
57
|
+
|
51
58
|
@run_context.send(:logger).log_exception(e)
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@trigger_conditions.each_value(&:cleanup)
|
62
|
+
# @!visibility private
|
63
|
+
def on_removal(listener)
|
64
|
+
@cleanup_hooks << listener
|
65
|
+
listen_for_removal unless @listener
|
60
66
|
end
|
61
67
|
|
62
68
|
private
|
63
69
|
|
70
|
+
def cleanup
|
71
|
+
@cleanup_hooks.each(&:cleanup)
|
72
|
+
end
|
73
|
+
|
74
|
+
def listen_for_removal
|
75
|
+
@listener ||= org.openhab.core.common.registry.RegistryChangeListener.impl do |method, element|
|
76
|
+
next unless method == :removed
|
77
|
+
|
78
|
+
logger.trace("Rule #{element.inspect} removed from registry")
|
79
|
+
next unless element.uid == uid
|
80
|
+
|
81
|
+
cleanup
|
82
|
+
$rules.remove_registry_change_listener(@listener)
|
83
|
+
end
|
84
|
+
$rules.add_registry_change_listener(@listener)
|
85
|
+
end
|
86
|
+
|
64
87
|
#
|
65
88
|
# Create the run queue based on guards
|
66
89
|
#
|
@@ -70,9 +93,9 @@ module OpenHAB
|
|
70
93
|
def create_queue(inputs)
|
71
94
|
case check_guards(event: extract_event(inputs))
|
72
95
|
when true
|
73
|
-
@run_queue.dup.grep_v(
|
96
|
+
@run_queue.dup.grep_v(BuilderDSL::Otherwise)
|
74
97
|
when false
|
75
|
-
@run_queue.dup.grep(
|
98
|
+
@run_queue.dup.grep(BuilderDSL::Otherwise)
|
76
99
|
end
|
77
100
|
end
|
78
101
|
|
@@ -166,7 +189,7 @@ module OpenHAB
|
|
166
189
|
event = extract_event(inputs)
|
167
190
|
|
168
191
|
while (task = run_queue.shift)
|
169
|
-
if task.is_a?(
|
192
|
+
if task.is_a?(BuilderDSL::Delay)
|
170
193
|
process_delay_task(inputs, mod, run_queue, task)
|
171
194
|
else
|
172
195
|
process_task(event, task)
|
@@ -183,10 +206,10 @@ module OpenHAB
|
|
183
206
|
def process_task(event, task)
|
184
207
|
ThreadLocal.thread_local(**@thread_locals) do
|
185
208
|
case task
|
186
|
-
when
|
187
|
-
when
|
188
|
-
when
|
189
|
-
when
|
209
|
+
when BuilderDSL::Run then process_run_task(event, task)
|
210
|
+
when BuilderDSL::Script then process_script_task(task)
|
211
|
+
when BuilderDSL::Trigger then process_trigger_task(event, task)
|
212
|
+
when BuilderDSL::Otherwise then process_otherwise_task(event, task)
|
190
213
|
end
|
191
214
|
end
|
192
215
|
end
|
@@ -5,6 +5,7 @@ require "forwardable"
|
|
5
5
|
require_relative "property"
|
6
6
|
require_relative "guard"
|
7
7
|
require_relative "rule_triggers"
|
8
|
+
require_relative "terse"
|
8
9
|
|
9
10
|
Dir[File.expand_path("triggers/*.rb", __dir__)].sort.each do |f|
|
10
11
|
require f
|
@@ -16,10 +17,100 @@ module OpenHAB
|
|
16
17
|
# Creates and manages OpenHAB Rules
|
17
18
|
#
|
18
19
|
module Rules
|
20
|
+
# A rules builder allows you to create OpenHAB rules.
|
19
21
|
#
|
20
|
-
#
|
22
|
+
# Note that all methods on this module are also availabe directly on {OpenHAB::DSL}.
|
21
23
|
#
|
22
24
|
class Builder
|
25
|
+
include Terse
|
26
|
+
|
27
|
+
# @return [org.openhab.core.automation.RuleProvider]
|
28
|
+
attr_reader :provider
|
29
|
+
|
30
|
+
def initialize(provider)
|
31
|
+
@provider = Core::Rules::Provider.current(provider)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Create a new rule
|
36
|
+
#
|
37
|
+
# @param [String] name The rule name
|
38
|
+
# @yield Block executed in the context of a {Rules::Builder}
|
39
|
+
# @yieldparam [Rules::Builder] rule
|
40
|
+
# Optional parameter to access the rule configuration from within execution blocks and guards.
|
41
|
+
# @return [Rule]
|
42
|
+
#
|
43
|
+
# @see OpenHAB::DSL::Rules::Builder Rule builder for details on rule triggers, guards and execution blocks
|
44
|
+
# @see Rules::Terse Terse Rules
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# require "openhab/dsl"
|
48
|
+
#
|
49
|
+
# rule "name" do
|
50
|
+
# <zero or more triggers>
|
51
|
+
# <zero or more execution blocks>
|
52
|
+
# <zero or more guards>
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
def rule(name = nil, id: nil, script: nil, binding: nil, &block)
|
56
|
+
raise ArgumentError, "Block is required" unless block
|
57
|
+
|
58
|
+
id ||= NameInference.infer_rule_id_from_block(block)
|
59
|
+
script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
|
60
|
+
|
61
|
+
builder = nil
|
62
|
+
|
63
|
+
ThreadLocal.thread_local(openhab_rule_type: "rule", openhab_rule_uid: id) do
|
64
|
+
builder = BuilderDSL.new(binding || block.binding)
|
65
|
+
builder.uid(id)
|
66
|
+
builder.instance_exec(builder, &block)
|
67
|
+
builder.guard = Guard.new(run_context: builder.caller, only_if: builder.only_if,
|
68
|
+
not_if: builder.not_if)
|
69
|
+
|
70
|
+
name ||= NameInference.infer_rule_name(builder)
|
71
|
+
name ||= id
|
72
|
+
|
73
|
+
builder.name(name)
|
74
|
+
logger.trace { builder.inspect }
|
75
|
+
builder.build(provider, script)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Create a new script
|
81
|
+
#
|
82
|
+
# A script is a rule with no triggers. It can be called by various other actions,
|
83
|
+
# such as the Run Rules action.
|
84
|
+
#
|
85
|
+
# @param [String] name A descriptive name
|
86
|
+
# @param [String] id The script's ID
|
87
|
+
# @yield [] Block executed when the script is executed.
|
88
|
+
# @return [Rule]
|
89
|
+
#
|
90
|
+
def script(name = nil, id: nil, script: nil, &block)
|
91
|
+
raise ArgumentError, "Block is required" unless block
|
92
|
+
|
93
|
+
id ||= NameInference.infer_rule_id_from_block(block)
|
94
|
+
name ||= id
|
95
|
+
script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
|
96
|
+
|
97
|
+
builder = nil
|
98
|
+
ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
|
99
|
+
builder = BuilderDSL.new(block.binding)
|
100
|
+
builder.uid(id)
|
101
|
+
builder.tags(["Script"])
|
102
|
+
builder.name(name)
|
103
|
+
builder.script(&block)
|
104
|
+
logger.trace { builder.inspect }
|
105
|
+
builder.build(provider, script)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Rule configuration for OpenHAB Rules engine
|
112
|
+
#
|
113
|
+
class BuilderDSL
|
23
114
|
include Core::EntityLookup
|
24
115
|
include DSL
|
25
116
|
prepend Triggers
|
@@ -703,6 +794,16 @@ module OpenHAB
|
|
703
794
|
|
704
795
|
@ruby_triggers << [:changed, items, { to: to, from: from, duration: duration }]
|
705
796
|
items.each do |item|
|
797
|
+
case item
|
798
|
+
when Core::Things::Thing,
|
799
|
+
Core::Things::ThingUID,
|
800
|
+
Core::Items::GenericItem,
|
801
|
+
Core::Items::GroupItem::Members
|
802
|
+
nil
|
803
|
+
else
|
804
|
+
raise ArgumentError, "items must be a GenericItem, GroupItem::Members, Thing, or ThingUID"
|
805
|
+
end
|
806
|
+
|
706
807
|
logger.trace("Creating changed trigger for entity(#{item}), to(#{to.inspect}), from(#{from.inspect})")
|
707
808
|
|
708
809
|
Array.wrap(from).each do |from_state|
|
@@ -970,6 +1071,13 @@ module OpenHAB
|
|
970
1071
|
@ruby_triggers << [:received_command, items, { command: commands }]
|
971
1072
|
|
972
1073
|
items.each do |item|
|
1074
|
+
case item
|
1075
|
+
when Core::Items::GenericItem,
|
1076
|
+
Core::Items::GroupItem::Members
|
1077
|
+
nil
|
1078
|
+
else
|
1079
|
+
raise ArgumentError, "items must be a GenericItem or GroupItem::Members"
|
1080
|
+
end
|
973
1081
|
commands.each do |cmd|
|
974
1082
|
logger.trace "Creating received command trigger for items #{item.inspect} and commands #{cmd.inspect}"
|
975
1083
|
|
@@ -1160,6 +1268,16 @@ module OpenHAB
|
|
1160
1268
|
updated = Updated.new(rule_triggers: @rule_triggers)
|
1161
1269
|
@ruby_triggers << [:updated, items, { to: to }]
|
1162
1270
|
items.map do |item|
|
1271
|
+
case item
|
1272
|
+
when Core::Things::Thing,
|
1273
|
+
Core::Things::ThingUID,
|
1274
|
+
Core::Items::GenericItem,
|
1275
|
+
Core::Items::GroupItem::Members
|
1276
|
+
nil
|
1277
|
+
else
|
1278
|
+
raise ArgumentError, "items must be a GenericItem, GroupItem::Members, Thing, or ThingUID"
|
1279
|
+
end
|
1280
|
+
|
1163
1281
|
logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
|
1164
1282
|
[to].flatten.map do |to_state|
|
1165
1283
|
updated.trigger(item: item, to: to_state, attach: attach)
|
@@ -1292,12 +1410,11 @@ module OpenHAB
|
|
1292
1410
|
# @param [String] script The source code of the rule
|
1293
1411
|
#
|
1294
1412
|
# @!visibility private
|
1295
|
-
def build(script)
|
1413
|
+
def build(provider, script)
|
1296
1414
|
return unless create_rule?
|
1297
1415
|
|
1298
|
-
rule = AutomationRule.new(
|
1299
|
-
added_rule = add_rule(rule)
|
1300
|
-
Rules.script_rules[rule.uid] = rule
|
1416
|
+
rule = AutomationRule.new(self)
|
1417
|
+
added_rule = add_rule(provider, rule)
|
1301
1418
|
# add config so that MainUI can show the script
|
1302
1419
|
added_rule.actions.first.configuration.put("type", "application/x-ruby")
|
1303
1420
|
added_rule.actions.first.configuration.put("script", script)
|
@@ -1356,8 +1473,7 @@ module OpenHAB
|
|
1356
1473
|
#
|
1357
1474
|
# @param [org.openhab.core.automation.module.script.rulesupport.shared.simple.SimpleRule] rule to add
|
1358
1475
|
#
|
1359
|
-
|
1360
|
-
def add_rule(rule)
|
1476
|
+
def add_rule(provider, rule)
|
1361
1477
|
base_uid = rule.uid
|
1362
1478
|
duplicate_index = 1
|
1363
1479
|
while $rules.get(rule.uid)
|
@@ -1365,7 +1481,9 @@ module OpenHAB
|
|
1365
1481
|
rule.uid = "#{base_uid} (#{duplicate_index})"
|
1366
1482
|
end
|
1367
1483
|
logger.trace("Adding rule: #{rule}")
|
1368
|
-
Core.automation_manager.
|
1484
|
+
unmanaged_rule = Core.automation_manager.add_unmanaged_rule(rule)
|
1485
|
+
provider.add(unmanaged_rule)
|
1486
|
+
unmanaged_rule
|
1369
1487
|
end
|
1370
1488
|
end
|
1371
1489
|
end
|
@@ -23,11 +23,6 @@ module OpenHAB
|
|
23
23
|
private_constant :KNOWN_TRIGGER_TYPES
|
24
24
|
|
25
25
|
class << self
|
26
|
-
# takes a freeform rule name and makes it more palatable as an id
|
27
|
-
def infer_rule_id_from_name(name)
|
28
|
-
name.downcase.delete("'\"").gsub(/\W+/, "_")
|
29
|
-
end
|
30
|
-
|
31
26
|
# get the block's source location, and simplify to a simple filename
|
32
27
|
def infer_rule_id_from_block(block)
|
33
28
|
file = File.basename(block.source_location.first)
|
@@ -26,13 +26,12 @@ module OpenHAB
|
|
26
26
|
# @param id [String] The ID for the rule.
|
27
27
|
# @yield The execution block for the rule.
|
28
28
|
# @return [void]
|
29
|
-
# @see
|
29
|
+
# @see BuilderDSL#$1
|
30
30
|
def def_terse_rule(trigger)
|
31
31
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
32
32
|
def #{trigger}(*args, name: nil, id: nil, **kwargs, &block) # def changed(*args, name: nil, id: nil, **kwargs, &block)
|
33
33
|
raise ArgumentError, "Block is required" unless block # raise ArgumentError, "Block is required" unless block
|
34
34
|
#
|
35
|
-
id ||= NameInference.infer_rule_id_from_name(name) if name # id ||= NameInference.infer_rule_id_from_name(name) if name
|
36
35
|
id ||= NameInference.infer_rule_id_from_block(block) # id ||= NameInference.infer_rule_id_from_block(block)
|
37
36
|
script = block.source rescue nil # script = block.source rescue nil
|
38
37
|
caller_binding = block.binding # caller_binding = block.binding
|
@@ -107,10 +107,13 @@ module OpenHAB
|
|
107
107
|
#
|
108
108
|
def changed_trigger(item:, from:, to:, attach: nil, conditions: nil)
|
109
109
|
type, config = case item
|
110
|
-
when GroupItem::Members
|
111
|
-
|
112
|
-
when Core::Things::Thing
|
113
|
-
|
110
|
+
when GroupItem::Members
|
111
|
+
group(group: item, from: from, to: to)
|
112
|
+
when Core::Things::Thing,
|
113
|
+
Core::Things::ThingUID
|
114
|
+
thing(thing: item, from: from, to: to)
|
115
|
+
else
|
116
|
+
item(item: item, from: from, to: to)
|
114
117
|
end
|
115
118
|
append_trigger(type: type, config: config, attach: attach, conditions: conditions)
|
116
119
|
end
|
@@ -6,19 +6,12 @@ module OpenHAB
|
|
6
6
|
module Triggers
|
7
7
|
# @!visibility private
|
8
8
|
module Conditions
|
9
|
-
#
|
10
|
-
# this is a no-op condition which simply executes the provided block
|
11
|
-
#
|
12
|
-
|
13
9
|
#
|
14
10
|
# Struct capturing data necessary for a conditional trigger
|
15
11
|
#
|
16
|
-
# TriggerDelay = Struct.new(:to, :from, :duration, :timer, :tracking_to, keyword_init: true) do
|
17
|
-
# def timer_active?
|
18
|
-
# timer&.active?
|
19
|
-
# end
|
20
|
-
# end
|
21
12
|
class Duration
|
13
|
+
attr_accessor :rule
|
14
|
+
|
22
15
|
#
|
23
16
|
# Create a new duration condition
|
24
17
|
# @param [Object] to optional condition on to state
|
@@ -39,7 +32,17 @@ module OpenHAB
|
|
39
32
|
# @param [Hash] inputs inputs from trigger
|
40
33
|
#
|
41
34
|
def process(mod:, inputs:, &block)
|
42
|
-
|
35
|
+
if @timer&.active?
|
36
|
+
process_active_timer(inputs, mod, &block)
|
37
|
+
elsif check_trigger_guards(inputs)
|
38
|
+
logger.trace("Trigger Guards Matched for #{self}, delaying rule execution")
|
39
|
+
# Add timer and attach timer to delay object, and also state being tracked to so
|
40
|
+
# timer can be cancelled if state changes
|
41
|
+
# Also another timer should not be created if changed to same value again but instead rescheduled
|
42
|
+
create_trigger_delay_timer(inputs, mod, &block)
|
43
|
+
else
|
44
|
+
logger.trace("Trigger Guards did not match for #{self}, ignoring trigger.")
|
45
|
+
end
|
43
46
|
end
|
44
47
|
|
45
48
|
# Cleanup any resources from the condition
|
@@ -51,13 +54,6 @@ module OpenHAB
|
|
51
54
|
|
52
55
|
private
|
53
56
|
|
54
|
-
#
|
55
|
-
# Checks if there is an active timer
|
56
|
-
# @return [true, false] true if the timer exists and is active, false otherwise
|
57
|
-
def timer_active?
|
58
|
-
@timer&.active?
|
59
|
-
end
|
60
|
-
|
61
57
|
#
|
62
58
|
# Check if trigger guards prevent rule execution
|
63
59
|
#
|
@@ -79,44 +75,12 @@ module OpenHAB
|
|
79
75
|
# @return [Array] An array of the values for [newState, oldState] or [newStatus, oldStatus]
|
80
76
|
#
|
81
77
|
def retrieve_states(inputs)
|
82
|
-
new_state = inputs["newState"] ||
|
83
|
-
old_state = inputs["oldState"] ||
|
78
|
+
new_state = inputs["newState"] || inputs["newStatus"]&.to_s&.downcase&.to_sym
|
79
|
+
old_state = inputs["oldState"] || inputs["oldStatus"]&.to_s&.downcase&.to_sym
|
84
80
|
|
85
81
|
[new_state, old_state]
|
86
82
|
end
|
87
83
|
|
88
|
-
#
|
89
|
-
# Converts a ThingStatus object to a ruby Symbol
|
90
|
-
#
|
91
|
-
# @param [org.openhab.core.thing.ThingStatus] status A ThingStatus instance
|
92
|
-
#
|
93
|
-
# @return [Symbol] A corresponding symbol, in lower case
|
94
|
-
#
|
95
|
-
def thing_status_to_sym(status)
|
96
|
-
status&.to_s&.downcase&.to_sym
|
97
|
-
end
|
98
|
-
|
99
|
-
#
|
100
|
-
# Process any matching trigger delays
|
101
|
-
#
|
102
|
-
# @param [Map] mod OpenHAB map object describing rule trigger
|
103
|
-
# @param [Map] inputs OpenHAB map object describing rule trigger
|
104
|
-
#
|
105
|
-
#
|
106
|
-
def process_trigger_delay(mod, inputs, &block)
|
107
|
-
if timer_active?
|
108
|
-
process_active_timer(inputs, mod, &block)
|
109
|
-
elsif check_trigger_guards(inputs)
|
110
|
-
logger.trace("Trigger Guards Matched for #{self}, delaying rule execution")
|
111
|
-
# Add timer and attach timer to delay object, and also state being tracked to so
|
112
|
-
# timer can be cancelled if state changes
|
113
|
-
# Also another timer should not be created if changed to same value again but instead rescheduled
|
114
|
-
create_trigger_delay_timer(inputs, mod, &block)
|
115
|
-
else
|
116
|
-
logger.trace("Trigger Guards did not match for #{self}, ignoring trigger.")
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
84
|
#
|
121
85
|
# Creates a timer for trigger delays
|
122
86
|
#
|
@@ -131,6 +95,7 @@ module OpenHAB
|
|
131
95
|
@timer = nil
|
132
96
|
yield
|
133
97
|
end
|
98
|
+
rule.on_removal(self)
|
134
99
|
@tracking_to, = retrieve_states(inputs)
|
135
100
|
end
|
136
101
|
|
@@ -140,7 +105,6 @@ module OpenHAB
|
|
140
105
|
# @param [Hash] inputs rule trigger inputs
|
141
106
|
# @param [Hash] mod rule trigger mods
|
142
107
|
#
|
143
|
-
#
|
144
108
|
def process_active_timer(inputs, mod, &block)
|
145
109
|
state, = retrieve_states(inputs)
|
146
110
|
if state == @tracking_to
|
@@ -150,7 +114,7 @@ module OpenHAB
|
|
150
114
|
logger.trace("Item changed to #{state} for #{self}, canceling timer.")
|
151
115
|
@timer.cancel
|
152
116
|
# Reprocess trigger delay after canceling to track new state (if guards matched, etc)
|
153
|
-
|
117
|
+
process(mod: mod, inputs: inputs, &block)
|
154
118
|
end
|
155
119
|
end
|
156
120
|
end
|
@@ -84,9 +84,6 @@ module OpenHAB
|
|
84
84
|
yield if check_procs(inputs: inputs)
|
85
85
|
end
|
86
86
|
|
87
|
-
# Cleanup any resources from the condition
|
88
|
-
def cleanup; end
|
89
|
-
|
90
87
|
#
|
91
88
|
# Check if command condition match the proc
|
92
89
|
# @param [Hash] inputs from trigger must be supplied if state is not supplied
|
@@ -33,7 +33,7 @@ module OpenHAB
|
|
33
33
|
# @return [Array] Trigger and config for thing
|
34
34
|
#
|
35
35
|
def trigger_for_thing(thing:, type:, to: nil, from: nil)
|
36
|
-
config = { "thingUID" => thing.
|
36
|
+
config = { "thingUID" => thing.to_s }
|
37
37
|
config["status"] = trigger_state_from_symbol(to).to_s if to
|
38
38
|
config["previousStatus"] = trigger_state_from_symbol(from).to_s if from
|
39
39
|
[type, config]
|
@@ -74,9 +74,13 @@ module OpenHAB
|
|
74
74
|
#
|
75
75
|
def update_trigger(item:, to:, attach: nil, conditions: nil)
|
76
76
|
type, config = case item
|
77
|
-
when GroupItem::Members
|
78
|
-
|
79
|
-
|
77
|
+
when GroupItem::Members
|
78
|
+
group_update(item: item, to: to)
|
79
|
+
when Core::Things::Thing,
|
80
|
+
Core::Things::ThingUID
|
81
|
+
thing_update(thing: item, to: to)
|
82
|
+
else
|
83
|
+
item_update(item: item, to: to)
|
80
84
|
end
|
81
85
|
append_trigger(type: type, config: config, attach: attach, conditions: conditions)
|
82
86
|
end
|
@@ -98,8 +98,8 @@ module OpenHAB
|
|
98
98
|
#
|
99
99
|
def watch_event_handler(glob)
|
100
100
|
lambda { |watch_event|
|
101
|
-
logger.trace("Received event(#{watch_event})")
|
102
101
|
if watch_event.path.fnmatch?(glob)
|
102
|
+
logger.trace("Received event(#{watch_event})")
|
103
103
|
@rule_engine_callback&.triggered(@trigger, { "event" => watch_event })
|
104
104
|
else
|
105
105
|
logger.trace("Event #{watch_event} did not match glob(#{glob})")
|
data/lib/openhab/dsl/rules.rb
CHANGED
@@ -1,29 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "script_handling"
|
4
|
-
|
5
3
|
module OpenHAB
|
6
4
|
module DSL
|
7
5
|
module Rules
|
8
|
-
@script_rules = {}
|
9
|
-
|
10
|
-
@scripted_rule_provider = OSGi.service(
|
11
|
-
"org.openhab.core.automation.module.script.rulesupport.shared.ScriptedRuleProvider"
|
12
|
-
)
|
13
|
-
class << self
|
14
|
-
# @!visibility private
|
15
|
-
attr_reader :script_rules, :scripted_rule_provider
|
16
|
-
|
17
|
-
#
|
18
|
-
# Cleanup rules in this script file
|
19
|
-
#
|
20
|
-
# @return [void]
|
21
|
-
#
|
22
|
-
def cleanup_rules
|
23
|
-
script_rules.each_value(&:cleanup)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
ScriptHandling.script_unloaded { cleanup_rules }
|
27
6
|
end
|
28
7
|
end
|
29
8
|
end
|
@@ -2,54 +2,5 @@
|
|
2
2
|
|
3
3
|
module OpenHAB
|
4
4
|
module DSL
|
5
|
-
#
|
6
|
-
# Provide callback mechanisms for script handling
|
7
|
-
#
|
8
|
-
module ScriptHandling
|
9
|
-
module_function
|
10
|
-
|
11
|
-
#
|
12
|
-
# Add a block of code to be executed once the rule script has finished loading.
|
13
|
-
#
|
14
|
-
# This can occur on OpenHAB start up, when the script is first created, or updated.
|
15
|
-
#
|
16
|
-
# Multiple hooks can be added by calling {#script_loaded} multiple times.
|
17
|
-
# They can be used to perform final initializations.
|
18
|
-
#
|
19
|
-
# @return [void]
|
20
|
-
#
|
21
|
-
# @example
|
22
|
-
# script_loaded do
|
23
|
-
# logger.info 'Hi, this script has just finished loading'
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# @example
|
27
|
-
# script_loaded do
|
28
|
-
# logger.info 'I will be called after the script finished loading too'
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
def script_loaded(&block)
|
32
|
-
Core::ScriptHandlingCallbacks.script_loaded_hooks << block
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
|
-
# Add a block of code to be executed when the script is unloaded.
|
37
|
-
#
|
38
|
-
# This can occur when OpenHAB shuts down, or when the script is being reloaded.
|
39
|
-
#
|
40
|
-
# Multiple hooks can be added by calling {#script_unloaded} multiple times.
|
41
|
-
# They can be used to perform final cleanup.
|
42
|
-
#
|
43
|
-
# @return [void]
|
44
|
-
#
|
45
|
-
# @example
|
46
|
-
# script_unloaded do
|
47
|
-
# logger.info 'Hi, this script has been unloaded'
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
def script_unloaded(&block)
|
51
|
-
Core::ScriptHandlingCallbacks.script_unloaded_hooks << block
|
52
|
-
end
|
53
|
-
end
|
54
5
|
end
|
55
6
|
end
|
@@ -6,36 +6,6 @@ module OpenHAB
|
|
6
6
|
# Contains extensions to simplify working with {Core::Things::Thing Thing}s.
|
7
7
|
#
|
8
8
|
module Things
|
9
|
-
# Stores all things created in scripts, and notifies the ThingRegistry
|
10
|
-
# of their existence
|
11
|
-
# aa@!visibility private
|
12
|
-
class ThingProvider < org.openhab.core.common.registry.AbstractProvider
|
13
|
-
include org.openhab.core.thing.ThingProvider
|
14
|
-
include Singleton
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
super
|
18
|
-
|
19
|
-
@things = []
|
20
|
-
|
21
|
-
$things.add_provider(self)
|
22
|
-
ScriptHandling.script_unloaded { $things.remove_provider(self) }
|
23
|
-
end
|
24
|
-
|
25
|
-
# Add a thing to this provider
|
26
|
-
def add(thing)
|
27
|
-
thing = thing.build
|
28
|
-
@things << thing
|
29
|
-
notify_listeners_about_added_element(thing)
|
30
|
-
thing
|
31
|
-
end
|
32
|
-
|
33
|
-
# Get all items in this provider
|
34
|
-
def getAll # rubocop:disable Naming/MethodName required by java interface
|
35
|
-
@things
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
9
|
# A thing builder allows you to dynamically create OpenHAB thing at runtime.
|
40
10
|
# This can be useful either to create things as soon as the script loads,
|
41
11
|
# or even later based on a rule executing.
|
@@ -45,6 +15,13 @@ module OpenHAB
|
|
45
15
|
# thing "astro:sun:home", "Astro Sun Data", config: { "geolocation" => "0,0" }
|
46
16
|
# end
|
47
17
|
class Builder
|
18
|
+
# @return [org.openhab.core.things.ManagedThingProvider]
|
19
|
+
attr_reader :provider
|
20
|
+
|
21
|
+
def initialize(provider)
|
22
|
+
@provider = Core::Things::Provider.current(provider)
|
23
|
+
end
|
24
|
+
|
48
25
|
# Create a new Bridge
|
49
26
|
# @see BridgeBuilder#initialize
|
50
27
|
def bridge(*args, **kwargs, &block)
|
@@ -62,7 +39,7 @@ module OpenHAB
|
|
62
39
|
def build(klass, *args, **kwargs, &block)
|
63
40
|
builder = klass.new(*args, **kwargs)
|
64
41
|
builder.instance_eval(&block) if block
|
65
|
-
thing =
|
42
|
+
thing = provider.add(builder.build)
|
66
43
|
thing = Core::Things::Proxy.new(thing)
|
67
44
|
thing.enable(enabled: builder.enabled) unless builder.enabled.nil?
|
68
45
|
thing
|