openhab-scripting 2.16.4 → 2.19.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: 1cf495280ef0c286169b0d453f3b03688563ab017b0fc5707d0243bfd24d43b1
4
- data.tar.gz: 7e1e590a1c0f25598d0e95841068faca6e9c98261764c0a53dd74b3ac36b82d6
3
+ metadata.gz: 74777515cf7cb008bb80d87ad05a1af9dcd8a260ebeb458b7d9ee24c4aa63453
4
+ data.tar.gz: 28bd0a8950695ac78e91177fe3884e86f278efdba8d695e1cf7f4637a36571a0
5
5
  SHA512:
6
- metadata.gz: 27acec53581abe0cc1df086e92b14591840c437e5cdb189fec7d69f8f72e62c442d10d6781d03c8a5b91e40fbb8d39ac7986d3a82f5c77bb3e84501dc3c314fe
7
- data.tar.gz: 58e558b957c89ea67bf405cb8530e0436d532179b07b9e34b1e79087a639796f4aac25c4a18eebe076ae869116f93fd679a51eb576ca29006a7c54222ef271ad
6
+ metadata.gz: 87f8af88c6f73b7498c054253544a4ac71940f634f1fa45a80c7bc1518c6c9906d3e099a5f0013afa0b4f454f3c06239479507c81afe000ed07e1f5bd052b75f
7
+ data.tar.gz: 5b2b7560d230a1d04725a5635f923b919439bc2156be7fc10474c2f9396c87823939f0cb590db8feb978577c6880e059ed2eb0cf83edd64c04ae915693ccb532
@@ -7,6 +7,8 @@ require 'openhab/dsl/group'
7
7
  require 'openhab/log/logger'
8
8
  require 'openhab/dsl/items/number_item'
9
9
  require 'openhab/dsl/items/string_item'
10
+ require 'openhab/dsl/items/datetime_item'
11
+ require 'openhab/dsl/items/rollershutter_item'
10
12
 
11
13
  # Automation lookup and injection of OpenHab entities
12
14
  java_import org.openhab.core.items.GroupItem
@@ -84,6 +86,9 @@ module OpenHAB
84
86
  #
85
87
  # @return [Object] the ruby wrapper for the item
86
88
  #
89
+ # rubocop: disable Metrics/MethodLength
90
+ # rubocop: disable Metrics/AbcSize
91
+ # Disabled line length and branch size - case dispatch pattern
87
92
  private_class_method def self.decorate_item(item)
88
93
  case item
89
94
  when GroupItem
@@ -92,10 +97,16 @@ module OpenHAB
92
97
  OpenHAB::DSL::Items::NumberItem.new(item)
93
98
  when Java::Org.openhab.core.library.items::StringItem
94
99
  OpenHAB::DSL::Items::StringItem.new(item)
100
+ when Java::Org.openhab.core.library.items::DateTimeItem
101
+ OpenHAB::DSL::Items::DateTimeItem.new(item)
102
+ when Java::Org.openhab.core.library.items::RollershutterItem
103
+ OpenHAB::DSL::Items::RollershutterItem.new(item)
95
104
  else
96
105
  item
97
106
  end
98
107
  end
108
+ # rubocop: enable Metrics/AbcSize
109
+ # rubocop: enable Metrics/MethodLength
99
110
 
100
111
  #
101
112
  # Looks up a Thing in the OpenHAB registry replacing '_' with ':'
@@ -13,11 +13,13 @@ require 'openhab/dsl/timers'
13
13
  require 'openhab/dsl/group'
14
14
  require 'openhab/dsl/things'
15
15
  require 'openhab/dsl/items/items'
16
+ require 'openhab/dsl/items/datetime_item'
16
17
  require 'openhab/dsl/items/number_item'
17
18
  require 'openhab/dsl/time_of_day'
18
19
  require 'openhab/dsl/gems'
19
20
  require 'openhab/dsl/persistence'
20
21
  require 'openhab/dsl/units'
22
+ require 'openhab/dsl/types/datetime'
21
23
  require 'openhab/dsl/types/quantity'
22
24
  require 'openhab/dsl/states'
