openhab-scripting 4.8.5 → 4.10.2

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: 19b14c62e681500abaa99858522f7592e0a4d93f6966a5cf8e99157b0944cbe6
4
- data.tar.gz: 071556f83604d539af3620a0796eef993edfc0bb224ad3dd08cf7d5a71e9d593
3
+ metadata.gz: 2363b08b3ff2cf49420f2083bad82d1c20fcc927104641bbcc824495bd0ba520
4
+ data.tar.gz: a589c5a4e5a92a8c4899784a70a1a2bd5c352ae46d0ccd446516369fb1ce39ad
5
5
  SHA512:
6
- metadata.gz: '01429a840f1af1e81886988f00ad628fa01dd7a7423ef2e20c59eb1d40822b573115d12a0c8c6fc093012ad29a70666bf280de52a789a8dc8cf6b0c7d2eb1867'
7
- data.tar.gz: 28aab00e8742851f08fee9535b39c913f78f4c7200f2bdbd8788e4d6c8ac8ae6f202a7f3e4675e0e02af2bbc953b6a10114b93987eff5c6ec37e1d6ad0f8ddeb
6
+ metadata.gz: dfe40bd0793be059b2196d18ea6e68fba9415b92326cb9e55b6a1bcbf68bc778ed96cb5f1a97ce2f6a61f6164452dea25e0c6f905bdd88c206cafc19194e850e
7
+ data.tar.gz: cdb36b59bd35ab74fa08cbfa1e011c73c3111f04702451e16698c8f701fadedfb6f68af514149dc6bac6a9808ad206ea5eba738a1cd78f5e2efee2b6fb52cd16
@@ -39,8 +39,6 @@ module OpenHAB
39
39
  logger.trace("Coercing #{self} as a request from #{other.class}")
40
40
  return [other, nil] unless state?
41
41
  return [other, state] if other.is_a?(Types::HSBType) || other.respond_to?(:to_str)
42
-
43
- raise TypeError, "can't convert #{other.class} into #{self.class}"
44
42
  end
45
43
 
46
44
  # any method that exists on {Types::HSBType} gets forwarded to +state+
@@ -40,8 +40,6 @@ module OpenHAB
40
40
  logger.trace("Coercing #{self} as a request from #{other.class}")
41
41
  return [other, nil] unless state?
42
42
  return [other, state] if other.is_a?(Types::DateTimeType) || other.respond_to?(:to_time)
43
-
44
- raise TypeError, "can't convert #{other.class} into #{self.class}"
45
43
  end
46
44
 
47
45
  # any method that exists on DateTimeType, Java's ZonedDateTime, or
@@ -39,8 +39,6 @@ module OpenHAB
39
39
  logger.trace("Coercing #{self} as a request from #{other.class}")
40
40
  return [other, nil] unless state?
41
41
  return [other, state] if other.is_a?(Types::PointType) || other.respond_to?(:to_str)
42
-
43
- raise TypeError, "can't convert #{other.class} into #{self.class}"
44
42
  end
45
43
 
46
44
  # OpenHAB has this method, but it _only_ accepts PointType, so remove it and delegate
@@ -47,8 +47,6 @@ module OpenHAB
47
47
  logger.trace("Coercing #{self} as a request from #{other.class}")
48
48
  return [other, nil] unless state?
49
49
  return [other, state] if other.is_a?(Types::NumericType) || other.respond_to?(:to_d)
50
-
51
- raise TypeError, "can't convert #{other.class} into #{self.class}"
52
50
  end
53
51
 
54
52
  # strip trailing zeros from commands
@@ -5,6 +5,8 @@ require 'set'
5
5
  require 'openhab/core/thread_local'
6
6
  require 'openhab/log/logger'
7
7
 
8
+ require_relative 'item_event'
9
+
8
10
  module OpenHAB
9
11
  module DSL
10
12
  #
@@ -29,6 +31,8 @@ module OpenHAB
29
31
  # @param [Config] config Rule configuration
30
32
  #
31
33
  # Constructor sets a number of variables, no further decomposition necessary
