openhab-jrubyscripting 5.0.0.rc1 → 5.0.0.rc3
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/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
|