openhab-scripting 4.42.1 → 4.43.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e41958655d441761618cb21164c7954bcb05c037023a080d2a70a741637d951
4
- data.tar.gz: ee4252bafef8e2a430f98c80bc3277e5c45ef9cd0c06b645f48da848031f0abf
3
+ metadata.gz: deaecd8879b238c5372c733482c69ef38703231f42a8869954d692ebd3c4fc7b
4
+ data.tar.gz: d11b35e9b654531f1c248992cb1cd2eca1e675dd37898ca28ce16760a1531c07
5
5
  SHA512:
6
- metadata.gz: c1dcd8ab59e1732eb76acd9c707d4dbd18dcae94d3fd6236d6c53362958b7fd0c977ef001c109f147df596321a99ee7640aceb25f92530f7cb8f59bd7733de9f
7
- data.tar.gz: 70d92d8df318f317c42843cf8eaae67b33c9cdb24f119074f7e59e117ec29f53f1594df05e8fd35059a666a600845375048f991c9cc15b35772fb34b35d83a4f
6
+ metadata.gz: 3052e39904c2548942c1018b592ca3370b3c15bdd1dc92685ee647f9854bcc406b886f1168b75954adab98884a45c9a92a7eb039a13056be5f4a99772111e425
7
+ data.tar.gz: 752cd312e184091663ea4c47506787fdd6ea9e56b1a794593c093b413784340bbb97c95956e716762757b355a6089e45cb96dbe2d61b6787f98641bbde557e75
@@ -33,7 +33,7 @@ module OpenHAB
33
33
  # @param [Hash] values Keys and values to set for running thread, if hash is nil no values are set
34
34
  #
35
35
  def thread_local(**values, &block)
36
- ThreadLocal.thread_local(values, &block)
36
+ ThreadLocal.thread_local(**values, &block)
37
37
  end
38
38
  end
39
39
  end
@@ -101,6 +101,18 @@ module OpenHAB
101
101
  volume = Types::PercentType.new(volume) unless volume.is_a?(Types::PercentType) || volume.nil?
102
102
  Audio.playSound sink&.to_s, filename.to_s, volume
103
103
  end
104
+
105
+ #
106
+ # Play an audio stream from an URL to the given sink(s). Set url to nil if streaming should be stopped
107
+ #
108
+ # @param [String] url The URL of the audio stream
109
+ # @param [String] sink The audio sink, or nil to use the default audio sink
110
+ #
111
+ # @return [void]
112
+ #
113
+ def play_stream(url, sink: nil)
114
+ Audio.playStream sink&.to_s, url
115
+ end
104
116
  end
105
117
  end
106
118
  end
@@ -37,7 +37,7 @@ module OpenHAB
37
37
  end
38
38
 
39
39
  # if we're NULL or UNDEF, implement special logic
40
- return nil_comparison unless state?
40
+ return nil_comparison(other) unless state?
41
41
 
42
42
  # delegate to how the state compares to the other object
43
43
  state <=> other
@@ -45,9 +45,10 @@ module OpenHAB
45
45
 
46
46
  # Special logic for NULL/UNDEF state comparison
47
47
  # @!visibility private
48
- def nil_comparison
48
+ def nil_comparison(other)
49
49
  # if comparing to nil, consider ourselves equal
50
50
  return 0 if other.nil?
51
+
51
52
  # if the other object is an Item, only consider equal if we're
52
53
  # in the same _kind_ of UnDefType state
53
54
  return raw_state == other.raw_state if other.is_a?(GenericItem) && !other.state?
@@ -51,6 +51,14 @@ module OpenHAB
51
51
  # @!method decrease
52
52
  # Send the +DECREASE+ command to the item
53
53
  # @return [DimmerItem] +self+
54
+
55
+ # raw numbers translate directly to PercentType, not a DecimalType
56
+ # @!visibility private
57
+ def format_type(command)
58
+ return Types::PercentType.new(command) if command.is_a?(Numeric)
59
+
60
+ super
61
+ end
54
62
  end
55
63
  end
56
64
  end
@@ -88,6 +88,7 @@ module OpenHAB
88
88
  @item.__send__(method, *args, &block)
89
89
  end
90
90
  end
91
+ ruby2_keywords :method_missing if respond_to? :ruby2_keywords
91
92
 
92
93
  # .
93
94
  def respond_to_missing?(method, include_private = false)