23
25
 
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'java'
5
+ require 'time'
6
+ require 'openhab/dsl/types/datetime'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ #
12
+ # Delegation to OpenHAB DateTime Item
13
+ #
14
+ # @author Anders Alfredsson
15
+ #
16
+ class DateTimeItem
17
+ extend Forwardable
18
+ include Comparable
19
+
20
+ def_delegator :@datetime_item, :to_s
21
+
22
+ #
23
+ # Create a new DateTimeItem
24
+ #
25
+ # @param [Java::org::openhab::core::libarary::items::DateTimeItem] datetime_item Openhab DateTimeItem to
26
+ # delegate to
27
+ #
28
+ def initialize(datetime_item)
29
+ @datetime_item = datetime_item
30
+ end
31
+
32
+ #
33
+ # Return an instance of DateTime that wraps the DateTimeItem's state
34
+ #
35
+ # @return [OpenHAB::DSL::Types::DateTime] Wrapper for the Item's state, or nil if it has no state
36
+ #
37
+ def to_dt
38
+ OpenHAB::DSL::Types::DateTime.new(@datetime_item.state) if state?
39
+ end
40
+
41
+ #
42
+ # Compare the Item's state to another Item or object that can be compared
43
+ #
44
+ # @param [Object] other Other objet to compare against
45
+ #
46
+ # @return [Integer] -1, 0 or 1 depending on the result of the comparison
47
+ #
48
+ def <=>(other)
49
+ return unless state?
50
+
51
+ logger.trace("Comparing self (#{self.class}) to #{other} (#{other.class})")
52
+ other = other.to_dt if other.is_a? DateTimeItem
53
+ to_dt <=> other
54
+ end
55
+
56
+ #
57
+ # Get the time zone of the Item
58
+ #
59
+ # @return [String] The timezone in `[+-]hh:mm(:ss)` format or nil if the Item has no state
60
+ #
61
+ def zone
62
+ to_dt.zone if state?
63
+ end
64
+
65
+ #
66
+ # Check if missing method can be delegated to other contained objects
67
+ #
68
+ # @param [String, Symbol] meth The method name to check for
69
+ #
70
+ # @return [Boolean] true if DateTimeItem or DateTime responds to the method, false otherwise
71
+ #
72
+ def respond_to_missing?(meth, *)
73
+ @datetime_item.respond_to?(meth) || to_dt.respond_to?(meth)
74
+ end
75
+
76
+ #
77
+ # Forward missing methods to the OpenHAB Item, or a DateTime object wrapping its state
78
+ #
79
+ # @param [String] meth method name
80
+ # @param [Array] args arguments for method
81
+ # @param [Proc] block <description>
82
+ #
83
+ # @return [Object] Value from delegated method in OpenHAB NumberItem
84
+ #
85
+ def method_missing(meth, *args, &block)
86
+ if @datetime_item.respond_to?(meth)
87
+ @datetime_item.__send__(meth, *args, &block)
88
+ elsif state?
89
+ to_dt.send(meth, *args, &block)
90
+ else
91
+ raise NoMethodError, "undefined method `#{meth}' for #{self.class}"
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'java'
5
+
6
+ module OpenHAB
7
+ module DSL
8
+ module Items
9
+ #
10
+ # Delegator to OpenHAB Rollershutter Item
11
+ #
12
+ class RollershutterItem < Numeric
13
+ extend Forwardable
14
+ include Comparable
15
+
16
+ def_delegator :@rollershutter_item, :to_s
17
+
18
+ java_import Java::OrgOpenhabCoreLibraryTypes::PercentType
19
+ java_import Java::OrgOpenhabCoreLibraryTypes::UpDownType
20
+ java_import Java::OrgOpenhabCoreLibraryTypes::StopMoveType
21
+
22
+ #
23
+ # Creates a new RollershutterItem
24
+ #
25
+ # @param [Java::OrgOpenhabCoreLibraryItems::RollershutterItem] rollershutter_item
26
+ # The OpenHAB RollershutterItem to delegate to
27
+ #
28
+ def initialize(rollershutter_item)
29
+ logger.trace("Wrapping #{rollershutter_item}")
30
+ @rollershutter_item = rollershutter_item
31
+
32
+ super()
33
+ end
34
+
35
+ #
36
+ # Check if the rollershutter is up
37
+ #
38
+ # @return [Boolean] true if the rollershutter is up, false otherwise
39
+ #
40
+ def up?
41
+ state.as(UpDownType) == UpDownType::UP
42
+ end
43
+
44
+ #
45
+ # Check if the rollershutter is down
46
+ #
47
+ # @return [Boolean] true if the rollershutter is down, false otherwise
48
+ #
49
+ def down?
50
+ state.as(UpDownType) == UpDownType::DOWN
51
+ end
52
+
53
+ #
54
+ # Returns the rollershutter's position
55
+ #
56
+ # @return [Java::OrgOpenhabCoreLibraryTypes::PercentType] the position of the rollershutter
57
+ #
58
+ def position
59
+ state.as(PercentType)
60
+ end
61
+
62
+ #
63
+ # Compare the rollershutter's position against another object
64
+ #
65
+ # @param [Object] other object to compare against
66
+ #
67
+ # @return [Integer] -1, 0 or 1 depending on the result of the comparison
68
+ #
69
+ def <=>(other)
70
+ case other
71
+ when PercentType, Java::OrgOpenhabCoreLibraryTypes::DecimalType then position.compare_to(other)
72
+ when Numeric then position.int_value <=> other
73
+ when RollershutterItem then position.compare_to(other.position)
74
+ when UpDownType then state.as(UpDownType) == other
75
+ end
76
+ end
77
+
78
+ #
79
+ # Coerce self into other to enable calculations
80
+ #
81
+ # @param [Numeric] other Other numeric to coerce into
82
+ #
83
+ # @return [Array<Numeric>] an array of other and self coerced into other's type
84
+ #
85
+ def coerce(other)
86
+ raise ArgumentError, "Cannot coerce to #{other.class}" unless other.is_a? Numeric
87
+
88
+ case other
89
+ when Integer then [other, position.int_value]
90
+ when Float then [other, position.float_value]
91
+ end
92
+ end
93
+
94
+ #
95
+ # Case equality
96
+ #
97
+ # @param [Java::OrgOpenhabCoreLibraryTypes::UpDownType, Numeric] other Other object to compare against
98
+ #
99
+ # @return [Boolean] true if self can be defined as other, false otherwise
100
+ #
101
+ def ===(other)
102
+ super unless other.is_a? UpDownType
103
+
104
+ state.as(UpDownType).equals(other)
105
+ end
106
+
107
+ #
108
+ # Sends an UP command to the Item
109
+ #
110
+ def up
111
+ command UpDownType::UP
112
+ end
113
+
114
+ #
115
+ # Sends a DOWN command to the Item
116
+ #
117
+ def down
118
+ command UpDownType::DOWN
119
+ end
120
+
121
+ #
122
+ # Sends a STOP command to the Item
123
+ #
124
+ def stop
125
+ command StopMoveType::STOP
126
+ end
127
+
128
+ #
129
+ # Sends a MOVE command to the Item
130
+ #
131
+ def move
132
+ command StopMoveType::MOVE
133
+ end
134
+
135
+ #
136
+ # Define math operations
137
+ #
138
+ %i[+ - * / %].each do |operator|
139
+ define_method(operator) do |other|
140
+ right, left = coerce(other)
141
+ left.send(operator, right)
142
+ end
143
+ end
144
+
145
+ #
146
+ # Checks if this method responds to the missing method
147
+ #
148
+ # @param [String] meth Name of the method to check
149
+ # @param [Boolean] _include_private boolean if private methods should be checked
150
+ #
151
+ # @return [Boolean] true if this object will respond to the supplied method, false otherwise
152
+ #
153
+ def respond_to_missing?(meth, _include_private = false)
154
+ @rollershutter_item.respond_to?(meth) || position.respond_to?(meth)
155
+ end
156
+
157
+ #
158
+ # Forward missing methods to Openhab RollershutterItem or the PercentType representing it's state
159
+ # if they are defined
160
+ #
161
+ # @param [String] meth method name
162
+ # @param [Array] args arguments for method
163
+ # @param [Proc] block <description>
164
+ #
165
+ # @return [Object] Value from delegated method in OpenHAB NumberItem
166
+ #
167
+ def method_missing(meth, *args, &block)
168
+ if @rollershutter_item.respond_to?(meth)
169
+ @rollershutter_item.__send__(meth, *args, &block)
170
+ elsif position.respond_to?(meth)
171
+ position.__send__(meth, *args, &block)
172
+ else
173
+ raise NoMethodError, "No method `#{meth}' defined for #{self.class}"
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
@@ -4,4 +4,5 @@
4
4
  require 'openhab/dsl/monkey_patch/ruby/range'