34
+ # rubocop:disable Metrics/MethodLength
35
+ # Metrics disabled because only setters are called or defaults set.
32
36
  def initialize(config:)
33
37
  super()
34
38
  set_name(config.name)
@@ -41,7 +45,9 @@ module OpenHAB
41
45
  @between = between || OpenHAB::DSL::TimeOfDay::ALL_DAY
42
46
  # Convert between to correct range or nil if not set
43
47
  @trigger_delays = config.trigger_delays
48
+ @attachments = config.attachments
44
49
  end
50
+ # rubocop:enable Metrics/MethodLength
45
51
 
46
52
  #
47
53
  # Execute the rule
@@ -51,7 +57,7 @@ module OpenHAB
51
57
  #
52
58
  #
53
59
  def execute(mod = nil, inputs = nil)
54
- logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs&.pretty_inspect}" }
60
+ logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs&.pretty_inspect})" }
55
61
  logger.trace { "Event details #{inputs['event'].pretty_inspect}" } if inputs&.key?('event')
56
62
  if trigger_delay inputs
57
63
  trigger_delay = trigger_delay(inputs)
@@ -88,6 +94,15 @@ module OpenHAB
88
94
  end
89
95
  end
90
96
 
97
+ #
98
+ # Get the trigger_id for the trigger that caused the rule creation
99
+ #
100
+ # @return [Hash] Input hash potentially containing trigger id
101
+ #
102
+ def trigger_id(inputs)
103
+ inputs&.keys&.grep(/\.event$/)&.first&.chomp('.event')
104
+ end
105
+
91
106
  #
92
107
  # Returns trigger delay from inputs if it exists
93
108
  #
@@ -100,7 +115,24 @@ module OpenHAB
100
115
  # ["72698819-83cb-498a-8e61-5aab8b812623.event", "oldState", "module", \
101
116
  # "72698819-83cb-498a-8e61-5aab8b812623.oldState", "event", "newState",\
102
117
  # "72698819-83cb-498a-8e61-5aab8b812623.newState"]
103
- @trigger_delays[inputs&.keys&.grep(/\.event$/)&.first&.chomp('.event')]
118
+ @trigger_delays[trigger_id(inputs)]
119
+ end
120
+
121
+ # If an attachment exists for the trigger for this event add it to the event object
122
+ # @param [Object] Event
123
+ # @param [Hash] Inputs into event
124
+ # @return [Object] Event with attachment added
125
+ #
126
+ def add_attachment(event, inputs)
127
+ attachment = @attachments[trigger_id(inputs)]
128
+ return event unless attachment
129
+
130
+ # Some events, like those from cron triggers don't have an event
131
+ # so an event is created
132
+ event ||= Struct.new(:event).new
133
+
134
+ event.attachment = attachment
135
+ event
104
136
  end
105
137
 
106
138
  #
@@ -268,8 +300,11 @@ module OpenHAB
268
300
  # @param [Map] inputs OpenHAB map object describing rule trigge
269
301
  #
270
302
  #
303
+ # rubocop:disable Metrics/MethodLength
304
+ # No logical way to break this method up
271
305
  def process_queue(run_queue, mod, inputs)
272
306
  event = inputs&.dig('event')
307
+ event = add_attachment(event, inputs)
273
308
 
274
309
  while (task = run_queue.shift)
275
310
  if task.is_a? RuleConfig::Delay
@@ -281,6 +316,7 @@ module OpenHAB
281
316
  rescue StandardError => e
282
317
  print_backtrace(e)
283
318
  end
319
+ # rubocop:enable Metrics/MethodLength
284
320
 
285
321
  #
286
322
  # Dispatch execution block tasks to different methods
@@ -13,13 +13,13 @@ module OpenHAB
13
13
  include OpenHAB::DSL::Rules::Property
14
14
 
15
15
  prop_array(:only_if) do |item|
16
- unless item.is_a?(Proc) || item.respond_to?(:truthy?)
16
+ unless item.is_a?(Proc) || [item].flatten.all? { |it| it.respond_to?(:truthy?) }
17
17
  raise ArgumentError, "Object passed to only_if must respond_to 'truthy?'"