@@ -64,15 +64,10 @@ module OpenHAB
64
64
  return [other, state] if other.is_a?(Types::NumericType) || other.respond_to?(:to_d)
65
65
  end
66
66
 
67
- # strip trailing zeros from commands
67
+ # raw numbers translate directly to DecimalType, not a string
68
68
  # @!visibility private
69
69
  def format_type(command)
70
- # DecimalType and PercentType we want to make sure we don't have extra zeros
71
- if command.instance_of?(Types::DecimalType) || command.instance_of?(Types::PercentType)
72
- return command.to_big_decimal.strip_trailing_zeros.to_plain_string
73
- end
74
- # BigDecimal types have trailing zeros stripped
75
- return command.to_java.strip_trailing_zeros.to_plain_string if command.is_a?(BigDecimal)
70
+ return Types::DecimalType.new(command) if command.is_a?(Numeric)
76
71
 
77
72
  super
78
73
  end
@@ -37,6 +37,14 @@ module OpenHAB
37
37
  # @!method move
38
38
  # Send the +MOVE+ command to the item
39
39
  # @return [RollershutterItem] +self+
40
+
41
+ # raw numbers translate directly to PercentType, not a DecimalType
42
+ # @!visibility private
43
+ def format_type(command)
44
+ return Types::PercentType.new(command) if command.is_a?(Numeric)
45
+
46
+ super
47
+ end
40
48
  end
41
49
  end
42
50
  end
@@ -173,7 +173,7 @@ module OpenHAB
173
173
  def execute(_mod = nil, inputs = nil)
174
174
  OpenHAB::DSL.import_presets
175
175
  @semaphore.synchronize do
176
- thread_local(@thread_locals) do
176
+ thread_local(**@thread_locals) do
177
177
  logger.trace "Canceling implicit timer #{@timed_command_details.timer} for "\
178
178
  "#{@timed_command_details.item.id} because received event #{inputs}"
179
179
  @timed_command_details.timer.cancel
@@ -24,18 +24,21 @@ module OpenHAB
24
24
  include OpenHAB::Core::ThreadLocal
25
25
  include OpenHAB::DSL::Between
26
26
 
27
+ field_writer :uid
28
+
27
29
  #
28
30
  # Create a new Rule
29
31
  #
30
32
  # @param [Config] config Rule configuration
31
33
  #
32
34
  # Constructor sets a number of variables, no further decomposition necessary
33
- def initialize(config:) # rubocop:disable Metrics/MethodLength
35
+ def initialize(config:) # rubocop:disable Metrics
34
36
  # Metrics disabled because only setters are called or defaults set.
35
37
  super()
36
38
  set_name(config.name)
37
39
  set_description(config.description)
38
40
  set_triggers(config.triggers)
41
+ self.uid = config.uid
39
42
  @run_context = config.caller
40
43
  @run_queue = config.run
41
44
  @guard = config.guard
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'method_source'
4
+
3
5
  require 'openhab/core/thread_local'
4
6
  require 'openhab/core/services'
5
7
  require 'openhab/log/logger'
@@ -32,6 +34,12 @@ module OpenHAB
32
34
 
33
35
  module_function
34
36
 
37
+ # get the block's source location, and simplify to a simple filename
38
+ def self.infer_rule_id_from_block(block)
39
+ file = File.basename(block.source_location.first)
40
+ "#{file}:#{block.source_location.last}"
41
+ end
42
+
35
43
  #
36
44
  # Create a new rule
37
45
  #
@@ -39,21 +47,25 @@ module OpenHAB
39
47
  # @yield [] Block executed in context of a RuleConfig
40
48
  #
41
49
  #
42
- # rubocop:disable Metrics/MethodLength
43
- def rule(rule_name, &block)
50
+ def rule(rule_name = nil, id: nil, script: nil, &block) # rubocop:disable Metrics
51
+ id ||= Rule.infer_rule_id_from_block(block)
52
+ rule_name ||= id
53
+ script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
54
+
44
55
  OpenHAB::Core::ThreadLocal.thread_local(RULE_NAME: rule_name) do
45
56
  @rule_name = rule_name
57
+
46
58
  config = RuleConfig.new(rule_name, block.binding)
59
+ config.uid(id)
47
60
  config.instance_exec(config, &block)
48
61
  config.guard = Guard::Guard.new(run_context: config.caller, only_if: config.only_if,
49
62
  not_if: config.not_if)