5
5
  require 'openhab/dsl/monkey_patch/ruby/number'
6
6
  require 'openhab/dsl/monkey_patch/ruby/string'
7
+ require 'openhab/dsl/monkey_patch/ruby/time'
7
8
  require 'bigdecimal/util'
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module MonkeyPatch
6
+ module Ruby
7
+ #
8
+ # Extend Time to make to_s return string parseable by OpenHAB
9
+ #
10
+ module TimeExtensions
11
+ include OpenHAB::Core
12
+
13
+ #
14
+ # Convert to ISO 8601 format
15
+ #
16
+ # @return [Java::JavaTime::Duration] Duration with number of units from self
17
+ #
18
+ def to_s
19
+ strftime '%FT%T.%N%:z'
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ #
28
+ # Extend Time class with to_s method
29
+ #
30
+ class Time
31
+ prepend OpenHAB::DSL::MonkeyPatch::Ruby::TimeExtensions
32
+ end
@@ -6,3 +6,4 @@ require 'openhab/dsl/monkey_patch/types/on_off_type'
6
6
  require 'openhab/dsl/monkey_patch/types/decimal_type'
7
7
  require 'openhab/dsl/monkey_patch/types/percent_type'
8
8
  require 'openhab/dsl/monkey_patch/types/quantity_type'