18
18
  end
19
19
  end
20
20
 
21
21
  prop_array(:not_if) do |item|
22
- unless item.is_a?(Proc) || item.respond_to?(:truthy?)
22
+ unless item.is_a?(Proc) || [item].flatten.all? { |it| it.respond_to?(:truthy?) }
23
23
  raise ArgumentError, "Object passed to not_if must respond_to 'truthy?'"
24
24
  end
25
25
  end
@@ -113,7 +113,7 @@ module OpenHAB
113
113
  # @return [Boolean] True if criteria are satisfied, false otherwise
114
114
  #
115
115
  def process_not_if(event, items, procs)
116
- items.none?(&:truthy?) && procs.none? { |proc| proc.call(event) }
116
+ items.flatten.none?(&:truthy?) && procs.none? { |proc| proc.call(event) }
117
117
  end
118
118
 
119
119
  #
@@ -126,7 +126,7 @@ module OpenHAB
126
126
  # @return [Boolean] True if criteria are satisfied, false otherwise
127
127
  #
128
128
  def process_only_if(event, items, procs)
129
- items.all?(&:truthy?) && procs.all? { |proc| proc.call(event) }
129
+ items.flatten.all?(&:truthy?) && procs.all? { |proc| proc.call(event) }
130
130
  end
131
131
  end
132
132
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Rules
6
+ #
7
+ # Extends OpenHAB events
8
+ #
9
+ module Events
10
+ java_import org.openhab.core.events.AbstractEvent
11
+
12
+ # Add attachments to ItemEvent
13
+ class AbstractEvent
14
+ attr_accessor :attachment
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -87,7 +87,7 @@ module OpenHAB
87
87
  rule = AutomationRule.new(config: config)
88
88
  Rules.script_rules << rule
89
89
  add_rule(rule)
90
- rule.execute if config.on_start?
90
+ rule.execute(nil, { 'event' => Struct.new(:attachment).new(config.start_attachment) }) if config.on_start?
91
91
  end
92
92
 
93
93
  #
@@ -37,6 +37,9 @@ module OpenHAB
37
37
  # @return [Array] Of trigger delays
38
38
  attr_reader :trigger_delays
39
39
 
40
+ # @return [Hash] Hash of trigger UIDs to attachments
41
+ attr_reader :attachments
42
+
40
43
  # @return [Array] Of trigger guards
41
44
  attr_accessor :guard
42
45
 
@@ -82,6 +85,7 @@ module OpenHAB
82
85
  def initialize(rule_name, caller_binding)
83
86
  @triggers = []
84
87
  @trigger_delays = {}
88
+ @attachments = {}
85
89
  @caller = caller_binding.eval 'self'
86
90
  enabled(true)
87
91
  on_start(false)
@@ -96,8 +100,8 @@ module OpenHAB
96
100
  #
97
101
  # rubocop: disable Style/OptionalBooleanParameter
98
102
  # Disabled cop due to use in a DSL
99
- def on_start(run_on_start = true)
100
- @on_start = run_on_start
103
+ def on_start(run_on_start = true, attach: nil)
104
+ @on_start = Struct.new(:enabled, :attach).new(run_on_start, attach)
101
105
  end
102
106
  # rubocop: enable Style/OptionalBooleanParameter
103
107
 
@@ -107,7 +111,16 @@ module OpenHAB
107
111
  # @return [Boolean] True if rule should run on start, false otherwise.
108
112
  #
109
113
  def on_start?
110
- @on_start
114
+ @on_start.enabled
115
+ end
116
+
117
+ #
118
+ # Get the optional start attachment
119
+ #
120
+ # @return [Object] optional user provided attachment to the on_start method
121
+ #
122
+ def start_attachment
123
+ @on_start.attach
111
124
  end
112
125
 
113
126
  #
@@ -144,7 +157,8 @@ module OpenHAB
144
157
  "Run blocks: (#{run}) " \
