openhab-scripting 4.10.0 → 4.11.0

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: 14f2ced679ac7bcaa331235fa8e86156b7c25d106628047f36d8bbd8c1ee2e0d
4
- data.tar.gz: 164856fab952fec915c2e562b1ef7da5e545a560efb2001e286360d6b558da14
3
+ metadata.gz: 7f4fc0e817de7a0a8ef1892e7e397552afb897bc45983935a73ab39f03975733
4
+ data.tar.gz: 756291721126083940a335788551a7d1bafdd7643b0bd4cd5cb3bedb7b576ae0
5
5
  SHA512:
6
- metadata.gz: 4d79581b46aa3606f63e79a7cc3a2ece846506f90c244a554df236bde8feb9f46067de014bbbff7639436716ec95b040949f632b60ecd86fc7580cc387039fe5
7
- data.tar.gz: 2c3f012ee50964c35c6996253fb5001b1253c4cf155f5d677174ba16ff765e8f4982a90bd9907876883d37702d0b2b8ff6c76c37d362f05df4c21c82218456f5
6
+ metadata.gz: 58b0de14c919cdc09bef1d8f37c782052a8a36740feddf797e2a8d38a112b334d795a270b757dbae3938269faf29b117aceb303de2c3878da608214aeb25e7fc
7
+ data.tar.gz: a0079a59f25d709814f20527045d7b7c57f4b7c702f3618c616be56117e60b7e0920d023d19d2752556f41f2a85b3e617280e00176a2d60513bef07a0067e882
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'time/time_of_day'
4
+ require_relative 'time/month_day'
5
+
6
+ module OpenHAB
7
+ module DSL
8
+ # Supports between range syntax
9
+ module Between
10
+ # Creates a range that can be compared against time of day/month days or strings
11
+ # to see if they are within the range
12
+ # @since 2.4.0
13
+ # @return Range object representing a TimeOfDay Range
14
+ def between(range)
15
+ raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
16
+
17
+ return OpenHAB::DSL::Between::MonthDayRange.range(range) if OpenHAB::DSL::Between::MonthDayRange.range?(range)
18
+
19
+ OpenHAB::DSL::Between::TimeOfDay.between(range)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -15,7 +15,7 @@ require 'openhab/dsl/actions'
15
15
  require 'openhab/dsl/timers'
16
16
  require 'openhab/dsl/group'
17
17
  require 'openhab/dsl/things'
18
- require 'openhab/dsl/time_of_day'
18
+ require 'openhab/dsl/between'
19
19
  require 'openhab/dsl/gems'
20
20
  require 'openhab/dsl/persistence'
21
21
  require 'openhab/dsl/units'
@@ -31,6 +31,7 @@ module OpenHAB
31
31
  # rubocop:disable Metrics/MethodLength
32
32
  def self.extended(base)
33
33
  base.send :include, OpenHAB::DSL::Actions
34
+ base.send :include, OpenHAB::DSL::Between
34
35
  base.send :include, OpenHAB::DSL::Groups
35
36
  base.send :include, OpenHAB::DSL::Items
36
37
  base.send :include, OpenHAB::DSL::Persistence
@@ -39,7 +40,7 @@ module OpenHAB
39
40
  base.send :include, OpenHAB::DSL::States
40
41
  base.send :include, OpenHAB::DSL::Things
41
42
  base.send :include, OpenHAB::DSL::Timers
42
- base.send :include, OpenHAB::DSL::TimeOfDay
43
+ base.send :include, OpenHAB::DSL::Between
43
44
  base.send :include, OpenHAB::DSL::Types
44
45
  base.send :include, OpenHAB::DSL::Units
45
46
  end
@@ -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
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'openhab/dsl/time_of_day'
4
-
5
3
  require_relative 'numeric_item'
6
4
 
7
5
  module OpenHAB
@@ -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
@@ -4,6 +4,7 @@ require 'java'
4
4
  require 'set'
5
5
  require 'openhab/core/thread_local'
6
6
  require 'openhab/log/logger'
7
+ require 'openhab/dsl/between'
7
8
 
8
9
  require_relative 'item_event'
9
10
 
@@ -22,7 +23,7 @@ module OpenHAB
22
23
  class AutomationRule < Java::OrgOpenhabCoreAutomationModuleScriptRulesupportSharedSimple::SimpleRule
23
24
  include OpenHAB::Log
24
25
  include OpenHAB::Core::ThreadLocal
