openhab-scripting 4.10.0 → 4.11.0

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: 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