openhab-scripting 2.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/workflow.yml +327 -0
- data/.gitignore +17 -0
- data/.java-version +1 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +113 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +245 -0
- data/Guardfile +35 -0
- data/LICENSE +277 -0
- data/README.md +23 -0
- data/Rakefile +406 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/config/userdata/config/org/openhab/restauth.config +3 -0
- data/cucumber.yml +1 -0
- data/docs/_config.yml +135 -0
- data/docs/contributing/index.md +47 -0
- data/docs/examples/conversions.md +123 -0
- data/docs/examples/index.md +61 -0
- data/docs/index.md +19 -0
- data/docs/installation/index.md +26 -0
- data/docs/motivation/index.md +27 -0
- data/docs/usage/execution.md +9 -0
- data/docs/usage/execution/delay.md +48 -0
- data/docs/usage/execution/otherwise.md +30 -0
- data/docs/usage/execution/run.md +70 -0
- data/docs/usage/execution/triggered.md +48 -0
- data/docs/usage/guards.md +51 -0
- data/docs/usage/guards/between.md +30 -0
- data/docs/usage/guards/not_if.md +41 -0
- data/docs/usage/guards/only_if.md +40 -0
- data/docs/usage/index.md +11 -0
- data/docs/usage/items.md +66 -0
- data/docs/usage/items/contact.md +84 -0
- data/docs/usage/items/dimmer.md +147 -0
- data/docs/usage/items/groups.md +76 -0
- data/docs/usage/items/number.md +225 -0
- data/docs/usage/items/string.md +49 -0
- data/docs/usage/items/switch.md +85 -0
- data/docs/usage/misc.md +7 -0
- data/docs/usage/misc/actions.md +108 -0
- data/docs/usage/misc/duration.md +21 -0
- data/docs/usage/misc/gems.md +25 -0
- data/docs/usage/misc/logging.md +21 -0
- data/docs/usage/misc/metadata.md +128 -0
- data/docs/usage/misc/store_states.md +42 -0
- data/docs/usage/misc/time_of_day.md +69 -0
- data/docs/usage/misc/timers.md +67 -0
- data/docs/usage/rule.md +43 -0
- data/docs/usage/things.md +29 -0
- data/docs/usage/triggers.md +8 -0
- data/docs/usage/triggers/changed.md +57 -0
- data/docs/usage/triggers/channel.md +54 -0
- data/docs/usage/triggers/command.md +69 -0
- data/docs/usage/triggers/cron.md +19 -0
- data/docs/usage/triggers/every.md +76 -0
- data/docs/usage/triggers/updated.md +78 -0
- data/lib/openhab.rb +39 -0
- data/lib/openhab/configuration.rb +16 -0
- data/lib/openhab/core/cron.rb +27 -0
- data/lib/openhab/core/debug.rb +34 -0
- data/lib/openhab/core/dsl.rb +47 -0
- data/lib/openhab/core/dsl/actions.rb +107 -0
- data/lib/openhab/core/dsl/entities.rb +103 -0
- data/lib/openhab/core/dsl/gems.rb +29 -0
- data/lib/openhab/core/dsl/group.rb +91 -0
- data/lib/openhab/core/dsl/items/items.rb +39 -0
- data/lib/openhab/core/dsl/items/number_item.rb +217 -0
- data/lib/openhab/core/dsl/items/string_item.rb +102 -0
- data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +4 -0
- data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +22 -0
- data/lib/openhab/core/dsl/monkey_patch/events.rb +5 -0
- data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +13 -0
- data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +25 -0
- data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +26 -0
- data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +54 -0
- data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +125 -0
- data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +27 -0
- data/lib/openhab/core/dsl/monkey_patch/items/items.rb +130 -0
- data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +259 -0
- data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +86 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +69 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +46 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +5 -0
- data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +24 -0
- data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +41 -0
- data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +25 -0
- data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +23 -0
- data/lib/openhab/core/dsl/monkey_patch/types/types.rb +7 -0
- data/lib/openhab/core/dsl/property.rb +85 -0
- data/lib/openhab/core/dsl/rule/channel.rb +41 -0
- data/lib/openhab/core/dsl/rule/cron.rb +115 -0
- data/lib/openhab/core/dsl/rule/guard.rb +99 -0
- data/lib/openhab/core/dsl/rule/item.rb +207 -0
- data/lib/openhab/core/dsl/rule/rule.rb +374 -0
- data/lib/openhab/core/dsl/rule/triggers.rb +77 -0
- data/lib/openhab/core/dsl/states.rb +63 -0
- data/lib/openhab/core/dsl/things.rb +93 -0
- data/lib/openhab/core/dsl/time_of_day.rb +203 -0
- data/lib/openhab/core/dsl/timers.rb +85 -0
- data/lib/openhab/core/dsl/types/quantity.rb +255 -0
- data/lib/openhab/core/dsl/units.rb +41 -0
- data/lib/openhab/core/duration.rb +69 -0
- data/lib/openhab/core/log.rb +175 -0
- data/lib/openhab/core/patch_load_path.rb +7 -0
- data/lib/openhab/core/startup_delay.rb +22 -0
- data/lib/openhab/osgi.rb +52 -0
- data/lib/openhab/version.rb +9 -0
- data/openhab-scripting.gemspec +30 -0
- data/openhab_rules/warmup.rb +5 -0
- metadata +157 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
#
|
6
|
+
# MonkeyPatching Decimal Type
|
7
|
+
#
|
8
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
9
|
+
class Java::OrgOpenhabCoreLibraryTypes::DecimalType
|
10
|
+
# rubocop:enable Style/ClassAndModuleChildren
|
11
|
+
|
12
|
+
#
|
13
|
+
# Compare self to other using Java BigDecimal compare method
|
14
|
+
#
|
15
|
+
# @param [Object] other object to compare to
|
16
|
+
#
|
17
|
+
# @return [Boolean] True if have the same BigDecimal representation, false otherwise
|
18
|
+
#
|
19
|
+
def ==(other)
|
20
|
+
return equals(other) unless other.is_a? Integer
|
21
|
+
|
22
|
+
to_big_decimal.compare_to(Java::JavaMath::BigDecimal.new(other)).zero?
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Monkey patching OnOffType
|
7
|
+
#
|
8
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
9
|
+
class Java::OrgOpenhabCoreLibraryTypes::OnOffType
|
10
|
+
# rubocop:enable Style/ClassAndModuleChildren
|
11
|
+
|
12
|
+
#
|
13
|
+
# Invert the type
|
14
|
+
#
|
15
|
+
# @return [Java::OrgOpenhabCoreLibraryTypes::OnOffType] OFF if ON, ON if OFF
|
16
|
+
#
|
17
|
+
def !
|
18
|
+
return OFF if self == ON
|
19
|
+
return ON if self == OFF
|
20
|
+
end
|
21
|
+
|
22
|
+
# Check if the supplied object is case equals to self
|
23
|
+
#
|
24
|
+
# @param [Object] other object to compare
|
25
|
+
#
|
26
|
+
# @return [Boolean] True if the other object responds to on?/off? and is in the same state as this object,
|
27
|
+
# nil if object cannot be compared
|
28
|
+
#
|
29
|
+
def ===(other)
|
30
|
+
# A case statement here causes and infinite loop
|
31
|
+
# rubocop:disable Style/CaseLikeIf
|
32
|
+
if self == ON
|
33
|
+
other.on? if other.respond_to? :on?
|
34
|
+
elsif self == OFF
|
35
|
+
other.off? if other.respond_to?('off?')
|
36
|
+
else
|
37
|
+
false
|
38
|
+
end
|
39
|
+
# rubocop:enable Style/CaseLikeIf
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Monkey patch for DSL use
|
7
|
+
#
|
8
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
9
|
+
class Java::OrgOpenhabCoreLibraryTypes::OpenClosedType
|
10
|
+
# rubocop:enable Style/ClassAndModuleChildren
|
11
|
+
java_import org.openhab.core.library.items.ContactItem
|
12
|
+
|
13
|
+
#
|
14
|
+
# Check if the supplied object is case equals to self
|
15
|
+
#
|
16
|
+
# @param [Object] other object to compare
|
17
|
+
#
|
18
|
+
# @return [Boolean] True if the other object is a ContactItem and has the same state
|
19
|
+
#
|
20
|
+
def ===(other)
|
21
|
+
super unless other.is_a? ContactItem
|
22
|
+
|
23
|
+
self == other.state
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
#
|
6
|
+
# MonkeyPatching PercentType
|
7
|
+
#
|
8
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
9
|
+
class Java::OrgOpenhabCoreLibraryTypes::PercentType
|
10
|
+
# rubocop:enable Style/ClassAndModuleChildren
|
11
|
+
|
12
|
+
#
|
13
|
+
# Need to override and point to super because default JRuby implementation doesn't point to == of parent class
|
14
|
+
#
|
15
|
+
# @param [Object] other object to check equality for
|
16
|
+
# @return [Boolean] True if other equals self, false otherwise
|
17
|
+
#
|
18
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
19
|
+
def ==(other)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
# rubocop:enable Lint/UselessMethodDefinition
|
23
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Monkey patch types
|
4
|
+
require 'core/dsl/monkey_patch/types/open_closed_type'
|
5
|
+
require 'core/dsl/monkey_patch/types/on_off_type'
|
6
|
+
require 'core/dsl/monkey_patch/types/decimal_type'
|
7
|
+
require 'core/dsl/monkey_patch/types/percent_type'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'core/log'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Provides methods to support DSL properties
|
7
|
+
#
|
8
|
+
module DSLProperty
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
#
|
12
|
+
# Extend the calling object with the property methods
|
13
|
+
#
|
14
|
+
# @param [Object] base object to extend
|
15
|
+
#
|
16
|
+
#
|
17
|
+
def self.included(base)
|
18
|
+
base.extend PropertyMethods
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Methods that support creating properties in the DSL
|
23
|
+
#
|
24
|
+
module PropertyMethods
|
25
|
+
#
|
26
|
+
# Dynamically creates a property that acts and an accessor with no arguments
|
27
|
+
# and a setter with any number of arguments or a block.
|
28
|
+
#
|
29
|
+
# @param [String] name of the property
|
30
|
+
#
|
31
|
+
#
|
32
|
+
def prop(name)
|
33
|
+
define_method(name) do |*args, &block|
|
34
|
+
if args.length.zero? && block.nil? == true
|
35
|
+
instance_variable_get("@#{name}")
|
36
|
+
else
|
37
|
+
logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
|
38
|
+
if args.length == 1
|
39
|
+
instance_variable_set("@#{name}", args.first)
|
40
|
+
elsif args.length > 1
|
41
|
+
instance_variable_set("@#{name}", args)
|
42
|
+
elsif block
|
43
|
+
instance_variable_set("@#{name}", block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Dynamically creates a property array acts and an accessor with no arguments
|
51
|
+
# and a pushes any number of arguments or a block onto they property array
|
52
|
+
# You can provide a block to this method which can be used to check if the provided value is acceptable.
|
53
|
+
#
|
54
|
+
# @param [String] name of the property
|
55
|
+
# @param [String] array_name name of the array to use, defaults to name of property
|
56
|
+
# @param [Class] wrapper object to put around elements added to the array
|
57
|
+
#
|
58
|
+
def prop_array(name, array_name: nil, wrapper: nil)
|
59
|
+
define_method(name) do |*args, &block|
|
60
|
+
array_name ||= name
|
61
|
+
if args.length.zero? && block.nil? == true
|
62
|
+
instance_variable_get("@#{array_name}")
|
63
|
+
else
|
64
|
+
logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
|
65
|
+
if args.length == 1
|
66
|
+
insert = args.first
|
67
|
+
elsif args.length > 1
|
68
|
+
insert = args
|
69
|
+
elsif block
|
70
|
+
insert = block
|
71
|
+
end
|
72
|
+
yield insert if block_given?
|
73
|
+
insert = wrapper.new(insert) if wrapper
|
74
|
+
instance_variable_set("@#{array_name}", (instance_variable_get("@#{array_name}") || []) << insert)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if array_name
|
79
|
+
define_method(array_name) do
|
80
|
+
instance_variable_get("@#{array_name}")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'core/log'
|
4
|
+
require 'openhab/core/dsl/rule/triggers'
|
5
|
+
|
6
|
+
module OpenHAB
|
7
|
+
module Core
|
8
|
+
module DSL
|
9
|
+
module Rule
|
10
|
+
#
|
11
|
+
# Channel triggers
|
12
|
+
#
|
13
|
+
module Channel
|
14
|
+
include Logging
|
15
|
+
|
16
|
+
#
|
17
|
+
# Creates a channel trigger
|
18
|
+
#
|
19
|
+
# @param [Array] channels array to create triggers for on form of 'binding_id:type_id:thing_id#channel_id' or 'channel_id' if thing is provided
|
20
|
+
# @param [thing] thing to create trigger for if not specified with the channel
|
21
|
+
# @param [String] triggered specific triggering condition to match for trigger
|
22
|
+
#
|
23
|
+
#
|
24
|
+
def channel(*channels, thing: nil, triggered: nil)
|
25
|
+
channels.flatten.each do |channel|
|
26
|
+
channel = [thing, channel].join(':') if thing
|
27
|
+
logger.trace("Creating channel trigger for channel(#{channel}), thing(#{thing}), trigger(#{triggered})")
|
28
|
+
[triggered].flatten.each do |trigger|
|
29
|
+
config = { 'channelUID' => channel }
|
30
|
+
config['event'] = trigger.to_s unless trigger.nil?
|
31
|
+
config['channelUID'] = channel
|
32
|
+
logger.trace("Creating Change Trigger for #{config}")
|
33
|
+
@triggers << Trigger.trigger(type: Trigger::CHANNEL_EVENT, config: config)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
require 'core/duration'
|
5
|
+
require 'core/dsl/time_of_day'
|
6
|
+
require 'core/cron'
|
7
|
+
|
8
|
+
module OpenHAB
|
9
|
+
module Core
|
10
|
+
module DSL
|
11
|
+
module Rule
|
12
|
+
#
|
13
|
+
# Cron type rules
|
14
|
+
#
|
15
|
+
module Cron
|
16
|
+
java_import org.openhab.core.automation.util.TriggerBuilder
|
17
|
+
java_import org.openhab.core.config.core.Configuration
|
18
|
+
|
19
|
+
include OpenHAB::Core::DSL::Rule
|
20
|
+
extend OpenHAB::Core::Cron
|
21
|
+
|
22
|
+
# @return [Map] Map of days of the week from symbols to to OpenHAB cron strings
|
23
|
+
DAY_OF_WEEK_MAP = {
|
24
|
+
monday: 'MON',
|
25
|
+
tuesday: 'TUE',
|
26
|
+
wednesday: 'WED',
|
27
|
+
thursday: 'THU',
|
28
|
+
friday: 'FRI',
|
29
|
+
saturday: 'SAT',
|
30
|
+
sunday: 'SUN'
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
private_constant :DAY_OF_WEEK_MAP
|
34
|
+
|
35
|
+
# @return [MAP] Converts the DAY_OF_WEEK_MAP to map used by Cron Expression
|
36
|
+
DAY_OF_WEEK_EXPRESSION_MAP = DAY_OF_WEEK_MAP.transform_values { |v| cron_expression_map.merge(dow: v) }
|
37
|
+
|
38
|
+
private_constant :DAY_OF_WEEK_EXPRESSION_MAP
|
39
|
+
|
40
|
+
# @return [Map] Create a set of cron expressions based on different time intervals
|
41
|
+
EXPRESSION_MAP = {
|
42
|
+
second: cron_expression_map,
|
43
|
+
minute: cron_expression_map.merge(second: '0'),
|
44
|
+
hour: cron_expression_map.merge(second: '0', minute: '0'),
|
45
|
+
day: cron_expression_map.merge(second: '0', minute: '0', hour: '0'),
|
46
|
+
week: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dow: 'MON'),
|
47
|
+
month: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dom: '1'),
|
48
|
+
year: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dom: '1', month: '1')
|
49
|
+
}.merge(DAY_OF_WEEK_EXPRESSION_MAP)
|
50
|
+
.freeze
|
51
|
+
|
52
|
+
private_constant :EXPRESSION_MAP
|
53
|
+
|
54
|
+
#
|
55
|
+
# Create a rule that executes at the specified interval
|
56
|
+
#
|
57
|
+
# @param [Object] value Symbol or Duration to execute this rule
|
58
|
+
# @param [Object] at TimeOfDay or String representing TimeOfDay in which to execute rule
|
59
|
+
#
|
60
|
+
#
|
61
|
+
def every(value, at: nil)
|
62
|
+
case value
|
63
|
+
when Symbol
|
64
|
+
expression_map = EXPRESSION_MAP[value]
|
65
|
+
expression_map = at_condition(expression_map, at) if at
|
66
|
+
cron(map_to_cron(expression_map))
|
67
|
+
when Duration
|
68
|
+
cron(map_to_cron(value.cron_map))
|
69
|
+
else
|
70
|
+
raise ArgumentExpression, 'Unknown interval' unless expression_map
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Create a OpenHAB Cron trigger
|
76
|
+
#
|
77
|
+
# @param [String] expression OpenHAB style cron expression
|
78
|
+
#
|
79
|
+
def cron(expression)
|
80
|
+
@triggers << Trigger.trigger(type: Trigger::CRON, config: { 'cronExpression' => expression })
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
#
|
86
|
+
# Map cron expression to to cron string
|
87
|
+
#
|
88
|
+
# @param [Map] map of cron expression
|
89
|
+
#
|
90
|
+
# @return [String] OpenHAB cron string
|
91
|
+
#
|
92
|
+
def map_to_cron(map)
|
93
|
+
%i[second minute hour dom month dow].map { |field| map.fetch(field) }.join(' ')
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# If an at time is provided, parse that and merge the new fields into the expression.
|
98
|
+
#
|
99
|
+
# @param [<Type>] expression_map <description>
|
100
|
+
# @param [<Type>] at_time <description>
|
101
|
+
#
|
102
|
+
# @return [<Type>] <description>
|
103
|
+
#
|
104
|
+
def at_condition(expression_map, at_time)
|
105
|
+
if at_time
|
106
|
+
tod = (at_time.is_a? TimeOfDay) ? at_time : TimeOfDay.parse(at_time)
|
107
|
+
expression_map = expression_map.merge(hour: tod.hour, minute: tod.minute, second: tod.second)
|
108
|
+
end
|
109
|
+
expression_map
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'core/dsl/property'
|
4
|
+
require 'core/log'
|
5
|
+
|
6
|
+
module OpenHAB
|
7
|
+
module Core
|
8
|
+
module DSL
|
9
|
+
module Rule
|
10
|
+
#
|
11
|
+
# Guards for rules
|
12
|
+
#
|
13
|
+
module Guard
|
14
|
+
include DSLProperty
|
15
|
+
|
16
|
+
prop_array(:only_if) do |item|
|
17
|
+
unless item.is_a?(Proc) || item.respond_to?(:truthy?)
|
18
|
+
raise ArgumentError, "Object passed to only_if must respond_to 'truthy?'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
prop_array(:not_if) do |item|
|
23
|
+
unless item.is_a?(Proc) || item.respond_to?(:truthy?)
|
24
|
+
raise ArgumentError, "Object passed to not_if must respond_to 'truthy?'"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Guard that can prevent execute of a rule if not satisfied
|
30
|
+
#
|
31
|
+
class Guard
|
32
|
+
include Logging
|
33
|
+
|
34
|
+
#
|
35
|
+
# Create a new Guard
|
36
|
+
#
|
37
|
+
# @param [Object] only_if Item or Proc to use as guard
|
38
|
+
# @param [Object] not_if Item or Proc to use as guard
|
39
|
+
#
|
40
|
+
def initialize(only_if: nil, not_if: nil)
|
41
|
+
@only_if = only_if
|
42
|
+
@not_if = not_if
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Convert the guard into a string
|
47
|
+
#
|
48
|
+
# @return [String] describing the only_of and not_if guards
|
49
|
+
#
|
50
|
+
def to_s
|
51
|
+
"only_if: #{@only_if}, not_if: #{@not_if}"
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Checks if a guard should run
|
56
|
+
#
|
57
|
+
# @param [OpenHAB Trigger Event] event OpenHAB Trigger Event
|
58
|
+
#
|
59
|
+
# @return [Boolean] True if guard is satisfied, false otherwise
|
60
|
+
#
|
61
|
+
def should_run?(event)
|
62
|
+
logger.trace("Checking guards #{self}")
|
63
|
+
check(@only_if, check_type: :only_if, event: event) && check(@not_if, check_type: :not_if, event: event)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
#
|
69
|
+
# Check if guard is satisfied
|
70
|
+
#
|
71
|
+
# @param [Array] conditions to check
|
72
|
+
# @param [Symbol] check_type type of check to perform (:only_if or :not_if)
|
73
|
+
# @param [Event] event OpenHAB event to see if it satisfies the guard
|
74
|
+
#
|
75
|
+
# @return [Boolean] True if guard is satisfied, false otherwise
|
76
|
+
#
|
77
|
+
def check(conditions, check_type:, event:)
|
78
|
+
return true if conditions.nil? || conditions.empty?
|
79
|
+
|
80
|
+
procs, items = conditions.flatten.partition { |condition| condition.is_a? Proc }
|
81
|
+
logger.trace("Procs: #{procs} Items: #{items}")
|
82
|
+
|
83
|
+
items.each { |item| logger.trace("#{item} truthy? #{item.truthy?}") }
|
84
|
+
|
85
|
+
case check_type
|
86
|
+
when :only_if
|
87
|
+
items.all?(&:truthy?) && procs.all? { |proc| proc.call(event) }
|
88
|
+
when :not_if
|
89
|
+
items.none?(&:truthy?) && procs.none? { |proc| proc.call(event) }
|
90
|
+
else
|
91
|
+
raise ArgumentError, "Unexpected check type: #{check_type}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|