25
- include OpenHAB::DSL::TimeOfDay
26
+ include OpenHAB::DSL::Between
26
27
  java_import java.time.ZonedDateTime
27
28
 
28
29
  #
@@ -42,7 +43,7 @@ module OpenHAB
42
43
  @run_queue = config.run
43
44
  @guard = config.guard
44
45
  between = config.between&.yield_self { between(config.between) }
45
- @between = between || OpenHAB::DSL::TimeOfDay::ALL_DAY
46
+ @between = between || OpenHAB::DSL::Between::ALL_DAY
46
47
  # Convert between to correct range or nil if not set
47
48
  @trigger_delays = config.trigger_delays
48
49
  @attachments = config.attachments
@@ -10,7 +10,7 @@ require 'openhab/dsl/rules/triggers/command'
10
10
  require 'openhab/dsl/rules/triggers/updated'
11
11
  require 'openhab/dsl/rules/guard'
12
12
  require 'openhab/core/entity_lookup'
13
- require 'openhab/dsl/time_of_day'
13
+ require 'openhab/dsl/between'
14
14
  require 'openhab/dsl/dsl'
15
15
  require 'openhab/dsl/timers'
16
16
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'java'
4
- require 'openhab/dsl/time_of_day'
5
4
 
6
5
  module OpenHAB
7
6
  module DSL
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ # Support for time related functions
6
+ module Between
7
+ # Manages Month Day Ranges
8
+ module MonthDayRange
9
+ include OpenHAB::Log
10
+
11
+ java_import java.time.Year
12
+
13
+ # Lambdas are used to calculate the year for the month day
14
+ # which must happen during evaluation time to support that rules
15
+ # creation and evaluation for execution are done in distinct phases
16
+ @current_year = -> { return Year.now }
17
+ @next_year = -> { return Year.now.plus_years(1) }
18
+
19
+ class << self
20
+ attr_reader :current_year, :next_year
21
+ end
22
+
23
+ # Creates a range that can be compared against MonthDay objects, strings
24
+ # or anything responding to 'to_date' to see if they are within the range
25
+ # @return Range object representing a MonthDay Range
26
+ # rubocop:disable Metrics/AbcSize
27
+ # Range method cannot be broken up cleaner
28
+ def self.range(range)
29
+ logger.trace "Creating MonthDay range from #{range}"
30
+ raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
31
+
32
+ start = MonthDay.parse(range.begin)
33
+ ending = MonthDay.parse(range.end)
34
+
35
+ logger.trace "Month Day Range Start(#{start}) - End (#{ending})"
36
+
37
+ # Wrap to next year if ending day of month is before starting day of month
38
+ ending_year = ending < start ? next_year : current_year
39
+
40
+ start_range = MonthDayRangeElement.new(month_day: start, year: current_year)
41
+ ending_range = MonthDayRangeElement.new(month_day: ending, year: ending_year)
42
+ range.exclude_end? ? (start_range...ending_range) : (start_range..ending_range)
43
+ end
44
+ # rubocop:enable Metrics/AbcSize
45
+
46
+ # Checks if supplied range can be converted to a month day range
47
+ # @param [Range] range to check begin and end values of
48
+ # @return [Boolean] Returns true if supplied range can be converted to a month day range
49
+ def self.range?(range)
50
+ return false unless range.is_a? Range
51
+
52
+ MonthDay.day_of_month?(range.begin) && MonthDay.day_of_month?(range.end)
53
+ end
54
+
55
+ # Represents a range element for a MonthDay object
56
+ # The LocalDate (MonthDay + Year) is dynamically calculated to allow for
57
+ # being used as a guard during rule evaluation
58
+ class MonthDayRangeElement
59
+ include Comparable
60
+ include OpenHAB::Log
61
+ java_import java.time.LocalDate
62
+ java_import java.time.Year
63
+
64
+ # Create a new MonthDayRange element
65
+ # @param [MonthDay] MonthDay element
66
+ # @param [Lambda] year lambda to calculate year to convert MonthDay to LocalDate
67
+ #
68
+ def initialize(month_day:, year:)
69
+ @month_day = month_day
70
+ @year = year
71
+ end
72
+
73
+ # Convert into a LocalDate using year lambda supplied in initializer
74
+ def to_local_date
75
+ @year.call.at_month_day(@month_day)
76
+ end
77
+
78
+ # Returns the MonthDay advanced by 1 day
79
+ # Required by Range class
80
+ def succ
81
+ next_date = to_local_date.plus_days(1)
82
+ # Handle rollover to next year
83
+ year = -> { Year.from(next_date) }
84
+ MonthDayRangeElement.new(month_day: MonthDay.from(next_date), year: year)
85
+ end
86
+
87
+ # Compare MonthDayRangeElement to other objects as required by Range class
88
+ # rubocop:disable Metrics/AbcSize
89
+ # Case statement needs to work against multiple types
90
+ def <=>(other)
91
+ case other
92
+ when LocalDate then to_local_date.compare_to(other)
93
+ when Date then self.<=>(LocalDate.of(other.year, other.month, other.day))
94
+ when MonthDay then self.<=>(MonthDayRange.current_year.call.at_month_day(other))
95
+ else
96
+ return self.<=>(other.to_local_date) if other.respond_to? :to_local_date
97
+ return self.<=>(other.to_date) if other.respond_to? :to_date
98
+
99
+ raise "Unable to convert #{other.class} to compare to MonthDay"
100
+ end
101
+ end
102
+ # rubocop:enable Metrics/AbcSize
103
+ end
104
+ end
105
+
106
+ java_import java.time.MonthDay
107
+ # Extend MonthDay java object with some helper methods
108
+ class MonthDay
109
+ include OpenHAB::Log
110
+ # Parse MonthDay string as defined with by Monthday class without leading double dash "--"
111
+ def self.parse(string)
112
+ ## string = "--#{string}" unless string.to_s.start_with? '--'
113
+ java_send :parse, [java.lang.CharSequence], "--#{string}"
114
+ end
115
+
116
+ # Can the supplied object be parsed into a MonthDay
117
+ def self.day_of_month?(obj)
118
+ /^-*[01][0-9]-[0-3]\d$/.match? obj.to_s
119
+ end
120
+
121
+ # Remove -- from MonthDay string representation
122
+ def to_s
123
+ to_string.delete_prefix('--')
124
+ end
125
+
126
+ # Extends MonthDay comparison to support Strings
127
+ # Necessary to support mixed ranges of Strings and MonthDay types
128
+ # @return [Number, nil] -1,0,1 if other MonthDay is less than, equal to, or greater than this MonthDay
129
+ def <=>(other)
130
+ case other
131
+ when String
132
+ self.<=>(MonthDay.parse(other))
133
+ else
134
+ super
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -10,7 +10,7 @@ module OpenHAB
10
10
  # Times without specific dates e.g. 6:00:00