9
+ require 'openhab/dsl/monkey_patch/types/up_down_type'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ module OpenHAB
5
+ module DSL
6
+ module MonkeyPatch
7
+ #
8
+ # Patches OpenHAB types
9
+ #
10
+ module Types
11
+ java_import Java::OrgOpenhabCoreLibraryTypes::UpDownType
12
+
13
+ #
14
+ # MonkeyPatching UpDownType
15
+ #
16
+ class UpDownType
17
+ #
18
+ # Check if the supplied object is case equals to self
19
+ #
20
+ # @param [Object] other object to compare
21
+ #
22
+ # @return [Boolean] True if the other object is a RollershutterItem and has the same state
23
+ #
24
+ def ===(other)
25
+ super unless other.is_a? OpenHAB::DSL::Items::RollershutterItem
26
+
27
+ equals(other.state.as(UpDownType))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -145,16 +145,14 @@ module OpenHAB
145
145
  #
146
146
  #
147
147
  def process_trigger_delay(trigger_delay, mod, inputs)
148
- if check_trigger_guards(trigger_delay, inputs)
148
+ if trigger_delay.timer_active?
149
+ process_active_timer(inputs, mod, trigger_delay)
150
+ elsif check_trigger_guards(trigger_delay, inputs)
149
151
  logger.trace("Trigger Guards Matched for #{trigger_delay}, delaying rule execution")
150
152
  # Add timer and attach timer to delay object, and also state being tracked to so timer can be cancelled if
151
153
  # state changes
152
154
  # Also another timer should not be created if changed to same value again but instead rescheduled
153
- if trigger_delay.timer_active?
154
- process_active_timer(inputs, mod, trigger_delay)
155
- else
156
- create_trigger_delay_timer(inputs, mod, trigger_delay)
157
- end
155
+ create_trigger_delay_timer(inputs, mod, trigger_delay)
158
156
  else
159
157
  logger.trace("Trigger Guards did not match for #{trigger_delay}, ignoring trigger.")
160
158
  end
@@ -173,7 +171,8 @@ module OpenHAB
173
171
  trigger_delay.timer = after(trigger_delay.duration) do
174
172
  logger.trace("Delay Complete for #{trigger_delay}, executing rule")
175
173
  trigger_delay.timer = nil
176
- process_queue(@run_queue.dup, mod, inputs)
174
+ queue = create_queue(inputs)
175
+ process_queue(queue, mod, inputs)
177
176
  end
178
177
  trigger_delay.tracking_to = inputs['newState']
179
178
  end
@@ -2,8 +2,9 @@
2
2
 
3
3
  require 'java'
4
4
  require 'openhab/log/logger'