145
158
  "on_start: (#{on_start?}) " \
146
159
  "Trigger Waits: #{trigger_delays} " \
147
- "Trigger UIDs: #{triggers.map(&:id).join(', ')}"
160
+ "Trigger UIDs: #{triggers.map(&:id).join(', ')}" \
161
+ "Attachments: #{attachments} "
148
162
  end
149
163
  end
150
164
  end
@@ -30,16 +30,16 @@ module OpenHAB
30
30
  #
31
31
  # @return [Trigger] OpenHAB trigger
32
32
  #
33
- def changed(*items, to: nil, from: nil, for: nil)
33
+ def changed(*items, to: nil, from: nil, for: nil, attach: nil)
34
34
  separate_groups(items).map do |item|
35
35
  logger.trace("Creating changed trigger for entity(#{item}), to(#{to}), from(#{from})")
36
36
  # for is a reserved word in ruby, so use local_variable_get :for
37
37
  if (wait_duration = binding.local_variable_get(:for))
38
- changed_wait(item, to: to, from: from, duration: wait_duration)
38
+ changed_wait(item, to: to, from: from, duration: wait_duration, attach: attach)
39
39
  else
40
40
  # Place in array and flatten to support multiple to elements or single or nil
41
41
  [to].flatten.map do |to_state|
42
- [from].flatten.map { |from_state| create_changed_trigger(item, from_state, to_state) }
42
+ [from].flatten.map { |from_state| create_changed_trigger(item, from_state, to_state, attach) }
43
43
  end
44
44
  end
45
45
  end.flatten
@@ -57,8 +57,8 @@ module OpenHAB
57
57
  #
58
58
  # @return [Trigger] OpenHAB trigger
59
59
  #
60
- def changed_wait(item, duration:, to: nil, from: nil)
61
- trigger = create_changed_trigger(item, nil, nil)
60
+ def changed_wait(item, duration:, to: nil, from: nil, attach: nil)
61
+ trigger = create_changed_trigger(item, nil, nil, attach)
62
62
  logger.trace("Creating Changed Wait Change Trigger for #{item}")
63
63
  @trigger_delays[trigger.id] = TriggerDelay.new(to: to, from: from, duration: duration)
64
64
  trigger
@@ -72,14 +72,14 @@ module OpenHAB
72
72
  # @param [String] to state restrict trigger to
73
73
  #
74
74
  #
75
- def create_changed_trigger(item, from, to)
75
+ def create_changed_trigger(item, from, to, attach)
76
76
  trigger, config = case item
77
77
  when OpenHAB::DSL::Items::GroupItem::GroupMembers
78
78
  create_group_changed_trigger(item, from, to)
79
79
  when Thing then create_thing_changed_trigger(item, from, to)
80
80
  else create_item_changed_trigger(item, from, to)
81
81
  end
82
- append_trigger(trigger, config)
82
+ append_trigger(trigger, config, attach: attach)
83
83
  end
84
84
 
85
85
  #
@@ -21,12 +21,12 @@ module OpenHAB
21
21
  # @param [String] triggered specific triggering condition to match for trigger
22
22
  #
23
23
  #
24
- def channel(*channels, thing: nil, triggered: nil)
24
+ def channel(*channels, thing: nil, triggered: nil, attach: nil)
25
25
  channels.flatten.each do |channel|
26
26
  channel = [thing, channel].join(':') if thing
27
27
  logger.trace("Creating channel trigger for channel(#{channel}), thing(#{thing}), trigger(#{triggered})")
28
28
  [triggered].flatten.each do |trigger|
29
- create_channel_trigger(channel, trigger)
29
+ create_channel_trigger(channel, trigger, attach)
30
30
  end
31
31
  end
32
32
  end
@@ -40,12 +40,12 @@ module OpenHAB
40
40
  # @param [Trigger] trigger specific channel trigger to match
41
41
  #
42
42
  #
43
- def create_channel_trigger(channel, trigger)
43
+ def create_channel_trigger(channel, trigger, attach)
44
44
  config = { 'channelUID' => channel }
