openhab-scripting 4.2.0 → 4.6.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: 4ebe32d36d3366345d28b81bc71d9cd315d1d84feb4a4f1745c882209b1fdbe2
4
- data.tar.gz: 95331e97286e86bc993eb979531c5e3f80bc203e752e97aa9f3a60698fd56274
3
+ metadata.gz: a9ccae52c29da91b7fadc2ac7ba2459e9870a257396849535458497ba48601e5
4
+ data.tar.gz: 0015aca73a5c79082adefb486afcbb545e324c0695d492e15397d2e0d691a204
5
5
  SHA512:
6
- metadata.gz: e406fa7d011a733376bb5977293f44d20b893f1f990486f342c541f8d287c453736b75007ba586bfc5e6801638ac71bc6d294ad1b4a436a83247bee157150eb0
7
- data.tar.gz: d4fad57e6ad4f71a969b8f8c6791c4240854a74800647a4bed770123221eb2491c251c2a28bcbcd1649225d348aadd91b0efc188adba16a56aa7115620224028
6
+ metadata.gz: 2db7c0a6f4182d3145871ab6936aa92d5acbe2a6d29e79f793a464d4fbb9514555021d9f0b103130ed99b04c9e149a414ea96df8f134f7db2fb71bade3824168
7
+ data.tar.gz: da447a4315a8d177db5fc6e476dd30ba93a071f06c6dc612a361f9d12a8539932f8a1659bdd919d8cdf61be2da759f720020d57fe399eaa1a2533bf5e1f56203
@@ -9,7 +9,6 @@ module OpenHAB
9
9
  # Module to import and streamline access to OpenHAB actions
10
10
  #
11
11
  module Actions
12
- java_import org.openhab.core.library.types.PercentType
13
12
  include OpenHAB::Log
14
13
 
15
14
  OpenHAB::Core::OSGI.services('org.openhab.core.model.script.engine.action.ActionService')&.each do |service|
@@ -83,7 +82,7 @@ module OpenHAB
83
82
  # @return [void]
84
83
  #
85
84
  def say(text, voice: nil, sink: nil, volume: nil)
86
- volume = PercentType.new(volume&.to_i) unless volume.is_a?(PercentType) || volume.nil?
85
+ volume = Types::PercentType.new(volume) unless volume.is_a?(Types::PercentType) || volume.nil?
87
86
  Voice.say text, voice, sink, volume
88
87
  end
89
88
 
@@ -97,7 +96,7 @@ module OpenHAB
97
96
  # @return [void]
98
97
  #
99
98
  def play_sound(filename, sink: nil, volume: nil)
100
- volume = PercentType.new(volume&.to_i) unless volume.is_a?(PercentType) || volume.nil?
99
+ volume = Types::PercentType.new(volume) unless volume.is_a?(Types::PercentType) || volume.nil?
101
100
  Audio.playSound sink, filename, volume
102
101
  end
103
102
  end
@@ -10,6 +10,7 @@ require 'openhab/dsl/monkey_patch/ruby/ruby'
10
10
  require 'openhab/dsl/monkey_patch/events/events'
11
11
  require 'openhab/dsl/monkey_patch/actions/actions'
12
12
  require 'openhab/dsl/rules/rule'
13
+ require 'openhab/dsl/rules/terse'
13
14
  require 'openhab/dsl/actions'
14
15
  require 'openhab/dsl/timers'
15
16
  require 'openhab/dsl/group'
@@ -34,6 +35,7 @@ module OpenHAB
34
35
  base.send :include, OpenHAB::DSL::Items
35
36
  base.send :include, OpenHAB::DSL::Persistence
36
37
  base.send :include, OpenHAB::DSL::Rules
38
+ base.send :include, OpenHAB::DSL::Rules::Terse
37
39
  base.send :include, OpenHAB::DSL::States
38
40
  base.send :include, OpenHAB::DSL::Things