5
+ require 'openhab/dsl/items/datetime_item'
6
+ require 'openhab/dsl/types/datetime'
5
7
  require 'time'
6
- require 'date'
7
8
 
8
9
  module OpenHAB
9
10
  module DSL
@@ -172,8 +173,9 @@ module OpenHAB
172
173
  case object
173
174
  when TimeOfDay then adjust_second_of_day(object.local_time.to_second_of_day)
174
175
  when String then adjust_second_of_day(TimeOfDay.parse(object).local_time.to_second_of_day)
175
- when Time then adjust_second_of_day(TimeOfDay.new(h: object.hour, m: object.min,
176
- s: object.sec).local_time.to_second_of_day)
176
+ when Time, OpenHAB::DSL::Types::DateTime, OpenHAB::DSL::Items::DateTimeItem
177
+ adjust_second_of_day(TimeOfDay.new(h: object.hour, m: object.min, s: object.sec)
178
+ .local_time.to_second_of_day)
177
179
  when TimeOfDayRangeElement then object.sod
178
180
  else raise ArgumentError, 'Supplied argument cannot be converted into Time Of Day Object'
179
181
  end
@@ -216,6 +218,8 @@ module OpenHAB
216
218
  private_class_method def to_time_of_day(object)
217
219
  case object
218
220
  when String then TimeOfDay.parse(object)
221
+ when Time, OpenHAB::DSL::Types::DateTime, OpenHAB::DSL::Items::DateTimeItem
222
+ TimeOfDay.new(h: object.hour, m: object.min, s: object.sec)
219
223
  else object
220
224
  end
221
225
  end