45
45
  config['event'] = trigger.to_s unless trigger.nil?
46
46
  config['channelUID'] = channel
47
47
  logger.trace("Creating Change Trigger for #{config}")
48
- @triggers << Trigger.trigger(type: Trigger::CHANNEL_EVENT, config: config)
48
+ append_trigger(Trigger::CHANNEL_EVENT, config, attach: attach)
49
49
  end
50
50
  end
51
51
  end
@@ -21,14 +21,14 @@ module OpenHAB
21
21
  # @param [Array] commands commands to match for trigger
22
22
  #
23
23
  #
24
- def received_command(*items, command: nil, commands: nil)
24
+ def received_command(*items, command: nil, commands: nil, attach: nil)
25
25
  separate_groups(items).map do |item|
26
26
  logger.trace("Creating received command trigger for item(#{item})"\
27
27
  "command(#{command}) commands(#{commands})")
28
28
 
29
29
  # Combine command and commands, doing union so only a single nil will be in the combined array.
30
30
  combined_commands = combine_commands(command, commands)
31
- create_received_trigger(combined_commands, item)
31
+ create_received_trigger(combined_commands, item, attach)
32
32
  end.flatten
33
33
  end
34
34
 
@@ -41,7 +41,7 @@ module OpenHAB
41
41
  # @param [Object] item to create trigger for
42
42
  #
43
43
  #
44
- def create_received_trigger(commands, item)
44
+ def create_received_trigger(commands, item, attach)
45
45
  commands.map do |command|
46
46
  if item.is_a? OpenHAB::DSL::Items::GroupItem::GroupMembers
47
47
  config, trigger = create_group_command_trigger(item)
@@ -49,7 +49,7 @@ module OpenHAB
49
49
  config, trigger = create_item_command_trigger(item)
50
50
  end
51
51
  config['command'] = command.to_s unless command.nil?
52
- append_trigger(trigger, config)
52
+ append_trigger(trigger, config, attach: attach)
53
53
  end
54
54
  end
55
55
 
@@ -46,9 +46,10 @@ module OpenHAB
46
46
  #
47
47
  # @return [Trigger] OpenHAB trigger
48
48
  #
49
- def append_trigger(type, config)
49
+ def append_trigger(type, config, attach: nil)
50
50
  logger.trace("Creating trigger of type #{type} for #{config}")
51
51
  trigger = Trigger.trigger(type: type, config: config)
52
+ @attachments[trigger.id] = attach if attach
52
53
  @triggers << trigger
53
54
  trigger
54
55
  end
@@ -19,12 +19,12 @@ module OpenHAB
19
19
  #
20
20
  # @return [Trigger] Trigger for updated entity
21
21
  #
22
- def updated(*items, to: nil)
22
+ def updated(*items, to: nil, attach: nil)
23
23
  separate_groups(items).map do |item|
24
24
  logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
25
25
  [to].flatten.map do |to_state|
26
26
  trigger, config = create_update_trigger(item, to_state)
27
- append_trigger(trigger, config)
27
+ append_trigger(trigger, config, attach: attach)
28
28
  end
29
29
  end.flatten
30
30
  end
@@ -161,7 +161,8 @@ module OpenHAB
161
161
  time_string = "#{time_string}T00:00:00#{zone}" if DATE_ONLY_REGEX.match?(time_string)
162
162
  self <=> DateTimeType.parse(time_string)
163
163
  elsif other.respond_to?(:coerce)
164
- lhs, rhs = other.coerce(self)
164
+ return nil unless (lhs, rhs = other.coerce(self))
165
+
165
166
  lhs <=> rhs
166
167
  end
167
168
  end
@@ -179,13 +180,11 @@ module OpenHAB
179
180
  def coerce(other)
180
181
  logger.trace("Coercing #{self} as a request from #{other.class}")
181
182
  if other.is_a?(Items::DateTimeItem)
182
- raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
183
+ return unless other.state?
183
184
 
184
185
  [other.state, self]
185
186
  elsif other.respond_to?(:to_time)
186
187
  [DateTimeType.new(other), self]