39
41
  base.send :include, OpenHAB::DSL::Timers
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ require_relative 'comparable_item'
6
+ require 'openhab/dsl/types/hsb_type'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ java_import org.openhab.core.library.items.ColorItem
12
+
13
+ # Adds methods to core OpenHAB ColorItem type to make it more natural in
14
+ # Ruby
15
+ class ColorItem < DimmerItem
16
+ extend Forwardable
17
+ include ComparableItem
18
+
19
+ # !@visibility private
20
+ def ==(other)
21
+ # need to check if we're referring to the same item before
22
+ # forwarding to <=> (and thus checking equality with state)
23
+ return true if equal?(other) || eql?(other)
24
+
25
+ super
26
+ end
27
+
28
+ #
29
+ # Type Coercion
30
+ #
31
+ # Coerce object to a HSBType
32
+ #
33
+ # @param [Types::HSBType, String] other object to coerce to a
34
+ # HSBType
35
+ #
36
+ # @return [[Types::HSBType, Types::HSBType]]
37
+ #
38
+ def coerce(other)
39
+ logger.trace("Coercing #{self} as a request from #{other.class}")
40
+ return [other, nil] unless state?
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
+ end
45
+
46
+ # any method that exists on {Types::HSBType} gets forwarded to +state+
47
+ delegate (Types::HSBType.instance_methods - instance_methods) => :state
48
+
49
+ # string commands aren't allowed on ColorItems, so try to implicitly
50
+ # convert it to an HSBType
51
+ # @!visibility private
52
+ def format_type(command)
53
+ return Types::HSBType.new(command) if command.respond_to?(:to_str)
54
+
55
+ super
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'generic_item'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Items
8
+ # Functionality to implement +ensure+/+ensure_states+
9
+ module Ensure
10
+ # Contains the global +ensure_states+ method
11
+ module EnsureStates
12
+ # Global method that takes a block and for the duration of the block
13
+ # all commands sent will check if the item is in the command's state
14
+ # before sending the command.
15
+ #
16
+ # @example Turn on several switches only if they're not already on
17
+ # ensure_states do
18
+ # Switch1.on
19
+ # Switch2.on
20
+ # end
21
+ def ensure_states
22
+ old = Thread.current[:ensure_states]
23
+ Thread.current[:ensure_states] = true
24
+ yield
25
+ ensure
26
+ Thread.current[:ensure_states] = old
27
+ end
28
+ module_function :ensure_states
29
+ end
30
+
31
+ # Contains the +ensure+ method mixed into {GenericItem} and {GroupItem::GroupMembers}
32
+ module Ensurable
33
+ # Fluent method call that you can chain commands on to, that will
34
+ # then automatically ensure that the item is not in the command's
35
+ # state before sending the command.
36
+ #
37
+ # @example Turn switch on only if it's not on
38
+ # MySwitch.ensure.on
39
+ # @example Turn on all switches in a group that aren't already on
40
+ # MySwitchGroup.members.ensure.on
41
+ def ensure
42
+ GenericItemDelegate.new(self)
43
+ end
44
+ end
45
+
46
+ # Extensions for {Items::GenericItem} to implement {Ensure}'s
47
+ # functionality
48
+ module GenericItem
49
+ include Ensurable
50
+
51
+ # If +ensure_states+ is active (by block or chained method), then
52
+ # check if this item is in the command's state before actually
53
+ # sending the command
54
+ def command(command)
55
+ return super unless Thread.current[:ensure_states]
56
+ return if command == state
57
+
58
+ super
59
+ end
60
+ alias << command
61
+ end
62
+
63
+ # "anonymous" class that wraps any method call in +ensure_states+
64
+ # before forwarding to the wrapped object
65
+ # @!visibility private
66
+ class GenericItemDelegate
67
+ def initialize(item)
68
+ @item = item
69
+ end
70
+
71
+ # activate +ensure_states+ before forwarding to the wrapped object
72
+ def method_missing(method, *args, &block)
73
+ return super unless @item.respond_to?(method)
74
+
75
+ ensure_states do
76
+ @item.__send__(method, *args, &block)
77
+ end
78
+ end
79
+
80
+ # .
81
+ def respond_to_missing?(method, include_private = false)
82
+ @item.respond_to?(method, include_private) || super
83
+ end
84
+ end
85
+ end
86
+
87
+ GenericItem.prepend(Ensure::GenericItem)
88
+ GroupItem::GroupMembers.include(Ensure::Ensurable)
89
+ end
90
+ end
91
+ end
92
+
93
+ Object.include OpenHAB::DSL::Items::Ensure::EnsureStates
@@ -3,6 +3,8 @@
3
3
  require 'openhab/dsl/items/metadata'
4
4
  require 'openhab/dsl/items/persistence'
5
5
 
6
+ require_relative 'item_equality'
7
+
6
8
  module OpenHAB
7
9
  module DSL
8
10
  module Items
@@ -12,6 +14,8 @@ module OpenHAB
12
14
  # Ruby