@@ -0,0 +1,326 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ require 'forwardable'
5
+ require 'time'
6
+
7
+ module OpenHAB
8
+ module DSL
9
+ module Types
10
+ #
11
+ # Ruby implementation for OpenHAB DateTimeType
12
+ #
13
+ # @author Anders Alfredsson
14
+ #
15
+ # rubocop: disable Metrics/ClassLength
16
+ # Disabled because this class has a single responsibility, there does not appear a logical
17
+ # way of breaking it up into multiple classes
18
+ class DateTime
19
+ extend Forwardable
20
+ include Comparable
21
+ include OpenHAB::Log
22
+
23
+ def_delegator :datetime, :to_s
24
+ def_delegator :zoned_date_time, :month_value, :month
25
+ def_delegator :zoned_date_time, :minute, :min
26
+ def_delegator :zoned_date_time, :second, :sec
27
+ def_delegator :zoned_date_time, :nano, :nsec
28
+ def_delegator :zoned_date_time, :to_epoch_second, :to_i
29
+ alias inspect to_s
30
+
31
+ java_import Java::OrgOpenhabCoreLibraryTypes::DateTimeType
32
+ java_import java.time.ZonedDateTime
33
+ java_import java.time.Instant
34
+ java_import java.time.ZoneId
35
+ java_import java.time.ZoneOffset
36
+ java_import java.time.Duration
37
+
38
+ #
39
+ # Regex expression to identify strings defining a time in hours, minutes and optionally seconds
40
+ #
41
+ TIME_ONLY_REGEX = /\A\d\d:\d\d(:\d\d)?\Z/.freeze
42
+
43
+ #
44
+ # Regex expression to identify strings defining a time in hours, minutes and optionally seconds
45
+ #
46
+ DATE_ONLY_REGEX = /\A\d{4}-\d\d-\d\d\Z/.freeze
47
+
48
+ attr_reader :datetime
49
+
50
+ #
51
+ # Create a new DateTime instance wrapping an OpenHAB DateTimeType
52
+ #
53
+ # @param [Java::org::openhab::core::library::types::DateTimeType] datetime The DateTimeType instance to
54
+ # delegate to, or an object that can be converted to a DateTimeType
55
+ #
56
+ def initialize(datetime)
57
+ @datetime = case datetime
58
+ when DateTimeType
59
+ datetime
60
+ when ZonedDateTime
61
+ DateTimeType.new(datetime)
62
+ else
63
+ raise "Unexpected type #{datetime.class} provided to DateTime initializer"
64
+ end
65
+ end
66
+
67
+ #
68
+ # Compare thes DateTime object to another
69
+ #
70
+ # @param [Object] other Other object to compare against
71
+ #
72
+ # @return [Integer] -1, 0 or 1 depending on the outcome
73
+ #
74
+ def <=>(other)
75
+ case other
76
+ when DateTime, DateTimeType, DateTimeItem
77
+ zoned_date_time.to_instant.compare_to(other.zoned_date_time.to_instant)
78
+ when TimeOfDay::TimeOfDay, TimeOfDay::TimeOfDayRangeElement
79
+ to_tod <=> other
80
+ when String
81
+ self <=> DateTime.parse(DATE_ONLY_REGEX =~ other ? "#{other}'T'00:00:00#{zone}" : other)
82
+ else
83
+ self <=> DateTime.from(other)
84
+ end
85
+ end
86
+
87
+ #
88
+ # Adds another object to this DateTime
89
+ #
90
+ # @param [Object] other Object to add to this. Can be a Numeric, another DateTime/Time/DateTimeType, a
91
+ # Duration or a String that can be parsed into a DateTimeType or Time object
92
+ #
93
+ # @return [DateTime] A new DateTime object representing the result of the calculation
94
+ #
95
+ def +(other)
96
+ logger.trace("Adding #{other} (#{other.class}) to #{self}")
97
+ case other
98
+ when Numeric then DateTime.from(to_time + other)
99
+ when DateTime, Time then self + other.to_f
100
+ when DateTimeType, String then self + DateTime.from(other).to_f
101
+ when Duration then DateTime.new(zoned_date_time.plus(other))
102
+ end
103
+ end
104
+
105
+ #
106
+ # Subtracts another object from this DateTime
107
+ #
108
+ # @param [Object] other Object to subtract fom this. Can be a Numeric, another DateTime/Time/DateTimeType, a
109
+ # Duration or a String that can be parsed into a DateTimeType or Time object
110
+ #
111
+ # @return [DateTime, Float] A new DateTime object representing the result of the calculation, or a Float
112
+ # representing the time difference in seconds if the subtraction is between two time objects
113
+ #
114
+ def -(other)
115
+ logger.trace("Subtracting #{other} (#{other.class}) from self")
116
+ case other
117
+ when Numeric then DateTime.from(to_time - other)
118
+ when String
119
+ dt = DateTime.parse(other)
120
+ TIME_ONLY_REGEX =~ other ? self - dt.to_f : time_diff(dt)
121
+ when Duration then DateTime.new(zoned_date_time.minus(other))
122
+ when Time, DateTime, DateTimeType, DateTimeItem then time_diff(other)
123
+ end
124
+ end
125
+
126
+ #
127
+ # Convert this DateTime to a ruby Time object
128
+ #
129
+ # @return [Time] A Time object representing the same instant and timezone
130
+ #
131
+ def to_time
132
+ Time.at(to_i, nsec, :nsec).localtime(utc_offset)
133
+ end
134
+
135
+ #
136
+ # Convert the time part of this DateTime to a TimeOfDay object
137
+ #
138
+ # @return [TimeOfDay] A TimeOfDay object representing the time
139
+ #
140
+ def to_time_of_day
141
+ TimeOfDay::TimeOfDay.new(h: hour, m: minute, s: second)
142
+ end
143
+
144
+ alias to_tod to_time_of_day
145
+
146
+ #
147
+ # Returns the value of time as a floating point number of seconds since the Epoch
148
+ #
149
+ # @return [Float] Number of seconds since the Epoch, with nanosecond presicion
150
+ #
151
+ def to_f
152
+ zoned_date_time.to_epoch_second + zoned_date_time.nano / 1_000_000_000
153
+ end
154
+
155
+ #
156
+ # The ZonedDateTime representing the state
157
+ #
158
+ # @return [Java::java::time::ZonedDateTime] ZonedDateTime representing the state
159
+ #
160
+ def zoned_date_time
161
+ @datetime.zonedDateTime
162
+ end
163
+
164
+ alias to_zdt zoned_date_time
165
+
166
+ #
167
+ # The offset in seconds from UTC
168
+ #
169
+ # @return [Integer] The offset from UTC, in seconds
170
+ #
171
+ def utc_offset
172
+ zoned_date_time.offset.total_seconds
173
+ end
174
+
175
+ #
176
+ # Returns true if time represents a time in UTC (GMT)
177
+ #
178
+ # @return [Boolean] true if utc_offset == 0, false otherwise
179
+ #
180
+ def utc?
181
+ utc_offset.zero?
182
+ end
183
+
184
+ #
185
+ # The timezone
186
+ #
187
+ # @return [String] The timezone in `[+-]hh:mm(:ss)` format ('Z' for UTC) or nil if the Item has no state
188
+ #
189
+ def zone
190
+ zoned_date_time.zone.id
191
+ end
192
+
193
+ #
194
+ # Check if missing method can be delegated to other contained objects
195
+ #
196
+ # @param [String, Symbol] meth the method name to check for
197
+ #
198
+ # @return [Boolean] true if DateTimeType, ZonedDateTime or Time responds to the method, false otherwise
199
+ #
200
+ def respond_to_missing?(meth, *)
201
+ @datetime.respond_to?(meth) ||
202
+ zoned_date_time.respond_to?(meth) ||
203
+ Time.instance_methods.include?(meth.to_sym)
204
+ end
205
+
206
+ #
207
+ # Forward missing methods to the OpenHAB DateTimeType, its ZonedDateTime object or a ruby Time
208
+ # object representing the same instant
209
+ #
210
+ # @param [String] meth method name
211
+ # @param [Array] args arguments for method
212
+ # @param [Proc] block <description>
213
+ #
214
+ # @return [Object] Value from delegated method in OpenHAB NumberItem
215
+ #
216
+ def method_missing(meth, *args, &block)
217
+ if @datetime.respond_to?(meth)
218
+ @datetime.__send__(meth, *args, &block)
219
+ elsif zoned_date_time.respond_to?(meth)
220
+ zoned_date_time.__send__(meth, *args, &block)
221
+ elsif Time.instance_methods.include?(meth.to_sym)
222
+ to_time.send(meth, *args, &block)
223
+ else
224
+ raise NoMethodError, "undefined method `#{meth}' for #{self.class}"
225
+ end
226
+ end
227
+
228
+ #
229
+ # Converts other objects to a DateTimeType
230
+ #
231
+ # @param [String, Numeric, Time] datetime an object that can be parsed or converted into
232
+ # a DateTimeType
233
+ #
234
+ # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
235
+ #
236
+ def self.from(datetime)
237
+ case datetime
238
+ when String
239
+ parse(datetime)
240
+ when Numeric
241
+ from_numeric(datetime)
242
+ when Time
243
+ from_time(datetime)
244
+ else
245
+ raise "Cannot convert #{datetime.class} to DateTime"
246
+ end
247
+ end
248
+
249
+ #
250
+ # Converts a Numeric into a DateTimeType
251
+ #
252
+ # @param [Numeric] numeric A Integer or Float representing the number of seconds since the epoch
253
+ #
254
+ # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
255
+ #
256
+ def self.from_numeric(numeric)
257
+ case numeric
258
+ when Integer
259
+ DateTime.new(ZonedDateTime.ofInstant(Instant.ofEpochSecond(datetime), ZoneId.systemDefault))
260
+ else
261
+ DateTime.new(ZonedDateTime.ofInstant(Instant.ofEpochSecond(datetime.to_i,
262
+ ((datetime % 1) * 1_000_000_000).to_i),
263
+ ZoneId.systemDefault))
264
+ end
265
+ end
266
+
267
+ #
268
+ # Converts a ruby Time object to an OpenHAB DateTimeType
269
+ #
270
+ # @param [Time] time The Time object to be converted
271
+ #
272
+ # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
273
+ #
274
+ def self.from_time(time)
275
+ instant = Instant.ofEpochSecond(time.to_i, time.nsec)
276
+ zone_id = ZoneId.of_offset('UTC', ZoneOffset.of_total_seconds(time.utc_offset))
277
+ DateTime.new(ZonedDateTime.ofInstant(instant, zone_id))
278
+ end
279
+
280
+ #
281
+ # Parses a string representing a time into an OpenHAB DateTimeType. First tries to parse it
282
+ # using the DateTimeType's parser, then falls back to the ruby Time.parse
283
+ #
284
+ # @param [String] time_string The string to be parsed
285
+ #
286
+ # @return [Java::org::openhab::core::library::types::DateTimeType] Object representing the same time
287
+ #
288
+ def self.parse(time_string)
289
+ time_string += 'Z' if TIME_ONLY_REGEX =~ time_string
290
+ DateTime.new(DateTimeType.new(time_string))
291
+ rescue Java::JavaLang::StringIndexOutOfBoundsException, Java::JavaLang::IllegalArgumentException
292
+ # Try ruby's Time.parse if OpenHAB's DateTimeType parser fails
293
+ begin
294
+ time = Time.parse(time_string)
295
+ DateTime.from(time)
296
+ rescue ArgumentError
297
+ raise "Unable to parse #{time_string} into a DateTime"
298
+ end
299
+ end
300
+
301
+ private
302
+
303
+ #
304
+ # Calculates the difference in time between this instance and another time object
305
+ #
306
+ # @param [Time, DateTime, DateTimeItem, Java::org::openhab::core::library::types::DateTimeType] time_obj
307
+ # The other time object to subtract from self
308
+ #
309
+ # @return [Float] The time difference between the two objects, in seconds
310
+ #
311
+ def time_diff(time_obj)
312
+ logger.trace("Calculate time difference between #{self} and #{time_obj}")
313
+ case time_obj
314
+ when Time
315
+ to_time - time_obj
316
+ when DateTime, DateTimeItem
317
+ self - time_obj.to_time
318
+ when DateTimeType
319
+ self - DateTime.new(time_obj).to_time
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+ # rubocop: enable Metrics/ClassLength
@@ -3,7 +3,7 @@
3
3
  require 'java'