187
- else
188
- raise TypeError, "can't convert #{other.class} into #{self.class}"
189
188
  end
190
189
  end
191
190
 
@@ -286,8 +285,7 @@ module OpenHAB
286
285
  self + other
287
286
  elsif other.respond_to?(:to_d)
288
287
  DateTimeType.new(zoned_date_time.plusNanos((other.to_d * 1_000_000_000).to_i))
289
- elsif other.respond_to?(:coerce)
290
- lhs, rhs = other.coerce(to_d)
288
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
291
289
  lhs + rhs
292
290
  else
293
291
  raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
@@ -320,8 +318,7 @@ module OpenHAB
320
318
  self - other
321
319
  elsif other.respond_to?(:to_d)
322
320
  DateTimeType.new(zoned_date_time.minusNanos((other.to_d * 1_000_000_000).to_i))
323
- elsif other.respond_to?(:coerce)
324
- lhs, rhs = other.coerce(to_d)
321
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
325
322
  lhs - rhs
326
323
  else
327
324
  raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
@@ -87,7 +87,8 @@ module OpenHAB
87
87
  elsif other.respond_to?(:to_d)
88
88
  to_d <=> other.to_d
89
89
  elsif other.respond_to?(:coerce)
90
- lhs, rhs = other.coerce(self)
90
+ return nil unless (lhs, rhs = other.coerce(self))
91
+
91
92
  lhs <=> rhs
92
93
  end
93
94
  end
@@ -109,15 +110,13 @@ module OpenHAB
109
110
  logger.trace("Coercing #{self} as a request from #{other.class}")
110
111
  if other.is_a?(Items::NumericItem) ||