50
63
  logger.trace { config.inspect }
51
- process_rule_config(config)
64
+ process_rule_config(config, script)
52
65
  end
53
66
  rescue StandardError => e
54
67
  logger.log_exception(e, @rule_name)
55
68
  end
56
- # rubocop:enable Metrics/MethodLength
57
69
 
58
70
  #
59
71
  # Cleanup rules in this script file
@@ -71,12 +83,15 @@ module OpenHAB
71
83
  # @param [RuleConfig] config for rule
72
84
  #
73
85
  #
74
- def process_rule_config(config)
86
+ def process_rule_config(config, script) # rubocop:disable Metrics
75
87
  return unless create_rule?(config)
76
88
 
77
89
  rule = AutomationRule.new(config: config)
78
90
  Rule.script_rules << rule
79
91
  added_rule = add_rule(rule)
92
+ added_rule.actions.first.id = 'script'
93
+ added_rule.actions.first.configuration.put('type', 'application/x-ruby')
94
+ added_rule.actions.first.configuration.put('script', script)
80
95
 
81
96
  rule.execute(nil, { 'event' => Struct.new(:attachment).new(config.start_attachment) }) if config.on_start?
82
97
  added_rule
@@ -131,6 +146,12 @@ module OpenHAB
131
146
  #
132
147
  #
133
148
  def add_rule(rule)
149
+ base_uid = rule.uid
150
+ duplicate_index = 1
151
+ while $rules.get(rule.uid) # rubocop:disable Style/GlobalVars
152
+ duplicate_index += 1
153
+ rule.uid = "#{base_uid} (#{duplicate_index})"
154
+ end
134
155
  logger.trace("Adding rule: #{rule.inspect}")
135
156
  Rule.automation_manager.addRule(rule)
136
157
  end
@@ -8,7 +8,6 @@ require_relative 'guard'
8
8
  require_relative 'rule_triggers'
9
9
  require 'openhab/core/entity_lookup'
10
10
  require 'openhab/dsl/between'
11
- require 'openhab/dsl/dsl'
12
11
  require 'openhab/dsl/timers'
13
12
 
14
13
  module OpenHAB
@@ -62,6 +61,7 @@ module OpenHAB
62
61
  prop_array :delay, :array_name => :run_queue, :wrapper => Delay
63
62
  prop_array :otherwise, :array_name => :run_queue, :wrapper => Otherwise
64
63
 
64
+ prop :uid
65
65
  prop :name
66
66
  prop :description
67
67
  prop :enabled
@@ -7,17 +7,44 @@ module OpenHAB
7
7
  module TerseRule
8
8
  %i[changed channel cron every updated received_command].each do |trigger|