11
11
  # @author Brian O'Connell
12
12
  # @since 0.0.1
13
- module TimeOfDay
13
+ module Between
14
14
  java_import java.time.LocalTime
15
15
  java_import java.time.format.DateTimeFormatterBuilder
16
16
  java_import java.util.Locale
@@ -123,6 +123,41 @@ module OpenHAB
123
123
  -(other <=> self)
124
124
  end
125
125
  end
126
+
127
+ # Creates a range that can be compared against time of day objects or strings
128
+ # to see if they are within the range
129
+ # @since 2.4.0
130
+ # @return Range object representing a TimeOfDay Range
131
+ def self.between(range)
132
+ raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
133
+
134
+ start = to_time_of_day(range.begin)
135
+ ending = to_time_of_day(range.end)
136
+
137
+ start_sod = start.local_time.to_second_of_day
138
+ ending_sod = ending.local_time.to_second_of_day
139
+ ending_sod += TimeOfDayRangeElement::NUM_SECONDS_IN_DAY if ending_sod < start_sod
140
+
141
+ start_range = TimeOfDayRangeElement.new(sod: start_sod, range_begin: start_sod)
142
+ ending_range = TimeOfDayRangeElement.new(sod: ending_sod, range_begin: start_sod)
143
+ range.exclude_end? ? (start_range...ending_range) : (start_range..ending_range)
144
+ end
145
+
146
+ #
147
+ # Convert object to TimeOfDay object
148
+ #
149
+ # @param [Object] object TimeOfDay or String to be converted
150
+ #
151
+ # @return [TimeOfDay] TimeOfDay created from supplied object
152
+ #
153
+ def self.to_time_of_day(object)
154
+ case object
155
+ when String then TimeOfDay.parse(object)
156
+ when Time, OpenHAB::DSL::Types::DateTimeType, OpenHAB::DSL::Items::DateTimeItem
157
+ TimeOfDay.new(h: object.hour, m: object.min, s: object.sec)
158
+ else object
159
+ end
160
+ end
126
161
  end