111
112
  (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
112
- raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
113
+ return unless other.state?
113
114
 
114
115
  [other.state, self]
115
116
  elsif other.is_a?(Type)
116
117
  [other, as(other.class)]
117
118
  elsif other.respond_to?(:to_d)
118
119
  [self.class.new(other.to_d), self]
119
- else
120
- raise TypeError, "can't convert #{other.class} into #{self.class}"
121
120
  end
122
121
  end
123
122
 
@@ -150,8 +149,7 @@ module OpenHAB
150
149
  # # result could already be a QuantityType
151
150
  # result = self.class.new(result) unless result.is_a?(NumericType)
152
151
  # result
153
- # elsif other.respond_to?(:coerce)
154
- # lhs, rhs = other.coerce(to_d)
152
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
155
153
  # lhs + rhs
156
154
  # else
157
155
  # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
@@ -168,8 +166,7 @@ module OpenHAB
168
166
  # result could already be a QuantityType
169
167
  result = self.class.new(result) unless result.is_a?(NumericType)
170
168
  result
171
- elsif other.respond_to?(:coerce)
172
- lhs, rhs = other.coerce(to_d)
169
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
173
170
  lhs #{ruby_op} rhs
174
171
  else
175
172
  raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
@@ -133,7 +133,7 @@ module OpenHAB
133
133
  logger.trace("Coercing #{self} as a request from #{other.class}")
134
134
  if other.is_a?(Items::NumericItem) ||
135
135
  (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
136
- raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
136
+ return unless other.state?
137
137
 
138
138
  [other.state, self]
139
139
  elsif other.respond_to?(:to_str)
@@ -64,7 +64,8 @@ module OpenHAB
64
64
  elsif other.respond_to?(:to_str)
65
65
  self == PointType.new(other)
66
66
  elsif other.respond_to?(:coerce)
67
- lhs, rhs = other.coerce(self)
67
+ return false unless (lhs, rhs = other.coerce(self))
68
+
68
69
  lhs == rhs
69
70
  end
70
71
  end
@@ -80,7 +81,10 @@ module OpenHAB
80
81
  # @return [[PointType, PointType]]
81
82
  #
82
83
  def coerce(other)
83
- [coerce_single(other), self]
84
+ lhs = coerce_single(other)
85
+ return unless lhs
86
+
87
+ [lhs, self]
84
88
  end
85
89
 
86
90
  # rename raw methods so we can overwrite them
@@ -123,7 +127,10 @@ module OpenHAB
123
127
  # @return [QuantityType]
124
128
  def distance_from(other)
125
129
  logger.trace("(#{self}).distance_from(#{other} (#{other.class})")
126
- QuantityType.new(raw_distance_from(coerce_single(other)), SIUnits::METRE)
130
+ other = coerce_single(other)
131
+ raise TypeError, "#{other.class} can't be coerced into #{self.class}" unless other
132
+
133
+ QuantityType.new(raw_distance_from(other), SIUnits::METRE)
127
134
  end
128
135
  alias - distance_from
129
136
 
@@ -131,18 +138,16 @@ module OpenHAB
131
138
 
132
139
  # coerce an object to a PointType
133
140
  # @return [PointType]
134
- def coerce_single(other) # rubocop:disable Metrics/MethodLength
141
+ def coerce_single(other)
135
142
  logger.trace("Coercing #{self} as a request from #{other.class}")
136
143
  if other.is_a?(PointType)
137
144
  other
138
145
  elsif other.is_a?(Items::LocationItem)
139
- raise TypeError, "can't convert #{other.raw_state} into #{self.class}" unless other.state?
146
+ return unless other.state?
140
147
 
141
148
  other.state
142
149
  elsif other.respond_to?(:to_str)
143
150
  PointType.new(other.to_str)
144
- else
145
- raise TypeError, "can't convert #{other.class} into #{self.class}"
146
151
  end
147
152
  end
148
153
  end
@@ -61,7 +61,8 @@ module OpenHAB
61
61
  elsif other.respond_to?(:to_d)
62
62
  compare_to(QuantityType.new(other.to_d.to_java, Units.unit || unit))
63
63
  elsif other.respond_to?(:coerce)
64
- lhs, rhs = other.coerce(self)
64
+ return nil unless (lhs, rhs = other.coerce(self))
65
+
65
66
  lhs <=> rhs
66
67
  end
67
68
  end
@@ -82,7 +83,7 @@ module OpenHAB
82
83
  logger.trace("Coercing #{self} as a request from #{other.class}")
83
84
  if other.is_a?(Items::NumericItem) ||
84
85
  (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
85
- raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
86
+ return unless other.state?
86
87
 
87
88
  [other.state, self]
88
89
  elsif other.is_a?(Type)
@@ -91,8 +92,6 @@ module OpenHAB
91
92
  [QuantityType.new(other.to_d.to_java, ONE), self]
92
93
  elsif other.is_a?(String)
93
94
  [QuantityType.new(other), self]
94
- else
95
- raise TypeError, "can't convert #{other.class} into #{self.class}"
96
95
  end
97
96
  end
98
97
 
@@ -123,9 +122,8 @@ module OpenHAB
123
122
  # elsif other.respond_to?(:to_d)
124
123
  # other = other.to_d.to_java
125
124
  # add_quantity(self.class.new(other, Units.unit || unit))
126
- # elsif other.respond_to?(:coerce)
127
- # lhs, rhs = other.coerce(to_d)
128
- # lhs = rhs
125
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
126
+ # lhs + rhs
129
127
  # else
130
128
  # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
131
129
  # end
@@ -148,8 +146,7 @@ module OpenHAB
148
146
  elsif other.respond_to?(:to_d)
149
147
  other = other.to_d.to_java
150
148
  #{java_op}_quantity(#{convert})
151
- elsif other.respond_to?(:coerce)
152
- lhs, rhs = other.coerce(to_d)
149
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
153
150
  lhs #{ruby_op} rhs
154
151
  else
155
152
  raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
@@ -179,8 +176,7 @@ module OpenHAB
179
176
  # self * self.class.new(other)
180
177
  # elsif other.respond_to?(:to_d)
181
178
  # multiply(other.to_d.to_java)
182
- # elsif other.respond_to?(:coerce)
183
- # lhs, rhs = other.coerce(to_d)
179
+ # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
184
180
  # lhs * rhs
185
181
  # else
186
182
  # raise TypeError, "#{other.class} can't be coerced into #{self.class}"
@@ -202,8 +198,7 @@ module OpenHAB
202
198
  self #{ruby_op} self.class.new(other)
203
199
  elsif other.respond_to?(:to_d)
204
200
  #{java_op}(other.to_d.to_java)
205
- elsif other.respond_to?(:coerce)
206
- lhs, rhs = other.coerce(to_d)
201
+ elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
207
202
  lhs #{ruby_op} rhs
208
203
  else
209
204
  raise TypeError, "\#{other.class} can't be coerced into \#{self.class}"
@@ -52,7 +52,8 @@ module OpenHAB
52
52
  elsif other.respond_to?(:to_str)
53
53
  to_str <=> other.to_str
54
54
  elsif other.respond_to?(:coerce)
55
- lhs, rhs = other.coerce(self)
55
+ return nil unless (lhs, rhs = other.coerce(self))
56
+
56
57
  lhs <=> rhs
57
58
  end
58
59
  end
@@ -70,13 +71,11 @@ module OpenHAB
70
71
  def coerce(other)
71
72
  logger.trace("Coercing #{self} as a request from #{other.class}")
72
73
  if other.is_a?(Items::StringItem)
73
- raise TypeError, "can't convert #{other.raw_state} into #{self.class}" unless other.state?
74
+ return unless other.state?
74
75
 
75
76
  [other.state, self]
76
77
  elsif other.respond_to?(:to_str)
77
78
  [String.new(other.to_str), self]
78
- else
79
- raise TypeError, "can't convert #{other.class} into #{self.class}"
80
79
  end
81
80
  end
82
81
 
@@ -28,8 +28,6 @@ module OpenHAB
28
28
  def coerce(other)
29
29
  logger.trace("Coercing #{self} (#{self.class}) as a request from #{other.class}")
30
30
  return [other.as(self.class), self] if other.is_a?(Type)
31
-
32
- raise TypeError, "can't convert #{other.class} into #{self.class}"
33
31
  end
34
32
 
35
33
  #
@@ -49,7 +47,8 @@ module OpenHAB
49
47
  # @return [Boolean] if the same value is represented, including
50
48
  # type conversions
51
49
  #
52
- def ==(other)
50
+ def ==(other) # rubocop:disable Metrics
51
+ logger.trace("(#{self.class}) #{self} == #{other} (#{other.class})")
53
52
  return true if equal?(other)
54
53
 
55
54
  # i.e. ON == OFF, REFRESH == ON, ON == REFRESH
@@ -60,7 +59,17 @@ module OpenHAB
60
59
  return self == other.raw_state if other.is_a?(Items::GenericItem)
61
60
 
62
61
  if other.respond_to?(:coerce)
63
- lhs, rhs = other.coerce(self)
62
+ begin
63
+ return false unless (lhs, rhs = other.coerce(self))
64
+ rescue TypeError
65
+ # this one is a bit odd. 50 (Integer) == ON is internally
66
+ # flipping the argument and calling this method. but it responds
67
+ # to coerce, and then raises a TypeError (from Float???) that
68
+ # it couldn't convert to OnOffType. it probably should have
69
+ # returned nil. catch it and return false instead
70
+ return false
71
+ end
72
+
64
73
  return lhs == rhs
65
74
  end
66
75
 
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.8.5'
8
+ VERSION = '4.10.2'
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.8.5
4
+ version: 4.10.2
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-11-01 00:00:00.000000000 Z
11
+ date: 2021-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -93,6 +93,7 @@ files:
93
93
  - lib/openhab/dsl/persistence.rb
94
94
  - lib/openhab/dsl/rules/automation_rule.rb
95
95
  - lib/openhab/dsl/rules/guard.rb
96
+ - lib/openhab/dsl/rules/item_event.rb
96
97
  - lib/openhab/dsl/rules/property.rb
97
98
  - lib/openhab/dsl/rules/rule.rb
98
99
  - lib/openhab/dsl/rules/rule_config.rb