openhab-scripting 4.6.0 → 4.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9ccae52c29da91b7fadc2ac7ba2459e9870a257396849535458497ba48601e5
4
- data.tar.gz: 0015aca73a5c79082adefb486afcbb545e324c0695d492e15397d2e0d691a204
3
+ metadata.gz: e7e6ee3df4ad1f531639fff95e296f8ed489f5b4a47a01c713d63855b98b5e6c
4
+ data.tar.gz: 8fe4c12aee553c1d8a4aba1509a0b90fb1fc40edc6f75c2b9c814b610e6b98a5
5
5
  SHA512:
6
- metadata.gz: 2db7c0a6f4182d3145871ab6936aa92d5acbe2a6d29e79f793a464d4fbb9514555021d9f0b103130ed99b04c9e149a414ea96df8f134f7db2fb71bade3824168
7
- data.tar.gz: da447a4315a8d177db5fc6e476dd30ba93a071f06c6dc612a361f9d12a8539932f8a1659bdd919d8cdf61be2da759f720020d57fe399eaa1a2533bf5e1f56203
6
+ metadata.gz: f841778b56365cb9df2e8f3749d09c11626b2d528dcf6250d32b31e5733dfb9caead2a9987171808d20fdacd72fac62189f5391b538c48bc0e0e63c0b743a0ce
7
+ data.tar.gz: b64a487d9d4a3d6fcf4d7c6e8137ec4237ad75d6756fdc5b91546616db14c21833cf52156c0edfacbdaa0dc58c92bba2028cec98d58bf3df2e00f770f0a93fbf
@@ -4,6 +4,8 @@ require 'pp'
4
4
  require 'java'
5
5
  require 'set'
6
6
 
7
+ require 'openhab/log/logger'
8
+
7
9
  # Automation lookup and injection of OpenHab entities
8
10
 
9
11
  module OpenHAB
@@ -24,9 +26,6 @@ module OpenHAB
24
26
  # @return [Object] Item or Thing if found in registry
25
27
  #
26
28
  def method_missing(method, *args, &block)
27
- return if method.to_s == 'scriptLoaded'
28
- return if method.to_s == 'scriptUnloaded'
29
-
30
29
  logger.trace("method missing, performing OpenHab Lookup for: #{method}")
31
30
  EntityLookup.lookup_entity(method) || super
32
31
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openhab/log/logger'
4
+ require 'openhab/dsl/rules/rule'
5
+ require 'openhab/dsl/timers'
6
+
7
+ # OpenHAB main module
8
+ module OpenHAB
9
+ module Core
10
+ #
11
+ # Manages script loading and unloading
12
+ #
13
+ module ScriptHandling
14
+ include OpenHAB::Log
15
+
16
+ #
17
+ # Executed when OpenHAB unloads a script file
18
+ #
19
+ # rubocop:disable Naming/MethodName
20
+ # method name dictacted by OpenHAB
21
+ def scriptUnloaded
22
+ logger.trace('Script unloaded')
23
+ OpenHAB::DSL::Rules.cleanup_rules
24
+ OpenHAB::DSL::Timers.cancel_all
25
+ end
26
+ # rubocop:enable Naming/MethodName
27
+
28
+ #
29
+ # Executed when OpenHAB loads a script file
30
+ #
31
+ # rubocop:disable Naming/MethodName
32
+ # method name dictacted by OpenHAB
33
+ def scriptLoaded(filename)
34
+ logger.trace("Script loaded: #{filename}")
35
+ end
36
+ # rubocop:enable Naming/MethodName
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # OpenHAB main module
4
+ module OpenHAB
5
+ module Core
6
+ #
7
+ # Manages thread local varaibles for access inside of blocks
8
+ #
9
+ module ThreadLocal
10
+ #
11
+ # Execute the supplied block with the supplied values set for the currently running thread
12
+ # The previous values for each key are restored after the block is executed
13
+ #
14
+ # @param [Hash] Keys and values to set for running thread
15
+ #
16
+ def thread_local(**values)
17
+ old_values = values.map { |key, _value| [key, Thread.current[key]] }.to_h
18
+ values.each { |key, value| Thread.current[key] = value }
19
+ yield
20
+ ensure
21
+ old_values.each { |key, value| Thread.current[key] = value }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openhab/dsl/monkey_patch/events/item_command'
4
+ require 'openhab/dsl/types/types'
4
5
 