13
15
  class GenericItem
14
16
  include Log
17
+ include ItemEquality
18
+
15
19
  prepend Metadata
16
20
  prepend Persistence
17
21
 
@@ -135,33 +139,6 @@ module OpenHAB
135
139
  other.instance_of?(self.class) && hash == other.hash
136
140
  end
137
141
 
138
- #
139
- # Check equality, with type conversions
140
- #
141
- # @param [GenericItem, Types::Type, Object] other object to
142
- # compare to
143
- #
144
- # If this item is +NULL+ or +UNDEF+, and +other+ is nil, they are
145
- # considered equal
146
- #
147
- # If this item is +NULL+ or +UNDEF+, and other is a {GenericItem}, they
148
- # are only considered equal if the other item is in the exact same
149
- # state (i.e. +NULL+ != +UNDEF+)
150
- #
151
- # Otherwise, the state of this item is compared with +other+
152
- #
153
- # @return [Boolean]
154
- #
155
- def ==(other)
156
- logger.trace("(#{self.class}) #{self} == #{other} (#{other.class})")
157
- return true if equal?(other) || eql?(other)
158
- return true if !state? && other.nil?
159
-
160
- return raw_state == other.raw_state if other.is_a?(GenericItem)
161
-
162
- state == other
163
- end
164
-
165
142
  # @!method null?
166
143
  # Check if the item state == +NULL+
167
144
  # @return [Boolean]
@@ -31,6 +31,74 @@ module OpenHAB
31
31
  def to_a
32
32
  group.get_members.to_a
33
33
  end
34
+
35
+ # Send a command to each member of the group
36
+ #
37
+ # @return [GroupMembers] +self+
38
+ def command(command)
39
+ each { |item| item << command }
40
+ end
41
+ alias << command
42
+
43
+ # @!method refresh
44
+ # Send the +REFRESH+ command to each member of the group
45
+ # @return [GroupMembers] +self+
46
+
47
+ # @!method on
48
+ # Send the +ON+ command to each member of the group
49
+ # @return [GroupMembers] +self+
50
+
51
+ # @!method off
52
+ # Send the +OFF+ command to each member of the group
53
+ # @return [GroupMembers] +self+
54
+
55
+ # @!method up
56
+ # Send the +UP+ command to each member of the group
57
+ # @return [GroupMembers] +self+
58
+
59
+ # @!method down
60
+ # Send the +DOWN+ command to each member of the group
61
+ # @return [GroupMembers] +self+
62
+
63
+ # @!method stop
64
+ # Send the +STOP+ command to each member of the group
65
+ # @return [GroupMembers] +self+
66
+
67
+ # @!method move
68
+ # Send the +MOVE+ command to each member of the group
69
+ # @return [GroupMembers] +self+
70
+
71
+ # @!method increase
72
+ # Send the +INCREASE+ command to each member of the group
73
+ # @return [GroupMembers] +self+
74
+
75
+ # @!method desrease
76
+ # Send the +DECREASE+ command to each member of the group
77
+ # @return [GroupMembers] +self+
78
+
79
+ # @!method play
80
+ # Send the +PLAY+ command to each member of the group
81
+ # @return [GroupMembers] +self+
82
+
83
+ # @!method pause
84
+ # Send the +PAUSE+ command to each member of the group
85
+ # @return [GroupMembers] +self+
86
+
87
+ # @!method rewind
88
+ # Send the +REWIND+ command to each member of the group
89
+ # @return [GroupMembers] +self+
90
+
91
+ # @!method fast_forward
92
+ # Send the +FASTFORWARD+ command to each member of the group
93
+ # @return [GroupMembers] +self+
94
+
95
+ # @!method next
96
+ # Send the +NEXT+ command to each member of the group
97
+ # @return [GroupMembers] +self+
98
+
99
+ # @!method previous
100
+ # Send the +PREVIOUS+ command to each member of the group
101
+ # @return [GroupMembers] +self+
34
102
  end
35
103
 