4
4
 
5
5
  # Import Imperial and SI Units overriding provided values
6
- %i[ImperialUnits SIUnits].each do |type|
6
+ %i[Units ImperialUnits SIUnits].each do |type|
7
7
  Object.send(:remove_const, type)
8
8
  java_import "org.openhab.core.library.unit.#{type}"
9
9
  end
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '2.16.4'
8
+ VERSION = '2.19.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: 2.16.4
4
+ version: 2.19.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-02-12 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -39,8 +39,10 @@ files:
39
39
  - lib/openhab/dsl/dsl.rb
40
40
  - lib/openhab/dsl/gems.rb
41
41
  - lib/openhab/dsl/group.rb
42
+ - lib/openhab/dsl/items/datetime_item.rb
42
43
  - lib/openhab/dsl/items/items.rb
43
44
  - lib/openhab/dsl/items/number_item.rb
45
+ - lib/openhab/dsl/items/rollershutter_item.rb
44
46
  - lib/openhab/dsl/items/string_item.rb
45
47
  - lib/openhab/dsl/monkey_patch/actions/actions.rb
46
48
  - lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb
@@ -59,12 +61,14 @@ files:
59
61
  - lib/openhab/dsl/monkey_patch/ruby/range.rb
60
62
  - lib/openhab/dsl/monkey_patch/ruby/ruby.rb