5
6
  require_relative 'item_registry'
6
7
 
@@ -27,6 +28,8 @@ module OpenHAB
27
28
  # Contains all OpenHAB *Item classes, as well as associated support
28
29
  # modules
29
30
  module Items
31
+ include OpenHAB::Log
32
+
30
33
  class << self
31
34
  private
32
35
 
@@ -44,7 +47,7 @@ module OpenHAB
44
47
  _command_predicate, state_predicate = Types::PREDICATE_ALIASES[state.to_s]
45
48
  next if klass.instance_methods.include?(state_predicate)
46
49
 
47
- OpenHAB::Core.logger.trace("Defining #{klass}##{state_predicate} for #{state}")
50
+ logger.trace("Defining #{klass}##{state_predicate} for #{state}")
48
51
  klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
49
52
  def #{state_predicate} # def on?
50
53
  raw_state == #{state} # raw_state == ON
@@ -60,21 +63,21 @@ module OpenHAB
60
63
  command = Types::COMMAND_ALIASES[value.to_s]
61
64
  next if klass.instance_methods.include?(command)
62
65
 
63
- OpenHAB::Core.logger.trace("Defining #{klass}##{command} for #{value}")
66
+ logger.trace("Defining #{klass}##{command} for #{value}")
64
67
  klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
65
68
  def #{command} # def on