127
162
 
128
163
  # Modules that refines the Ruby Range object cover? and include? methods to support TimeOfDay ranges
@@ -168,17 +203,20 @@ module OpenHAB
168
203
  #
169
204
  # @return [Integer] seconds of day represented by supplied object
170
205
  #
206
+ # rubocop:disable Metrics/AbcSize
207
+ # case statement needs to compare against multiple types
171
208
  def to_second_of_day(object)
172
209
  case object
173
210
  when TimeOfDay then adjust_second_of_day(object.local_time.to_second_of_day)
174
211
  when String then adjust_second_of_day(TimeOfDay.parse(object).local_time.to_second_of_day)
175
- when Time, OpenHAB::DSL::Types::DateTimeType, OpenHAB::DSL::Items::DateTimeItem
212
+ when ::Time, OpenHAB::DSL::Types::DateTimeType, OpenHAB::DSL::Items::DateTimeItem
176
213
  adjust_second_of_day(TimeOfDay.new(h: object.hour, m: object.min, s: object.sec)
177
214
  .local_time.to_second_of_day)
178
215
  when TimeOfDayRangeElement then object.sod
179
- else raise ArgumentError, 'Supplied argument cannot be converted into Time Of Day Object'
216
+ else raise ArgumentError, "Supplied argument #{object.class} cannot be converted into Time Of Day Object"
180
217
  end
181
218
  end
219
+ # rubocop:enable Metrics/AbcSize
182
220
 
183
221
  def adjust_second_of_day(second_of_day)
184
222
  second_of_day += NUM_SECONDS_IN_DAY if second_of_day < @range_begin
@@ -186,46 +224,9 @@ module OpenHAB
186
224
  end
187
225
  end
188
226
 
189
- # Creates a range that can be compared against time of day objects or strings
190
- # to see if they are within the range
191
- # @since 2.4.0
192
- # @return Range object representing a TimeOfDay Range
193
- module_function
194
-
195
- def between(range)
196
- raise ArgumentError, 'Supplied object must be a range' unless range.is_a? Range
197
-
198
- start = to_time_of_day(range.begin)
199
- ending = to_time_of_day(range.end)
200
-
201
- start_sod = start.local_time.to_second_of_day
202
- ending_sod = ending.local_time.to_second_of_day
203
- ending_sod += TimeOfDayRangeElement::NUM_SECONDS_IN_DAY if ending_sod < start_sod
204
-
205
- start_range = TimeOfDayRangeElement.new(sod: start_sod, range_begin: start_sod)
206
- ending_range = TimeOfDayRangeElement.new(sod: ending_sod, range_begin: start_sod)
207
- range.exclude_end? ? (start_range...ending_range) : (start_range..ending_range)
208
- end
209
-
210
- #
211
- # Convert object to TimeOfDay object
212
- #
213
- # @param [Object] object TimeOfDay or String to be converted
214
- #
215
- # @return [TimeOfDay] TimeOfDay created from supplied object
216
- #
217
- private_class_method def to_time_of_day(object)
218
- case object
219
- when String then TimeOfDay.parse(object)
220
- when Time, OpenHAB::DSL::Types::DateTimeType, OpenHAB::DSL::Items::DateTimeItem
221
- TimeOfDay.new(h: object.hour, m: object.min, s: object.sec)
222
- else object
223
- end
224
- end
225
-
226
227
  MIDNIGHT = TimeOfDay.midnight
227
228
  NOON = TimeOfDay.noon
228
- ALL_DAY = between(TimeOfDay.new(h: 0, m: 0, s: 0)..TimeOfDay.new(h: 23, m: 59, s: 59))
229
+ ALL_DAY = TimeOfDay.between(TimeOfDay.new(h: 0, m: 0, s: 0)..TimeOfDay.new(h: 23, m: 59, s: 59))
229
230
  end
230
231
  end
231
232
  end
@@ -59,6 +59,10 @@ module OpenHAB
59
59
  # @return [Timer] Rescheduled timer instances
60
60
  #
61
61
  def reschedule(duration = nil)
62
+ unless duration.nil? || duration.is_a?(Java::JavaTimeTemporal::TemporalAmount)
63
+ raise ArgumentError, 'Supplied argument must be a duration'
64
+ end
65
+
62
66
  duration ||= @duration
63
67
  Timers.timer_manager.add(self)
64
68
  @timer.reschedule(ZonedDateTime.now.plus(duration))