61
63
  - lib/openhab/dsl/monkey_patch/ruby/string.rb
64
+ - lib/openhab/dsl/monkey_patch/ruby/time.rb
62
65
  - lib/openhab/dsl/monkey_patch/types/decimal_type.rb
63
66
  - lib/openhab/dsl/monkey_patch/types/on_off_type.rb
64
67
  - lib/openhab/dsl/monkey_patch/types/open_closed_type.rb
65
68
  - lib/openhab/dsl/monkey_patch/types/percent_type.rb
66
69
  - lib/openhab/dsl/monkey_patch/types/quantity_type.rb
67
70
  - lib/openhab/dsl/monkey_patch/types/types.rb
71
+ - lib/openhab/dsl/monkey_patch/types/up_down_type.rb
68
72
  - lib/openhab/dsl/persistence.rb
69
73
  - lib/openhab/dsl/rules/automation_rule.rb
70
74
  - lib/openhab/dsl/rules/guard.rb
@@ -81,6 +85,7 @@ files:
81
85
  - lib/openhab/dsl/things.rb
82
86
  - lib/openhab/dsl/time_of_day.rb
83
87
  - lib/openhab/dsl/timers.rb
88
+ - lib/openhab/dsl/types/datetime.rb
84
89
  - lib/openhab/dsl/types/quantity.rb
85
90
  - lib/openhab/dsl/units.rb
86
91
  - lib/openhab/log/configuration.rb