36
104
  include Enumerable
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Items
6
+ # Shared method for checking item equality by delegating to state
7
+ module ItemEquality
8
+ # Check equality, with type conversions
9
+ #
10
+ # @param [GenericItem, Types::Type, Object] other object to
11
+ # compare to
12
+ #
13
+ # If this item is +NULL+ or +UNDEF+, and +other+ is nil, they are
14
+ # considered equal
15
+ #
16
+ # If this item is +NULL+ or +UNDEF+, and other is a {GenericItem}, they
17
+ # are only considered equal if the other item is in the exact same
18
+ # state (i.e. +NULL+ != +UNDEF+)
19
+ #
20
+ # Otherwise, the state of this item is compared with +other+
21
+ #
22
+ # @return [Boolean]
23
+ #
24
+ def ==(other)
25
+ logger.trace("(#{self.class}) #{self} == #{other} (#{other.class})")
26
+ return true if equal?(other) || eql?(other)
27
+ return true if !state? && other.nil?
28
+
29
+ return raw_state == other.raw_state if other.is_a?(GenericItem)
30
+
31
+ state == other
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -10,14 +10,18 @@ require_relative 'switch_item'
10
10
  require_relative 'date_time_item'
11
11
  require_relative 'dimmer_item'
12
12
 
13
+ require_relative 'color_item'
13
14
  require_relative 'contact_item'
14
15
  require_relative 'group_item'
15
16
  require_relative 'image_item'
17
+ require_relative 'location_item'
16
18
  require_relative 'number_item'
17
19
  require_relative 'player_item'
18
20
  require_relative 'rollershutter_item'
19
21
  require_relative 'string_item'
20
22
 
23
+ require_relative 'ensure'
24
+
21
25
  module OpenHAB
22
26
  module DSL
23
27
  # Contains all OpenHAB *Item classes, as well as associated support
@@ -51,7 +55,7 @@ module OpenHAB
51
55
 
52
56
  # defined methods for commanding an item to one of the Enum states
53
57
  # as well as predicates for if an ItemCommandEvent is one of those commands
54
- def def_command_methods(klass) # rubocop:disable Metrics/MethodLength method has single purpose
58
+ def def_command_methods(klass) # rubocop:disable Metrics method has single purpose
55
59
  values_for_enums(klass.ACCEPTED_COMMAND_TYPES).each do |value|
56
60
  command = Types::COMMAND_ALIASES[value.to_s]
57
61
  next if klass.instance_methods.include?(command)
@@ -63,6 +67,13 @@ module OpenHAB
63
67
  end # end
64
68
  RUBY
65
69
 