@@ -59,7 +59,7 @@ module OpenHAB
59
59
  rescue java.lang.StringIndexOutOfBoundsException, java.lang.IllegalArgumentException
60
60
  # Try ruby's Time.parse if OpenHAB's DateTimeType parser fails
61
61
  begin
62
- DateTimeType.new(Time.parse(time_string))
62
+ DateTimeType.new(::Time.parse(time_string))
63
63
  rescue ArgumentError
64
64
  raise ArgumentError, "Unable to parse #{time_string} into a DateTimeType"
65
65
  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
 
@@ -195,7 +194,7 @@ module OpenHAB
195
194
  # @return [Time] A Time object representing the same instant and timezone
196
195
  #
197
196
  def to_time
198
- Time.at(to_i, nsec, :nsec).localtime(utc_offset)
197
+ ::Time.at(to_i, nsec, :nsec).localtime(utc_offset)
199
198
  end
200
199
 
201
200
  #
@@ -257,7 +256,7 @@ module OpenHAB
257
256
  # @!visibility private
258
257
  def respond_to_missing?(method, _include_private = false)
259
258
  return true if zoned_date_time.respond_to?(method)
260
- return true if Time.instance_methods.include?(method.to_sym)
259
+ return true if ::Time.instance_methods.include?(method.to_sym)
261
260
 
262
261
  super
263
262
  end
@@ -268,7 +267,7 @@ module OpenHAB
268
267
  #
269
268
  def method_missing(method, *args, &block)
270
269
  return zoned_date_time.send(method, *args, &block) if zoned_date_time.respond_to?(method)
271
- return to_time.send(method, *args, &block) if Time.instance_methods.include?(method.to_sym)
270
+ return to_time.send(method, *args, &block) if ::Time.instance_methods.include?(method.to_sym)
272
271
 
273
272
  super
274
273
  end
@@ -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.10.0'
8
+ VERSION = '4.11.0'
9
9
  end
data/lib/openhab.rb CHANGED
@@ -19,7 +19,6 @@ module OpenHAB
19
19
  # @param [Object] base Object to decorate with DSL and helper methods
20
20
  #
21
21
  #
22
- # rubocop:disable Metrics/MethodLength
23
22
  # Number of extensions and includes requires more lines
24
23
  def self.extended(base)
25
24
  OpenHAB::Core.wait_till_openhab_ready
@@ -27,16 +26,14 @@ module OpenHAB
27
26
  base.extend OpenHAB::Core::ScriptHandling
28
27
  base.extend OpenHAB::Core::EntityLookup
29
28
  base.extend OpenHAB::DSL
30
- base.extend OpenHAB::DSL::TimeOfDay
29
+ base.extend OpenHAB::DSL::Between
31
30
 
32
- base.send :include, OpenHAB::DSL::TimeOfDay
33
31
  base.send :include, OpenHAB::DSL::Items
34
32
  base.send :include, OpenHAB::DSL::Types
35
33
  logger.info "OpenHAB JRuby Scripting Library Version #{OpenHAB::VERSION} Loaded"
36
34
 
37
35
  OpenHAB::Core.add_rubylib_to_load_path
38
36
  end
39
- # rubocop:enable Metrics/MethodLength
40
37
  end
41
38
 
42
39
  # 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.10.0
4
+ version: 4.11.0
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-02 00:00:00.000000000 Z
11
+ date: 2021-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,6 +53,7 @@ files:
53
53
  - lib/openhab/core/script_handling.rb
54
54
  - lib/openhab/core/thread_local.rb
55
55
  - lib/openhab/dsl/actions.rb
56
+ - lib/openhab/dsl/between.rb
56
57
  - lib/openhab/dsl/dsl.rb
57
58
  - lib/openhab/dsl/gems.rb
58
59
  - lib/openhab/dsl/group.rb
@@ -106,7 +107,8 @@ files:
106
107
  - lib/openhab/dsl/rules/triggers/updated.rb
107
108
  - lib/openhab/dsl/states.rb
108
109
  - lib/openhab/dsl/things.rb
109
- - lib/openhab/dsl/time_of_day.rb
110
+ - lib/openhab/dsl/time/month_day.rb
111
+ - lib/openhab/dsl/time/time_of_day.rb
110
112
  - lib/openhab/dsl/timers.rb
111
113
  - lib/openhab/dsl/timers/manager.rb
112
114
  - lib/openhab/dsl/timers/reentrant_timer.rb