openhab-scripting 2.15.0 → 2.16.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +12 -16
  3. data/lib/openhab/core/entity_lookup.rb +162 -0
  4. data/lib/openhab/core/openhab_setup.rb +31 -0
  5. data/lib/openhab/core/osgi.rb +61 -0
  6. data/lib/openhab/dsl/actions.rb +105 -0
  7. data/lib/openhab/dsl/dsl.rb +47 -0
  8. data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
  9. data/lib/openhab/dsl/group.rb +100 -0
  10. data/lib/openhab/dsl/items/items.rb +46 -0
  11. data/lib/openhab/dsl/items/number_item.rb +352 -0
  12. data/lib/openhab/dsl/items/string_item.rb +120 -0
  13. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
  14. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
  15. data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
  16. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
  17. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
  18. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
  19. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
  20. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
  21. data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
  22. data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
  23. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
  24. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
  25. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
  26. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
  27. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
  28. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +7 -0
  29. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
  30. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
  31. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
  32. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
  33. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
  34. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
  35. data/lib/openhab/dsl/monkey_patch/types/types.rb +8 -0
  36. data/lib/openhab/dsl/persistence.rb +25 -0
  37. data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
  38. data/lib/openhab/dsl/rules/guard.rb +134 -0
  39. data/lib/openhab/dsl/rules/property.rb +102 -0
  40. data/lib/openhab/dsl/rules/rule.rb +116 -0
  41. data/lib/openhab/dsl/rules/rule_config.rb +151 -0
  42. data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
  43. data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
  44. data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
  45. data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
  46. data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
  47. data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
  48. data/lib/openhab/dsl/states.rb +61 -0
  49. data/lib/openhab/dsl/things.rb +91 -0
  50. data/lib/openhab/dsl/time_of_day.rb +228 -0
  51. data/lib/openhab/dsl/timers.rb +77 -0
  52. data/lib/openhab/dsl/types/quantity.rb +290 -0
  53. data/lib/openhab/dsl/units.rb +39 -0
  54. data/lib/openhab/log/configuration.rb +21 -0
  55. data/lib/openhab/log/logger.rb +172 -0
  56. data/lib/openhab/version.rb +1 -1
  57. metadata +55 -56
  58. data/lib/openhab/configuration.rb +0 -16
  59. data/lib/openhab/core/cron.rb +0 -27
  60. data/lib/openhab/core/debug.rb +0 -34
  61. data/lib/openhab/core/dsl.rb +0 -51
  62. data/lib/openhab/core/dsl/actions.rb +0 -107
  63. data/lib/openhab/core/dsl/entities.rb +0 -140
  64. data/lib/openhab/core/dsl/group.rb +0 -93
  65. data/lib/openhab/core/dsl/items/items.rb +0 -51
  66. data/lib/openhab/core/dsl/items/number_item.rb +0 -318
  67. data/lib/openhab/core/dsl/items/string_item.rb +0 -120
  68. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
  69. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
  70. data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
  71. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
  72. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
  73. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
  74. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
  75. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -167
  76. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
  77. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
  78. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
  79. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
  80. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
  81. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
  82. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
  83. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -6
  84. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -24
  85. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
  86. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
  87. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
  88. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -7
  89. data/lib/openhab/core/dsl/persistence.rb +0 -27
  90. data/lib/openhab/core/dsl/property.rb +0 -96
  91. data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -348
  92. data/lib/openhab/core/dsl/rule/guard.rb +0 -136
  93. data/lib/openhab/core/dsl/rule/rule.rb +0 -117
  94. data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
  95. data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
  96. data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
  97. data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
  98. data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
  99. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
  100. data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
  101. data/lib/openhab/core/dsl/states.rb +0 -63
  102. data/lib/openhab/core/dsl/things.rb +0 -93
  103. data/lib/openhab/core/dsl/time_of_day.rb +0 -229
  104. data/lib/openhab/core/dsl/timers.rb +0 -79
  105. data/lib/openhab/core/dsl/types/quantity.rb +0 -292
  106. data/lib/openhab/core/dsl/units.rb +0 -41
  107. data/lib/openhab/core/log.rb +0 -170
  108. data/lib/openhab/core/patch_load_path.rb +0 -7
  109. data/lib/openhab/core/startup_delay.rb +0 -23
  110. data/lib/openhab/osgi.rb +0 -59
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- java_import org.openhab.core.library.items.SwitchItem
4
-
5
- # Alias class names for easy is_a? comparisons
6
- Switch = SwitchItem
7
-
8
- #
9
- # Monkeypatching SwitchItem to add Ruby Support methods
10
- #
11
- # rubocop:disable Style/ClassAndModuleChildren
12
- class Java::OrgOpenhabCoreLibraryItems::SwitchItem
13
- java_import org.openhab.core.library.types.OnOffType
14
- # rubocop:enable Style/ClassAndModuleChildren
15
-
16
- #
17
- # Send the OFF command to the switch
18
- #
19
- #
20
- def off
21
- command(OnOffType::OFF)
22
- end
23
-
24
- #
25
- # Send the OFF command to the switch
26
- #
27
- #
28
- def on
29
- command(OnOffType::ON)
30
- end
31
-
32
- #
33
- # Check if a switch is on
34
- #
35
- # @return [Boolean] True if the switch is on, false otherwise
36
- #
37
- def on?
38
- state? && state == OnOffType::ON
39
- end
40
-
41
- alias truthy? on?
42
-
43
- #
44
- # Check if a switch is off
45
- #
46
- # @return [Boolean] True if the switch is off, false otherwise
47
- #
48
- def off?
49
- state? && state == OnOffType::OFF
50
- end
51
-
52
- #
53
- # Send a command to invert the state of the switch
54
- #
55
- # @return [OnOffType] Inverted state
56
- #
57
- def toggle
58
- self << !self
59
- end
60
-
61
- #
62
- # Return the inverted state of the switch: ON if the switch is OFF, UNDEF or NULL; OFF if the switch is ON
63
- #
64
- # @return [OnOffType] Inverted state
65
- #
66
- def !
67
- return !state if state?
68
-
69
- OnOffType::ON
70
- end
71
-
72
- #
73
- # Check for equality against supplied object
74
- #
75
- # @param [Object] other object to compare to
76
- #
77
- # @return [Boolean] True if other is a OnOffType and other equals state for this switch item,
78
- # otherwise result from super
79
- #
80
- def ==(other)
81
- if other.is_a? OnOffType
82
- state? && state == other
83
- else
84
- super
85
- end
86
- end
87
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenHAB
4
- module Core
5
- module DSL
6
- module MonkeyPatch
7
- module Ruby
8
- #
9
- # Extend integer to create duration object
10
- #
11
- module IntegerExtensions
12
- include OpenHAB::Core
13
-
14
- #
15
- # Create Duration with the specified unit
16
- #
17
- # @return [Java::JavaTime::Duration] Duration with number of units from self
18
- #
19
- %w[millis seconds minutes hours].each do |unit|
20
- define_method(unit) { Java::JavaTime::Duration.public_send("of_#{unit}", self) }
21
- end
22
-
23
- alias second seconds
24
- alias millisecond millis
25
- alias milliseconds millis
26
- alias ms millis
27
- alias minute minutes
28
- alias hour hours
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
35
-
36
- #
37
- # Prepend Integer class with duration extensions
38
- #
39
- class Integer
40
- prepend OpenHAB::Core::DSL::MonkeyPatch::Ruby::IntegerExtensions
41
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
-
5
- # Monkey patch range to support case equality of OpenHab "Numeric" Objects
6
-
7
- module OpenHAB
8
- module Core
9
- module DSL
10
- #
11
- # MonkeyPatch both Ruby and OpenHAB Objects to support DSL
12
- #
13
- module MonkeyPatch
14
- #
15
- # MonkeyPatch ruby object to support DSL
16
- #
17
- module Ruby
18
- #
19
- # Extensions for Range Class to support DimmerItems
20
- #
21
- module RangeExtensions
22
- #
23
- # Override range === method to support DimmerItems
24
- #
25
- # @param [Object] other object to compare for case equals
26
- #
27
- # @return [Boolean] if other is DimmerItem and state is covered by range,
28
- # result from parent Range class if not DimmerItem
29
- #
30
- def ===(other)
31
- return super unless other.is_a? DimmerItem
32
-
33
- cover? other.state.to_i
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
41
-
42
- #
43
- # Prepend Range class with RangeExtensions
44
- #
45
- class Range
46
- prepend OpenHAB::Core::DSL::MonkeyPatch::Ruby::RangeExtensions
47
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Monkey patch ruby
4
- require 'openhab/core/dsl/monkey_patch/ruby/range'
5
- require 'openhab/core/dsl/monkey_patch/ruby/number'
6
- require 'bigdecimal/util'
@@ -1,24 +0,0 @@
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
@@ -1,41 +0,0 @@
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
@@ -1,25 +0,0 @@
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
@@ -1,23 +0,0 @@
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
@@ -1,7 +0,0 @@
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'
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenHAB
4
- module Core
5
- module DSL
6
- #
7
- # Provides support for interacting with OpenHAB Persistence service
8
- #
9
- module Persistence
10
- #
11
- # Sets a thread local variable to set the default persistence service
12
- # for method calls inside the block
13
- #
14
- # @param [Object] Persistence service either as a String or a Symbol
15
- # @yield [] Block executed in context of the supplied persistence service
16
- #
17
- #
18
- def persistence(service)
19
- Thread.current.thread_variable_set(:persistence_service, service)
20
- yield
21
- ensure
22
- Thread.current.thread_variable_set(:persistence_service, nil)
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,96 +0,0 @@
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
- # rubocop:disable Metrics/MethodLength
33
- # rubocop:disable Metrics/AbcSize
34
- # rubocop:disable Metrics/CyclomaticComplexity
35
- # rubocop:disable Metrics/PerceivedComplexity
36
- def prop(name)
37
- # rubocop rules are disabled because this method is dynamically defined on the calling
38
- # object making calls to other methods in this module impossible, or if done on methods
39
- # in this module than instance variable belong to the module not the calling class
40
- define_method(name) do |*args, &block|
41
- if args.length.zero? && block.nil? == true
42
- instance_variable_get("@#{name}")
43
- else
44
- logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
45
- if args.length == 1
46
- instance_variable_set("@#{name}", args.first)
47
- elsif args.length > 1
48
- instance_variable_set("@#{name}", args)
49
- elsif block
50
- instance_variable_set("@#{name}", block)
51
- end
52
- end
53
- end
54
- end
55
-
56
- #
57
- # Dynamically creates a property array acts and an accessor with no arguments
58
- # and a pushes any number of arguments or a block onto they property array
59
- # You can provide a block to this method which can be used to check if the provided value is acceptable.
60
- #
61
- # @param [String] name of the property
62
- # @param [String] array_name name of the array to use, defaults to name of property
63
- # @param [Class] wrapper object to put around elements added to the array
64
- #
65
- def prop_array(name, array_name: nil, wrapper: nil)
66
- define_method(name) do |*args, &block|
67
- array_name ||= name
68
- if args.length.zero? && block.nil? == true
69
- instance_variable_get("@#{array_name}")
70
- else
71
- logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
72
- if args.length == 1
73
- insert = args.first
74
- elsif args.length > 1
75
- insert = args
76
- elsif block
77
- insert = block
78
- end
79
- yield insert if block_given?
80
- insert = wrapper.new(insert) if wrapper
81
- instance_variable_set("@#{array_name}", (instance_variable_get("@#{array_name}") || []) << insert)
82
- end
83
- end
84
-
85
- return unless array_name
86
-
87
- define_method(array_name) do
88
- instance_variable_get("@#{array_name}")
89
- end
90
- end
91
- end
92
- # rubocop:enable Metrics/MethodLength
93
- # rubocop:enable Metrics/AbcSize
94
- # rubocop:enable Metrics/CyclomaticComplexity
95
- # rubocop:enable Metrics/PerceivedComplexity
96
- end
@@ -1,348 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
-
5
- module OpenHAB
6
- module Core
7
- module DSL
8
- #
9
- # Creates and manages OpenHAB Rules
10
- #
11
- module Rule
12
- #
13
- # JRuby extension to OpenHAB Rule
14
- #
15
- # rubocop: disable Metrics/ClassLength
16
- # Disabled because this class has a single responsibility, there does not appear a logical
17
- # way of breaking it up into multiple classes
18
- class AutomationRule < Java::OrgOpenhabCoreAutomationModuleScriptRulesupportSharedSimple::SimpleRule
19
- include Logging
20
- include OpenHAB::Core::DSL::Tod
21
- java_import java.time.ZonedDateTime
22
-
23
- #
24
- # Create a new Rule
25
- #
26
- # @param [Config] config Rule configuration
27
- #
28
- def initialize(config:)
29
- super()
30
- set_name(config.name)
31
- set_description(config.description)
32
- set_triggers(config.triggers)
33
- @run_queue = config.run
34
- @guard = config.guard
35
- between = config.between&.yield_self { between(config.between) }
36
- @between = between || OpenHAB::Core::DSL::Tod::ALL_DAY
37
- # Convert between to correct range or nil if not set
38
- @trigger_delays = config.trigger_delays
39
- end
40
-
41
- #
42
- # Execute the rule
43
- #
44
- # @param [Map] mod map provided by OpenHAB rules engine
45
- # @param [Map] inputs map provided by OpenHAB rules engine containing event and other information
46
- #
47
- #
48
- def execute(mod = nil, inputs = nil)
49
- logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs&.pretty_inspect}" }
50
- logger.trace { "Event details #{inputs['event'].pretty_inspect}" } if inputs&.key?('event')
51
- if trigger_delay inputs
52
- trigger_delay = trigger_delay(inputs)
53
- process_trigger_delay(trigger_delay, mod, inputs)
54
- else
55
- # If guards are satisfied execute the run type blocks
56
- # If they are not satisfied, execute the Othewise blocks
57
- queue = create_queue(inputs)
58
- process_queue(queue, mod, inputs)
59
- end
60
- end
61
-
62
- private
63
-
64
- #
65
- # Create the run queue based on guards
66
- #
67
- # @param [Map] inputs rule inputs
68
- #
69
- # @return [Queue] <description>
70
- #
71
- def create_queue(inputs)
72
- case check_guards(event: inputs&.dig('event'))
73
- when true
74
- @run_queue.dup
75
- when false
76
- @run_queue.dup.grep(RuleConfig::Otherwise)
77
- end
78
- end
79
-
80
- #
81
- # Returns trigger delay from inputs if it exists
82
- #
83
- # @param [Map] inputs map from OpenHAB containing UID
84
- #
85
- # @return [Array] Array of trigger delays that match rule UID
86
- #
87
- def trigger_delay(inputs)
88
- # Parse this to get the trigger UID:
89
- # ["72698819-83cb-498a-8e61-5aab8b812623.event", "oldState", "module", \
90
- # "72698819-83cb-498a-8e61-5aab8b812623.oldState", "event", "newState",\
91
- # "72698819-83cb-498a-8e61-5aab8b812623.newState"]
92
- @trigger_delays[inputs&.keys&.grep(/\.event$/)&.first&.chomp('.event')]
93
- end
94
-
95
- #
96
- # Check if trigger guards prevent rule execution
97
- #
98
- # @param [Delay] trigger_delay rules delaying trigger because of
99
- # @param [Map] inputs OpenHAB map object describing rule trigger
100
- #
101
- # @return [Boolean] True if the rule should execute, false if trigger guard prevents execution
102
- #
103
- def check_trigger_guards(trigger_delay, inputs)
104
- old_state = inputs['oldState']
105
- new_state = inputs['newState']
106
- if check_from(trigger_delay, old_state)
107
- return true if check_to(trigger_delay, new_state)
108
-
109
- logger.trace("Skipped execution of rule '#{name}' because to state #{new_state}"\
110
- " does not equal specified state(#{trigger_delay.to})")
111
- else
112
- logger.trace("Skipped execution of rule '#{name}' because old state #{old_state}"\
113
- " does not equal specified state(#{trigger_delay.from})")
114
- end
115
- end
116
-
117
- #
118
- # Check the from state against the trigger delay
119
- #
120
- # @param [TriggerDelay] trigger_delay Information about the trigger delay
121
- # @param [Item State] state from state to check
122
- #
123
- # @return [Boolean] true if no from state is defined or defined state equals supplied state
124
- #
125
- def check_from(trigger_delay, state)
126
- trigger_delay.from.nil? || trigger_delay.from == state
127
- end
128
-
129
- #
130
- # Check the to state against the trigger delay
131
- #
132
- # @param [TriggerDelay] trigger_delay Information about the trigger delay
133
- # @param [Item State] state to-state to check
134
- #
135
- # @return [Boolean] true if no to state is defined or defined state equals supplied state
136
- #
137
- def check_to(trigger_delay, state)
138
- trigger_delay.to.nil? || trigger_delay.to == state
139
- end
140
-
141
- #
142
- # Process any matching trigger delays
143
- #
144
- # @param [Map] mod OpenHAB map object describing rule trigger
145
- # @param [Map] inputs OpenHAB map object describing rule trigger
146
- #
147
- #
148
- def process_trigger_delay(trigger_delay, mod, inputs)
149
- if check_trigger_guards(trigger_delay, inputs)
150
- logger.trace("Trigger Guards Matched for #{trigger_delay}, delaying rule execution")
151
- # Add timer and attach timer to delay object, and also state being tracked to so timer can be cancelled if
152
- # state changes
153
- # Also another timer should not be created if changed to same value again but instead rescheduled
154
- if trigger_delay.timer_active?
155
- process_active_timer(inputs, mod, trigger_delay)
156
- else
157
- create_trigger_delay_timer(inputs, mod, trigger_delay)
158
- end
159
- else
160
- logger.trace("Trigger Guards did not match for #{trigger_delay}, ignoring trigger.")
161
- end
162
- end
163
-
164
- #
165
- # Creatas a timer for trigger delays
166
- #
167
- # @param [Hash] inputs rule trigger inputs
168
- # @param [Hash] mod rule trigger mods
169
- # @param [TriggerDelay] trigger_delay specifications
170
- #
171
- #
172
- def create_trigger_delay_timer(inputs, mod, trigger_delay)
173
- logger.trace("Creating timer for rule #{name} and trigger delay #{trigger_delay}")
174
- trigger_delay.timer = after(trigger_delay.duration) do
175
- logger.trace("Delay Complete for #{trigger_delay}, executing rule")
176
- trigger_delay.timer = nil
177
- process_queue(@run_queue.dup, mod, inputs)
178
- end
179
- trigger_delay.tracking_to = inputs['newState']
180
- end
181
-
182
- #
183
- # Process an active trigger timer
184
- #
185
- # @param [Hash] inputs rule trigger inputs
186
- # @param [Hash] mod rule trigger mods
187
- # @param [TriggerDelay] trigger_delay specifications
188
- #
189
- #
190
- def process_active_timer(inputs, mod, trigger_delay)
191
- state = inputs['newState']
192
- if state == trigger_delay.tracking_to
193
- logger.trace("Item changed to #{state} for #{trigger_delay}, rescheduling timer.")
194
- trigger_delay.timer.reschedule(ZonedDateTime.now.plus(duration))
195
- else
196
- logger.trace("Item changed to #{state} for #{trigger_delay}, cancelling timer.")
197
- trigger_delay.timer.cancel
198
- # Reprocess trigger delay after cancelling to track new state (if guards matched, etc)
199
- process_trigger_delay(trigger_delay, mod, inputs)
200
- end
201
- end
202
-
203
- #
204
- # Check if any guards prevent execution
205
- #
206
- # @param [Map] event OpenHAB rule trigger event
207
- #
208
- # @return [Boolean] True if guards says rule should execute, false otherwise
209
- #
210
- def check_guards(event:)
211
- if @guard.should_run? event
212
- now = TimeOfDay.now
213
- return true if @between.cover? now
214
-
215
- logger.trace("Skipped execution of rule '#{name}' because the current time #{now} "\
216
- "is not between #{@between.begin} and #{@between.end}")
217
- else
218
- logger.trace("Skipped execution of rule '#{name}' because of guard #{@guard}")
219
- end
220
- false
221
- end
222
-
223
- #
224
- # Patch event to include event.item when it doesn't exist
225
- # This is to patch a bug see https://github.com/boc-tothefuture/openhab-jruby/issues/75
226
- # It may be fixed in the openhab core in the future, in which case, this patch will no longer be necessary
227
- #
228
- # @param [OpenHAB Event] event to check for item accessor
229
- # @param [OpenHAB Event Inputs] inputs inputs to running rule
230
- #
231
- def add_event_item(event, inputs)
232
- return if event.nil? || defined?(event.item)
233
-
234
- class << event
235
- attr_accessor :item
236
- end
237
- event.item = inputs&.dig('triggeringItem')
238
- end
239
-
240
- #
241
- # Process the run queue
242
- #
243
- # @param [Array] run_queue array of procs of various types to execute
244
- # @param [Map] mod OpenHAB map object describing rule trigger
245
- # @param [Map] inputs OpenHAB map object describing rule trigge
246
- #
247
- #
248
- def process_queue(run_queue, mod, inputs)
249
- event = inputs&.dig('event')
250
-
251
- while (task = run_queue.shift)
252
- case task
253
- when RuleConfig::Run then process_run_task(event, inputs, task)
254
- when RuleConfig::Trigger then process_trigger_task(event, task)
255
- when RuleConfig::Delay then process_delay_task(inputs, mod, run_queue, task)
256
- when RuleConfig::Otherwise then process_otherwise_task(event, task)
257
- end
258
- end
259
- end
260
-
261
- #
262
- # Process an otherwise block
263
- #
264
- # @param [OpenHab Event] event that triggered the rule
265
- # @param [Task] task task containing otherwise block to execute
266
- #
267
- #
268
- def process_otherwise_task(event, task)
269
- logger.trace { "Executing rule '#{name}' otherwise block with event(#{event})" }
270
- task.block.call(event)
271
- end
272
-
273
- #
274
- # Process delay task
275
- #
276
- # @param [Map] inputs Rule trigger inputs
277
- # @param [Map] mod Rule modes
278
- # @param [Queue] run_queue Queue of tasks for this rule
279
- # @param [Delay] task to process
280
- #
281
- #
282
- def process_delay_task(inputs, mod, run_queue, task)
283
- remaining_queue = run_queue.slice!(0, run_queue.length)
284
- after(task.duration) { process_queue(remaining_queue, mod, inputs) }
285
- end
286
-
287
- #
288
- # Process a task that is caused by a group item
289
- #
290
- # @param [Map] event Rule event map
291
- # @param [Trigger] task to execute
292
- #
293
- #
294
- def process_trigger_task(event, task)
295
- # rubocop: disable Style/GlobalVars
296
- triggering_item = $ir.get(event&.itemName)
297
- # rubocop: enable Style/GlobalVars
298
- logger.trace { "Executing rule '#{name}' trigger block with item (#{triggering_item})" }
299
- task.block.call(triggering_item) if triggering_item
300
- end
301
-
302
- #
303
- # Process a run task
304
- #
305
- # @param [OpenHab Event] event information
306
- # @param [Map] inputs of rule trigger information
307
- # @param [Run] task to execute
308
- #
309
- #
310
- def process_run_task(event, inputs, task)
311
- add_event_item(event, inputs)
312
- logger.trace { "Executing rule '#{name}' run block with event(#{event})" }
313
- task.block.call(event)
314
- end
315
-
316
- #
317
- # Create a new hash in which all elements are converted to strings
318
- #
319
- # @param [Map] hash in which all elements should be converted to strings
320
- #
321
- # @return [Map] new map with values converted to strings
322
- #
323
- def inspect_hash(hash)
324
- hash.each_with_object({}) do |(key, value), new_hash|
325
- new_hash[inspect_item(key)] = inspect_item(value)
326
- end
327
- end
328
-
329
- #
330
- # Convert an individual element into a string based on if it a Ruby or Java object
331
- #
332
- # @param [Object] item to convert to a string
333
- #
334
- # @return [String] representation of item
335
- #
336
- def inspect_item(item)
337
- if item.respond_to? :to_string
338
- item.to_string
339
- elsif item.respond_to? :to_str
340
- item.to_str
341
- end
342
- end
343
- end
344
- end
345
- end
346
- end
347
- end
348
- # rubocop: enable Metrics/ClassLength