70
+ OpenHAB::Core.logger.trace("Defining GroupItem::GroupMembers##{command} for #{value}")
71
+ GroupItem::GroupMembers.class_eval <<~RUBY, __FILE__, __LINE__ + 1
72
+ def #{command} # def on
73
+ each(&:#{command}) # each(&:on)
74
+ end # end
75
+ RUBY
76
+
66
77
  OpenHAB::Core.logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
67
78
  MonkeyPatch::Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
68
79
  def #{command}? # def refresh?
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ require_relative 'comparable_item'
6
+ require 'openhab/dsl/types/point_type'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ java_import org.openhab.core.library.items.LocationItem
12
+
13
+ # Adds methods to core OpenHAB NumberItem type to make it more natural in
14
+ # Ruby
15
+ class LocationItem < GenericItem
16
+ extend Forwardable
17
+ include ComparableItem
18
+
19
+ # !@visibility private
20
+ def ==(other)
21
+ # need to check if we're referring to the same item before
22
+ # forwarding to <=> (and thus checking equality with state)
23
+ return true if equal?(other) || eql?(other)
24
+
25
+ super
26
+ end
27
+
28
+ #
29
+ # Type Coercion
30
+ #
31
+ # Coerce object to a PointType
32
+ #
33
+ # @param [Types::PointType, String] other object to coerce to a
34
+ # PointType
35
+ #
36
+ # @return [[Types::PointType, Types::PointType]]
37
+ #
38
+ def coerce(other)
39
+ logger.trace("Coercing #{self} as a request from #{other.class}")
40
+ return [other, nil] unless state?
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
+ end
45
+
46
+ # OpenHAB has this method, but it _only_ accepts PointType, so remove it and delegate
47
+ remove_method :distance_from
48
+
49
+ # any method that exists on {Types::PointType} gets forwarded to +state+
50
+ delegate (Types::PointType.instance_methods - instance_methods) => :state
51
+ end
52
+ end
53
+ end
54
+ end
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'forwardable'
4
4
 
5
- require 'openhab/dsl/items/comparable_item'
5
+ require_relative 'comparable_item'
6
+ require_relative 'item_equality'
6
7
 
7
8
  module OpenHAB
8
9
  module DSL
@@ -15,6 +16,7 @@ module OpenHAB
15
16
 
16
17
  # apply meta-programming methods to including class
17
18
  def self.included(klass)
19
+ klass.prepend ItemEquality # make sure this is first
18
20
  klass.extend Forwardable
19
21
  klass.delegate %i[+ - * / % | positive? negative? to_d to_f to_i to_int zero?] => :state
20
22
  # remove the JRuby default == so that we can inherit the Ruby method
@@ -91,7 +91,7 @@ module OpenHAB
91
91
 
92
92
  return super unless other.is_a?(javax.measure.Unit)
93
93
 
94
- QuantityType.new(to_d.to_java, other)
94
+ Types::QuantityType.new(to_d.to_java, other)
95
95
  end
96
96
  end
97
97
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Rules
6
+ # Module containing terse rule stubs
7
+ module Terse
8
+ %i[changed channel cron every updated received_command].each do |trigger|
9
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
10
+ def #{trigger}(*args, name: nil, **kwargs, &block) # def changed(*args, name: nil, **kwargs, &block)
11
+ # if no name is given, just default to the name of the rules file # # if no name is given, just default to the name of the rules file
12
+ name ||= File.basename(caller_locations.last.path) # name ||= File.basename(caller_locations.last.path)
13
+ rule name do # rule name do
14
+ #{trigger}(*args, **kwargs) # changed(*args, **kwargs)
15
+ run(&block) # run(&block)
16
+ end # end
17
+ end # end
18
+ module_function #{trigger.inspect} # module_function :changed
19
+ RUBY
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'percent_type'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Types
8
+ java_import org.openhab.core.library.types.HSBType
9
+
10
+ # global alias
11
+ ::HSBType = HSBType
12
+
13
+ # Adds methods to core OpenHAB HSBType to make it more natural in Ruby
14
+ class HSBType < PercentType
15
+ # @!parse BLACK = BLACK # @return [HSBType]
16
+ # @!parse WHITE = WHITE # @return [HSBType]
17
+ # @!parse RED = RED # @return [HSBType]
18
+ # @!parse GREEN = GREEN # @return [HSBType]
19
+ # @!parse BLUE = BLUE # @return [HSBType]
20
+
21
+ # conversion to QuantityType doesn't make sense on HSBType
22
+ undef_method :|
23
+
24
+ remove_method :==
25
+
26
+ # r, g, b as an array of symbols
27
+ RGB_KEYS = %i[r g b].freeze
28
+ private_constant :RGB_KEYS
29
+
30
+ class << self
31
+ # @!method from_rgb(r, g, b)
32
+ # Create HSBType from RGB values
33
+ # @param r [Integer] Red component (0-255)
34
+ # @param g [Integer] Green component (0-255)
35
+ # @param b [Integer] Blue component (0-255)
36
+ # @return [HSBType]
37
+
38
+ # @!method from_xy(x, y)
39
+ # Create HSBType representing the provided xy color values in CIE XY color model
40
+ # @param x [Float]
41
+ # @param y [Float]
42
+ # @return [HSBType]
43
+
44
+ # Create HSBType from hue, saturation, and brightness values
45
+ # @param hue [DecimalType, QuantityType, Numeric] Hue component (0-360º)
46
+ # @param saturation [PercentType, Numeric] Saturation component (0-100%)
47
+ # @param brightness [PercentType, Numeric] Brightness component (0-100%)
48
+ # @return [HSBType]
49
+ def from_hsv(hue, saturation, brightness)
50
+ new(hue, saturation, brightness)
51
+ end
52
+
53
+ # add additional "overloads" to the constructor
54
+ # @!visibility private
55
+ def new(*args) # rubocop:disable Metrics
56
+ if args.length == 1 && args.first.respond_to?(:to_str)
57
+ value = args.first.to_str
58
+
59
+ # parse some formats OpenHAB doesn't understand
60
+ # in this case, HTML hex format for rgb
61
+ if (match = value.match(/^#(\h{2})(\h{2})(\h{2})$/))
62
+ rgb = match.to_a[1..3].map { |v| v.to_i(16) }
63
+ logger.trace("creating from rgb #{rgb.inspect}")
64
+ return from_rgb(*rgb)
65
+ end
66
+ end
67
+
68
+ return super unless args.length == 3
69
+
70
+ # convert from several numeric-like types to the exact types
71
+ # OpenHAB needs
72
+ hue = args[0]
73
+ args[0] = if hue.is_a?(DecimalType)
74
+ hue
75
+ elsif hue.is_a?(QuantityType)
76
+ DecimalType.new(hue.to_unit(::Units::DEGREE_ANGLE).to_big_decimal)
77
+ elsif hue.respond_to?(:to_d)
78
+ DecimalType.new(hue)
79
+ end
80
+ args[1..2] = args[1..2].map do |v|
81
+ if v.is_a?(PercentType)
82
+ v
83
+ elsif v.respond_to?(:to_d)
84
+ PercentType.new(v)
85
+ end
86
+ end
87
+
88
+ super(*args)
89
+ end
90
+ end
91
+
92
+ #
93
+ # Comparison
94
+ #
95
+ # @param [NumericType, Items::NumericItem, Items::ColorItem, Numeric, String]
96
+ # other object to compare to
97
+ #
98
+ # @return [Integer, nil] -1, 0, +1 depending on whether +other+ is
99
+ # less than, equal to, or greater than self
100
+ #
101
+ # nil is returned if the two values are incomparable
102
+ #
103
+ def <=>(other)
104
+ logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
105
+ if other.is_a?(Items::ColorItem) ||
106
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(ColorItem))
107
+ return false unless other.state?
108
+
109
+ self <=> other.state
110
+ elsif other.respond_to?(:to_str)
111
+ self <=> HSBType.new(other)
112
+ else
113
+ super
114
+ end
115
+ end
116
+
117
+ #
118
+ # Type Coercion
119
+ #
120
+ # Coerce object to a HSBType
121
+ #
122
+ # @param [NumericType, Items::NumericItem, Items::ColorItem, Numeric, String]
123
+ # other object to coerce to a HSBType
124
+ #
125
+ # @return [[HSBType, HSBType]]
126
+ #
127
+ def coerce(other)
128
+ logger.trace("Coercing #{self} as a request from #{other.class}")
129
+ if other.is_a?(Items::NumericItem) ||
130
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(Items::NumericItem))
131
+ raise TypeError, "can't convert #{UnDefType} into #{self.class}" unless other.state?
132
+
133
+ [other.state, self]
134
+ elsif other.respond_to?(:to_str)
135
+ [HSBType.new(other.to_str), self]
136
+ else
137
+ super
138
+ end
139
+ end
140
+
141
+ # rename raw methods so we can overwrite them
142
+ # @!visibility private
143
+ alias raw_hue hue
144
+
145
+ # @!attribute [r] hue
146
+ # @return [QuantityType]
147
+ def hue
148
+ QuantityType.new(raw_hue.to_big_decimal, ::Units::DEGREE_ANGLE)
149
+ end
150
+
151
+ # Convert to a packed 32-bit RGB value representing the color in the default sRGB color model.
152
+ #
153
+ # The alpha component is always 100%.
154
+ #
155
+ # @return [Integer]
156
+ alias argb rgb
157
+
158
+ # Convert to a packed 24-bit RGB value representing the color in the default sRGB color model.
159
+ # @return [Integer]
160
+ def rgb
161
+ argb & 0xffffff
162
+ end
163
+
164
+ # Convert to an HTML-style string of 6 hex characters in the default sRGB color model.
165
+ # @return [String] +'#xxxxxx'+
166
+ def to_hex
167
+ Kernel.format('#%06x', rgb)
168
+ end
169
+
170
+ # include units
171
+ # @!visibility private
172
+ def to_s
173
+ "#{hue},#{saturation},#{brightness}"
174
+ end
175
+
176
+ # @!attribute [r] saturation
177
+ # @return [PercentType]
178
+
179
+ # @!attribute [r] brightness
180
+ # @return [PercentType]
181
+
182
+ # @!attribute [r] red
183
+ # @return [PercentType]
184
+
185
+ # @!attribute [r] green
186
+ # @return [PercentType]
187
+
188
+ # @!attribute [r] blue
189
+ # @return [PercentType]
190
+
191
+ # @!method to_rgb
192
+ # Convert to RGB values representing the color in the default sRGB color model
193
+ # @return [[PercentType, PercentType, PercentType]]
194
+
195
+ # @!method to_xy
196
+ # Convert to the xyY values representing this object's color in CIE XY color model
197
+ # @return [[PercentType, PercentType]]
198
+ end
199
+ end
200
+ end
201
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'decimal_type'
4
+
3
5
  module OpenHAB
4
6
  module DSL
5
7
  module Types
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Types
6
+ java_import org.openhab.core.library.types.PointType
7
+
8
+ # global scope
9
+ # @!visibility private
10
+ ::PointType = PointType
11
+
12
+ # Adds methods to core OpenHAB PointType to make it more natural in Ruby
13
+ class PointType
14
+ # @!parse include PrimitiveType
15
+
16
+ # @param latitude [DecimalType, QuantityType, StringType, Numeric]
17
+ # @param longitude [DecimalType, QuantityType, StringType, Numeric]
18
+ # @param altitude [DecimalType, QuantityType, StringType, Numeric]
19
+ def initialize(*args) # rubocop:disable Metrics
20
+ if (2..3).cover?(args.length)
21
+ args = args.each_with_index.map do |value, index|
22
+ if value.is_a?(DecimalType) || value.is_a?(StringType)
23
+ value
24
+ elsif value.is_a?(QuantityType)
25
+ unit = index == 2 ? Units.unit || SIUnits::METRE : Units::DEGREE_ANGLE
26
+ DecimalType.new(value.to_unit(unit).to_big_decimal)
27
+ elsif value.respond_to?(:to_str)
28
+ StringType.new(value.to_str)
29
+ elsif value.respond_to?(:to_d)
30
+ DecimalType.new(value)
31
+ end
32
+ end
33
+ end
34
+
35
+ super(*args)
36
+ end
37
+
38
+ #
39
+ # Check equality without type conversion
40
+ #
41
+ # @return [Boolean] if the same value is represented, without type
42
+ # conversion
43
+ def eql?(other)
44
+ return false unless other.instance_of?(self.class)
45
+
46
+ equals(other.to_s).zero?
47
+ end
48
+
49
+ #
50
+ # Check equality with type conversion
51
+ #
52
+ # @param [PointType, Items::LocationItem, String]
53
+ # other object to compare to
54
+ #
55
+ # @return [Boolean]
56
+ #
57
+ def ==(other) # rubocop:disable Metrics
58
+ logger.trace("(#{self.class}) #{self} == #{other} (#{other.class})")
59
+ if other.is_a?(Items::LocationItem) ||
60
+ (other.is_a?(Items::GroupItem) && other.base_item.is_a?(LocationItem))
61
+ return false unless other.state?
62
+
63
+ self == other.state
64
+ elsif other.respond_to?(:to_str)
65
+ self == PointType.new(other)
66
+ elsif other.respond_to?(:coerce)
67
+ lhs, rhs = other.coerce(self)
68
+ lhs == rhs
69
+ end
70
+ end
71
+
72
+ #
73
+ # Type Coercion
74
+ #
75
+ # Coerce object to a PointType
76
+ #
77
+ # @param [Items::LocationItem, String] other object to coerce to a
78
+ # PointType
79
+ #
80
+ # @return [[PointType, PointType]]
81
+ #
82
+ def coerce(other)
83
+ [coerce_single(other), self]
84
+ end
85
+
86
+ # rename raw methods so we can overwrite them
87
+ # @!visibility private
88
+ alias raw_latitude latitude
89
+ # .
90
+ # @!visibility private
91
+ alias raw_longitude longitude
92
+ # .
93
+ # @!visibility private
94
+ alias raw_altitude altitude
95
+ # .
96
+ # @!visibility private
97
+ alias raw_distance_from distance_from
98
+
99
+ # @!attribute [r] latitude
100
+ # @return [QuantityType]
101
+ def latitude
102
+ QuantityType.new(raw_latitude.to_big_decimal, SIUnits::DEGREE_ANGLE)
103
+ end
104
+
105
+ # @!attribute [r] longitude
106
+ # @return [QuantityType]
107
+ def longitude
108
+ QuantityType.new(raw_longitude.to_big_decimal, SIUnits::DEGREE_ANGLE)
109
+ end
110
+
111
+ # @!attribute [r] altitude
112
+ # @return [QuantityType]
113
+ def altitude
114
+ QuantityType.new(raw_altitude.to_big_decimal, Units::METRE)
115
+ end
116
+
117
+ #
118
+ # Calculate the distance in meters from other, ignoring altitude.
119
+ #
120
+ # This algorithm also ignores the oblate spheroid shape of Earth and
121
+ # assumes a perfect sphere, so results are inexact.
122
+ #
123
+ # @return [QuantityType]
124
+ def distance_from(other)
125
+ logger.trace("(#{self}).distance_from(#{other} (#{other.class})")
126
+ QuantityType.new(raw_distance_from(coerce_single(other)), SIUnits::METRE)
127
+ end
128
+ alias - distance_from
129
+
130
+ private
131
+
132
+ # coerce an object to a PointType
133
+ # @return [PointType]
134
+ def coerce_single(other) # rubocop:disable Metrics/MethodLength
135
+ logger.trace("Coercing #{self} as a request from #{other.class}")
136
+ if other.is_a?(PointType)
137
+ other
138
+ elsif other.is_a?(Items::LocationItem)
139
+ raise TypeError, "can't convert #{other.raw_state} into #{self.class}" unless other.state?
140
+
141
+ other.state
142
+ elsif other.respond_to?(:to_str)
143
+ PointType.new(other.to_str)
144
+ else
145
+ raise TypeError, "can't convert #{other.class} into #{self.class}"
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -4,12 +4,14 @@ require_relative 'type'
4
4
 
5
5
  require_relative 'date_time_type'
6
6
  require_relative 'decimal_type'
7
+ require_relative 'hsb_type'
7
8
  require_relative 'increase_decrease_type'
8
9
  require_relative 'next_previous_type'
9
10
  require_relative 'open_closed_type'
10
11
  require_relative 'on_off_type'
11
12
  require_relative 'percent_type'
12
13
  require_relative 'play_pause_type'
14
+ require_relative 'point_type'
13
15
  require_relative 'quantity_type'
14
16
  require_relative 'refresh_type'
15
17
  require_relative 'rewind_fastforward_type'
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.2.0'
8
+ VERSION = '4.6.0'
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.6.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-10-18 00:00:00.000000000 Z
11
+ date: 2021-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -54,15 +54,19 @@ files:
54
54
  - lib/openhab/dsl/dsl.rb
55
55
  - lib/openhab/dsl/gems.rb
56
56
  - lib/openhab/dsl/group.rb
57
+ - lib/openhab/dsl/items/color_item.rb
57
58
  - lib/openhab/dsl/items/comparable_item.rb
58
59
  - lib/openhab/dsl/items/contact_item.rb
59
60
  - lib/openhab/dsl/items/date_time_item.rb
60
61
  - lib/openhab/dsl/items/dimmer_item.rb
62
+ - lib/openhab/dsl/items/ensure.rb
61
63
  - lib/openhab/dsl/items/generic_item.rb
62
64
  - lib/openhab/dsl/items/group_item.rb
63
65
  - lib/openhab/dsl/items/image_item.rb
66
+ - lib/openhab/dsl/items/item_equality.rb
64
67
  - lib/openhab/dsl/items/item_registry.rb
65
68
  - lib/openhab/dsl/items/items.rb
69
+ - lib/openhab/dsl/items/location_item.rb
66
70
  - lib/openhab/dsl/items/metadata.rb
67
71
  - lib/openhab/dsl/items/number_item.rb
68
72
  - lib/openhab/dsl/items/numeric_item.rb
@@ -89,6 +93,7 @@ files:
89
93
  - lib/openhab/dsl/rules/property.rb
90
94
  - lib/openhab/dsl/rules/rule.rb
91
95
  - lib/openhab/dsl/rules/rule_config.rb
96
+ - lib/openhab/dsl/rules/terse.rb
92
97
  - lib/openhab/dsl/rules/triggers/changed.rb
93
98
  - lib/openhab/dsl/rules/triggers/channel.rb
94
99
  - lib/openhab/dsl/rules/triggers/command.rb
@@ -102,6 +107,7 @@ files:
102
107
  - lib/openhab/dsl/types/comparable_type.rb
103
108
  - lib/openhab/dsl/types/date_time_type.rb
104
109
  - lib/openhab/dsl/types/decimal_type.rb
110
+ - lib/openhab/dsl/types/hsb_type.rb
105
111
  - lib/openhab/dsl/types/increase_decrease_type.rb
106
112
  - lib/openhab/dsl/types/next_previous_type.rb
107
113
  - lib/openhab/dsl/types/numeric_type.rb
@@ -109,6 +115,7 @@ files:
109
115
  - lib/openhab/dsl/types/open_closed_type.rb
110
116
  - lib/openhab/dsl/types/percent_type.rb
111
117
  - lib/openhab/dsl/types/play_pause_type.rb
118
+ - lib/openhab/dsl/types/point_type.rb
112
119
  - lib/openhab/dsl/types/quantity_type.rb
113
120
  - lib/openhab/dsl/types/refresh_type.rb
114
121
  - lib/openhab/dsl/types/rewind_fastforward_type.rb