9
9
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
10
- def #{trigger}(*args, name: nil, **kwargs, &block) # def changed(*args, name: nil, **kwargs, &block)
11
- # if no name is given, just default to the name of the rules file # # if no name is given, just default to the name of the rules file
12
- name ||= File.basename(caller_locations.last.path) # name ||= File.basename(caller_locations.last.path)
13
- rule name do # rule name do
14
- #{trigger}(*args, **kwargs) # changed(*args, **kwargs)
15
- run(&block) # run(&block)
16
- end # end
17
- end # end
18
- module_function #{trigger.inspect} # module_function :changed
10
+ def #{trigger}(*args, name: nil, **kwargs, &block) # def changed(*args, name: nil, **kwargs, &block)
11
+ name ||= infer_rule_name(#{trigger.inspect}, args, kwargs) # name ||= infer_rule_name(:changed, args, kwargs)
12
+ id = Rule.infer_rule_id_from_block(block) # id = Rule.infer_rule_id_from_block(block)
13
+ name ||= id # name ||= id
14
+ script = block.source rescue nil # script = block.source rescue nil
15
+ rule name, id: id, script: script do # rule name, id: id, script: script do
16
+ #{trigger}(*args, **kwargs) # changed(*args, **kwargs)
17
+ run(&block) # run(&block)
18
+ end # end
19
+ end # end
20
+ module_function #{trigger.inspect} # module_function :changed
19
21
  RUBY
20
22
  end
23
+
24
+ private
25
+
26
+ # formulate a readable rule name such as "TestSwitch received command ON" if possible
27
+ def infer_rule_name(trigger, args, kwargs) # rubocop:disable Metrics
28
+ return unless %i[changed updated received_command].include?(trigger) &&
29
+ args.length == 1 &&
30
+ (kwargs.keys - %i[from to command]).empty?
31
+ return if kwargs[:from].is_a?(Enumerable)
32
+ return if kwargs[:to].is_a?(Enumerable)
33
+ return if kwargs[:command].is_a?(Enumerable)
34
+
35
+ trigger_name = trigger.to_s.tr('_', ' ')
36
+ name = if args.first.is_a?(GroupItem::GroupMembers) # rubocop:disable Style/CaseLikeIf === doesn't work with GenericItem
37
+ "#{args.first.group.name}.members #{trigger_name}"
38
+ elsif args.first.is_a?(GenericItem)
39
+ "#{args.first.name} #{trigger_name}"
40
+ end
41
+ return unless name
42
+
43
+ name += " from #{kwargs[:from].inspect}" if kwargs[:from]
44
+ name += " to #{kwargs[:to].inspect}" if kwargs[:to]
45
+ name += " #{kwargs[:command].inspect}" if kwargs[:command]
46
+ name
47
+ end
21
48
  end
22
49
  end
23
50
  end
@@ -35,6 +35,7 @@ module OpenHAB
35
35
  from = Conditions::Proc.from_value(from)
36
36
  @conditions = Conditions::Proc.new(to: to, from: from)
37
37
  @duration = duration
38
+ @timer = nil
38
39
  logger.trace "Created Duration Condition To(#{to}) From(#{from}) "\
39
40
  "Conditions(#{@conditions}) Duration(#{@duration})"
40
41
  end
@@ -20,9 +20,6 @@ module OpenHAB
20
20
  class Proc
21
21
  include OpenHAB::Log
22
22
 
23
- # Proc that doesn't check any fields
24
- ANY = Proc.new.freeze
25
-
26
23
  #
27
24
  # Converts supplied ranges to procs that check range
28
25
  # @param [Array] ranges objects to convert to range proc if they are ranges
@@ -83,6 +80,9 @@ module OpenHAB
83
80
  @command = command
84
81
  end
85
82
 
83
+ # Proc that doesn't check any fields
84
+ ANY = Proc.new.freeze # this needs to be defined _after_ initialize so its instance variables are set
85
+
86
86
  #
87
87
  # Process rule
88
88
  # @param [Hash] inputs inputs from trigger
@@ -82,7 +82,7 @@ module OpenHAB
82
82
  OpenHAB::DSL.import_presets
83
83
  semaphore.synchronize do
84
84
  Timers.timer_manager.delete(self)
85
- thread_local(@thread_locals) do
85
+ thread_local(**@thread_locals) do
86
86
  yield(self)
87
87
  end
88
88
  end
@@ -36,14 +36,14 @@ module OpenHAB
36
36
  if value.is_a?(java.math.BigDecimal)
37
37
  super
38
38
  elsif value.is_a?(BigDecimal)
39
- super(value.to_java)
39
+ super(value.to_java.strip_trailing_zeros)
40
40
  elsif value.is_a?(DecimalType)
41
41
  super(value.to_big_decimal)
42
42
  elsif value.is_a?(Items::NumericItem) ||
43
43
  (value.is_a?(Items::GroupItem) && value.base_item.is_a?(Items::NumericItem))
44
44
  super(value.state)
45
45
  elsif value.respond_to?(:to_d)
46
- super(value.to_d.to_java)
46
+ super(value.to_d.to_java.strip_trailing_zeros)
47
47
  else # rubocop:disable Lint/DuplicateBranch
48
48
  # duplicates the Java BigDecimal branch, but that needs to go first
49
49
  # in order to avoid unnecessary conversions
@@ -212,7 +212,7 @@ module OpenHAB
212
212
  .then { |klass| java_klass(klass) }
213
213
  .then(&:name)
214
214
  .then { |name| filter_base_classes(name) }
215
- .then { |name| name&.prepend('.') }
215
+ .then { |name| ".#{name}" unless name.nil? } # name is frozen in jruby 9.4
216
216
  end
217
217
 
218
218
  # Get the appropriate java class for the supplied klass if the supplied
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.42.1'
8
+ VERSION = '4.43.1'
9
9
  end
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.42.1
4
+ version: 4.43.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: 2022-06-20 00:00:00.000000000 Z
11
+ date: 2022-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: method_source
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
41
55
  description: JRuby Helper Libraries for OpenHAB Scripting
42
56
  email:
43
57
  - broconne@gmail.com