66
69
  command(#{value}) # command(ON)
67
70
  end # end
68
71
  RUBY
69
72
 
70
- OpenHAB::Core.logger.trace("Defining GroupItem::GroupMembers##{command} for #{value}")
73
+ logger.trace("Defining GroupItem::GroupMembers##{command} for #{value}")
71
74
  GroupItem::GroupMembers.class_eval <<~RUBY, __FILE__, __LINE__ + 1
72
75
  def #{command} # def on
73
76
  each(&:#{command}) # each(&:on)
74
77
  end # end
75
78
  RUBY
76
79
 
77
- OpenHAB::Core.logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
80
+ logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
78
81
  MonkeyPatch::Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
79
82
  def #{command}? # def refresh?
80
83
  command == #{value} # command == REFRESH
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'java'
4
+ require 'set'
5
+ require 'openhab/core/thread_local'
6
+ require 'openhab/log/logger'
4
7
 
5
8
  module OpenHAB
6
9
  module DSL
@@ -16,6 +19,7 @@ module OpenHAB
16
19
  # way of breaking it up into multiple classes
17
20
  class AutomationRule < Java::OrgOpenhabCoreAutomationModuleScriptRulesupportSharedSimple::SimpleRule
18
21
  include OpenHAB::Log
22
+ include OpenHAB::Core::ThreadLocal
19
23
  include OpenHAB::DSL::TimeOfDay
20
24
  java_import java.time.ZonedDateTime
21
25
 
@@ -24,6 +28,7 @@ module OpenHAB
24
28
  #
25
29
  # @param [Config] config Rule configuration
26
30
  #
31
+ # Constructor sets a number of variables, no further decomposition necessary
27
32
  def initialize(config:)
28
33
  super()
29
34
  set_name(config.name)
@@ -59,6 +64,14 @@ module OpenHAB
59
64
  end
60
65
  end
61
66
 
67
+ #
68
+ # Cleanup any resources associated with automation rule
69
+ #
70
+ def cleanup
71
+ logger.trace "Cancelling #{@trigger_delays.length} Trigger Delays(s) for rule '#{name}'"
72
+ @trigger_delays.each_value { |trigger_delay| trigger_delay.timer&.cancel }
73
+ end
74
+
62
75
  private
63
76
 
64
77
  #
@@ -13,6 +13,12 @@ module OpenHAB
13
13
  # Creates and manages OpenHAB Rules
14
14
  #
15
15
  module Rules
16
+ @script_rules = []
17
+
18
+ class << self
19
+ attr_reader :script_rules
20
+ end
21
+
16
22
  #
17
23
  # Create a new rule
18
24
  #
@@ -45,6 +51,13 @@ module OpenHAB
45
51
  end
46
52
  end
47
53
 
54
+ #
55
+ # Cleanup rules in this script file
56
+ #
57
+ def self.cleanup_rules
58
+ @script_rules.each(&:cleanup)
59
+ end
60
+
48
61
  private
49
62
 
50
63
  #
@@ -67,6 +80,7 @@ module OpenHAB
67
80
  return unless create_rule?(config)
68
81
 
69
82
  rule = AutomationRule.new(config: config)
83
+ Rules.script_rules << rule
70
84
  add_rule(rule)
71
85
  rule.execute if config.on_start?
72
86
  end
@@ -26,7 +26,7 @@ module OpenHAB
26
26
  class RuleConfig
27
27
  include OpenHAB::Log
28
28
  include OpenHAB::Core::EntityLookup
29
- include OpenHAB::DSL::Rules::Triggers
29
+ prepend OpenHAB::DSL::Rules::Triggers
30
30
  include OpenHAB::DSL::Rules::Guard
31
31
  include OpenHAB::DSL::Rules::Property
32
32
  extend OpenHAB::DSL
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'openhab/log/logger'
4
4
  require 'openhab/dsl/types/date_time_type'
5
+ require 'openhab/dsl/items/items'
5
6
  require 'time'
6
7
 
7
8
  module OpenHAB
@@ -3,6 +3,7 @@
3
3
  require 'java'
4
4
  require 'delegate'
5
5
  require 'forwardable'
6
+ require 'openhab/log/logger'
6
7
 
7
8
  module OpenHAB
8
9
  module DSL
@@ -10,15 +11,23 @@ module OpenHAB
10
11
  # Provides access to and ruby wrappers around OpenHAB timers
11
12
  #
12
13
  module Timers
14
+ include OpenHAB::Log
13
15
  java_import org.openhab.core.model.script.actions.ScriptExecution
14
16
  java_import java.time.ZonedDateTime
15
17
 
18
+ # Tracks active timers
19
+ @timers = Set.new
20
+ class << self
21
+ attr_accessor :timers
22
+ end
23
+
16
24
  # Ruby wrapper for OpenHAB Timer
17
25
  # This class implements delegator to delegate methods to the OpenHAB timer
18
26
  #
19
27
  # @author Brian O'Connell
20
28
  # @since 2.0.0
21
29
  class Timer < SimpleDelegator
30
+ include OpenHAB::Log
22
31
  extend Forwardable
23
32
 
24
33
  def_delegator :@timer, :is_active, :active?
@@ -31,20 +40,19 @@ module OpenHAB
31
40
  # @param [Duration] duration Duration until timer should fire
32
41
  # @param [Block] block Block to execute when timer fires
33
42
  #
34
- def initialize(duration:)
43
+ def initialize(duration:, &block)
35
44
  @duration = duration
36
45
 
37
46
  # A semaphore is used to prevent a race condition in which calling the block from the timer thread
38
47
  # occurs before the @timer variable can be set resulting in @timer being nil
39
48
  semaphore = Mutex.new
40
49
 
41
- timer_block = proc { semaphore.synchronize { yield(self) } }
42
-
43
50
  semaphore.synchronize do
44
51
  @timer = ScriptExecution.createTimer(
45
- ZonedDateTime.now.plus(@duration), timer_block
52
+ ZonedDateTime.now.plus(@duration), timer_block(semaphore, &block)
46
53
  )
47
54
  super(@timer)
55
+ Timers.timers << self
48
56
  end
49
57
  end
50
58
 
@@ -53,12 +61,40 @@ module OpenHAB
53
61
  #
54
62
  # @param [Duration] duration
55
63
  #
56
- # @return [<Type>] <description>
64
+ # @return [Timer] Rescheduled timer instances
57
65
  #
58
66
  def reschedule(duration = nil)
59
67
  duration ||= @duration
68
+ Timers.timers << self
60
69
  @timer.reschedule(ZonedDateTime.now.plus(duration))
61
70
  end
71
+
72
+ # Cancel timer
73
+ #
74
+ # @return [Boolean] True if cancel was successful, false otherwise
75
+ #
76
+ def cancel
77
+ Timers.timers.delete(self)
78
+ @timer.cancel
79
+ end
80
+
81
+ private
82
+
83
+ #
84
+ # Constructs a block to execute timer within
85
+ #
86
+ # @param [Semaphore] Semaphore to obtain before executing
87
+ #
88
+ # @return [Proc] Block for timer to execute
89
+ #
90
+ def timer_block(semaphore)
91
+ proc {
92
+ semaphore.synchronize do
93
+ Timers.timers.delete(self)
94
+ yield(self)
95
+ end
96
+ }
97
+ end
62
98
  end
63
99
 
64
100
  #
@@ -72,6 +108,14 @@ module OpenHAB
72
108
  def after(duration, &block)
73
109
  Timer.new(duration: duration, &block)
74
110
  end
111
+
112
+ #
113
+ # Cancels all active timers
114
+ #
115
+ def self.cancel_all
116
+ logger.trace("Cancelling #{@timers.length} timers")
117
+ @timers.each(&:cancel)
118
+ end
75
119
  end
76
120
  end
77
121
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'openhab/log/logger'
4
+
3
5
  require_relative 'type'
4
6
 
5
7
  require_relative 'date_time_type'
@@ -27,6 +29,8 @@ module OpenHAB
27
29
  # modules
28
30
  #
29
31
  module Types
32
+ include OpenHAB::Log
33
+
30
34
  # Hash taking a Enum value, and returning two symbols of
31
35
  # predicates to be defined for it. the first is the "command" form,
32
36
  # which should be defined on ItemCommandEvent, and on the Type itself.
@@ -65,7 +69,7 @@ module OpenHAB
65
69
  states = PREDICATE_ALIASES[value.to_s]
66
70
 
67
71
  ([command] | states).each do |method|
68
- OpenHAB::Core.logger.trace("Defining #{klass}##{method} for #{value}")
72
+ logger.trace("Defining #{klass}##{method} for #{value}")
69
73
  klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
70
74
  def #{method} # def on?
71
75
  self == #{value} # self == ON
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.6.0'
8
+ VERSION = '4.6.1'
9
9
  end
data/lib/openhab.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openhab/core/load_path'
4
+ require 'openhab/core/entity_lookup'
5
+ require 'openhab/core/script_handling'
4
6
  require 'openhab/core/openhab_setup'
5
7
  require 'openhab/log/logger'
6
8
  require 'openhab/dsl/dsl'
@@ -17,9 +19,12 @@ module OpenHAB
17
19
  # @param [Object] base Object to decorate with DSL and helper methods
18
20
  #
19
21
  #
22
+ # rubocop:disable Metrics/MethodLength
23
+ # Number of extensions and includes requires more lines
20
24
  def self.extended(base)
21
25
  OpenHAB::Core.wait_till_openhab_ready
22
26
  base.extend Log
27
+ base.extend OpenHAB::Core::ScriptHandling
23
28
  base.extend OpenHAB::Core::EntityLookup
24
29
  base.extend OpenHAB::DSL
25
30
  base.extend OpenHAB::DSL::TimeOfDay
@@ -31,6 +36,7 @@ module OpenHAB
31
36
 
32
37
  OpenHAB::Core.add_rubylib_to_load_path
33
38
  end
39
+ # rubocop:enable Metrics/MethodLength
34
40
  end
35
41
 
36
42
  # Extend caller with OpenHAB methods
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.0
4
+ version: 4.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-20 00:00:00.000000000 Z
11
+ date: 2021-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -50,6 +50,8 @@ files:
50
50
  - lib/openhab/core/load_path.rb
51
51
  - lib/openhab/core/openhab_setup.rb
52
52
  - lib/openhab/core/osgi.rb
53
+ - lib/openhab/core/script_handling.rb
54
+ - lib/openhab/core/thread_local.rb
53
55
  - lib/openhab/dsl/actions.rb
54
56
  - lib/openhab/dsl/dsl.rb
55
57
  - lib/openhab/dsl/gems.rb