openhab-scripting 4.1.4 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/entity_lookup.rb +1 -57
  3. data/lib/openhab/dsl/actions.rb +2 -3
  4. data/lib/openhab/dsl/dsl.rb +8 -12
  5. data/lib/openhab/dsl/group.rb +1 -5
  6. data/lib/openhab/dsl/items/color_item.rb +60 -0
  7. data/lib/openhab/dsl/items/comparable_item.rb +49 -0
  8. data/lib/openhab/dsl/items/contact_item.rb +41 -0
  9. data/lib/openhab/dsl/items/date_time_item.rb +64 -0
  10. data/lib/openhab/dsl/items/dimmer_item.rb +59 -0
  11. data/lib/openhab/dsl/items/ensure.rb +93 -0
  12. data/lib/openhab/dsl/items/generic_item.rb +174 -0
  13. data/lib/openhab/dsl/items/group_item.rb +121 -89
  14. data/lib/openhab/dsl/items/image_item.rb +5 -41
  15. data/lib/openhab/dsl/items/item_equality.rb +36 -0
  16. data/lib/openhab/dsl/items/item_registry.rb +49 -0
  17. data/lib/openhab/dsl/items/items.rb +81 -35
  18. data/lib/openhab/dsl/items/metadata.rb +325 -0
  19. data/lib/openhab/dsl/items/number_item.rb +6 -312
  20. data/lib/openhab/dsl/items/numeric_item.rb +68 -0
  21. data/lib/openhab/dsl/items/persistence.rb +122 -0
  22. data/lib/openhab/dsl/items/player_item.rb +49 -40
  23. data/lib/openhab/dsl/items/rollershutter_item.rb +25 -77
  24. data/lib/openhab/dsl/items/string_item.rb +16 -58
  25. data/lib/openhab/dsl/items/switch_item.rb +62 -0
  26. data/lib/openhab/dsl/lazy_array.rb +8 -6
  27. data/lib/openhab/dsl/monkey_patch/events/events.rb +2 -2
  28. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +67 -24
  29. data/lib/openhab/dsl/monkey_patch/events/item_event.rb +5 -5
  30. data/lib/openhab/dsl/monkey_patch/events/item_state.rb +10 -11
  31. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +10 -11
  32. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +25 -2
  33. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -3
  34. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +24 -24
  35. data/lib/openhab/dsl/rules/terse.rb +24 -0
  36. data/lib/openhab/dsl/states.rb +1 -1
  37. data/lib/openhab/dsl/time_of_day.rb +3 -5
  38. data/lib/openhab/dsl/types/comparable_type.rb +21 -0
  39. data/lib/openhab/dsl/types/date_time_type.rb +334 -0
  40. data/lib/openhab/dsl/types/decimal_type.rb +187 -0
  41. data/lib/openhab/dsl/types/hsb_type.rb +201 -0
  42. data/lib/openhab/dsl/types/increase_decrease_type.rb +23 -0
  43. data/lib/openhab/dsl/types/next_previous_type.rb +23 -0
  44. data/lib/openhab/dsl/types/numeric_type.rb +39 -0
  45. data/lib/openhab/dsl/types/on_off_type.rb +29 -0
  46. data/lib/openhab/dsl/types/open_closed_type.rb +29 -0
  47. data/lib/openhab/dsl/types/percent_type.rb +70 -0
  48. data/lib/openhab/dsl/types/play_pause_type.rb +27 -0
  49. data/lib/openhab/dsl/types/quantity_type.rb +275 -0
  50. data/lib/openhab/dsl/types/refresh_type.rb +18 -0
  51. data/lib/openhab/dsl/types/rewind_fastforward_type.rb +33 -0
  52. data/lib/openhab/dsl/types/stop_move_type.rb +23 -0
  53. data/lib/openhab/dsl/types/string_type.rb +88 -0
  54. data/lib/openhab/dsl/types/type.rb +72 -0
  55. data/lib/openhab/dsl/types/types.rb +78 -0
  56. data/lib/openhab/dsl/types/un_def_type.rb +22 -0
  57. data/lib/openhab/dsl/types/up_down_type.rb +32 -0
  58. data/lib/openhab/dsl/units.rb +11 -6
  59. data/lib/openhab/version.rb +1 -1
  60. data/lib/openhab.rb +0 -1
  61. metadata +36 -28
  62. data/lib/openhab/dsl/items/datetime_item.rb +0 -75
  63. data/lib/openhab/dsl/items/item_command.rb +0 -90
  64. data/lib/openhab/dsl/items/item_delegate.rb +0 -125
  65. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +0 -51
  66. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +0 -140
  67. data/lib/openhab/dsl/monkey_patch/items/items.rb +0 -142
  68. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +0 -328
  69. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +0 -123
  70. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +0 -71
  71. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +0 -47
  72. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -32
  73. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +0 -97
  74. data/lib/openhab/dsl/monkey_patch/types/increase_decrease_type.rb +0 -23
  75. data/lib/openhab/dsl/monkey_patch/types/next_previous_type.rb +0 -23
  76. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +0 -79
  77. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +0 -71
  78. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +0 -77
  79. data/lib/openhab/dsl/monkey_patch/types/play_pause_type.rb +0 -23
  80. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +0 -69
  81. data/lib/openhab/dsl/monkey_patch/types/refresh_type.rb +0 -23
  82. data/lib/openhab/dsl/monkey_patch/types/rewind_fastforward_type.rb +0 -23
  83. data/lib/openhab/dsl/monkey_patch/types/stop_move_type.rb +0 -23
  84. data/lib/openhab/dsl/monkey_patch/types/types.rb +0 -15
  85. data/lib/openhab/dsl/monkey_patch/types/up_down_type.rb +0 -72
  86. data/lib/openhab/dsl/types/datetime.rb +0 -338
  87. data/lib/openhab/dsl/types/quantity.rb +0 -300
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f3ac7afca9a32afdb3e8f52bf8b522919d0b6750a537f4e68808fd7d08eb57b
4
- data.tar.gz: e45f368adf72623ea4a9652d9e88b2af06afd9bfc146ae8e308600513be36607
3
+ metadata.gz: 13732b675b80ad3a92e2346e56da3e7d63b6a4845f8409c5a545d1b5006ab999
4
+ data.tar.gz: a5b9d54c25a47857256805d849344cfde4602ad23408228cc595bfc574a04587
5
5
  SHA512:
6
- metadata.gz: 784d720a2b034f87f4d811c504ddf2718bf9340540f1f347e0d5de957a133be542b9dcc072df508662a280978e8e21ee3c188504d7b6ed63ea5a78cef2dc4080
7
- data.tar.gz: bb1a34c08c83a46064d529be1ee3082147c441bc1fbe69f0fa3fff7536733fe26ec471d9912b88ba39cd22837649bf81516d95a12b70e59dab59e1592c66668b
6
+ metadata.gz: 9d8715ab0e0e84315b02a67aeb28f47ebcddb8b58ea5ea1043b53ef329f5f5017329fdae23961530cd1f0ac184e38acf8ad11fd9b1a7a41f77f486cf3d53f01c
7
+ data.tar.gz: 15a9babdc9a9d7179dda57fcad46356175c25933f534cc4ed1dad9566a56bdde08677b6ef0224c2761fdeb1dd9253f4d6a50cec5a5804bd703b6c843e438a66b
@@ -3,13 +3,6 @@
3
3
  require 'pp'
4
4
  require 'java'
5
5
  require 'set'
6
- require 'openhab/dsl/group'
7
- require 'openhab/log/logger'
8
- require 'openhab/dsl/items/number_item'
9
- require 'openhab/dsl/items/string_item'
10
- require 'openhab/dsl/items/datetime_item'
11
- require 'openhab/dsl/items/rollershutter_item'
12
- require 'openhab/dsl/items/group_item'
13
6
 
14
7
  # Automation lookup and injection of OpenHab entities
15
8
 
@@ -68,52 +61,6 @@ module OpenHAB
68
61
  lookup_item(name) || lookup_thing(name)
69
62
  end
70
63
 
71
- #
72
- # Decorate items with Ruby wrappers
73
- #
74
- # @param [Array] items Array of items to decorate
75
- #
76
- # @return [Array] Array of decorated items
77
- #
78
- def self.decorate_items(*items)
79
- items.flatten.map { |item| decorate_item(item) }
80
- end
81
-
82
- #
83
- # Decorate item with Ruby wrappers
84
- #
85
- # @param [Object] item the item object to decorate
86
- #
87
- # @return [Object] the ruby wrapper for the item
88
- #
89
- # rubocop: disable Metrics/MethodLength
90
- # rubocop: disable Metrics/CyclomaticComplexity
91
- # Disabled line length and branch size - case dispatch pattern
92
- def self.decorate_item(item)
93
- logger.trace("Decorating #{item.class}")
94
- case item
95
- when Java::OrgOpenhabCoreItems::GroupItem
96
- OpenHAB::DSL::Items::GroupItem.new(item)
97
- when Java::OrgOpenhabCoreLibraryItems::NumberItem
98
- OpenHAB::DSL::Items::NumberItem.new(item)
99
- when Java::OrgOpenhabCoreLibraryItems::StringItem
100
- OpenHAB::DSL::Items::StringItem.new(item)
101
- when Java::OrgOpenhabCoreLibraryItems::DateTimeItem
102
- OpenHAB::DSL::Items::DateTimeItem.new(item)
103
- when Java::OrgOpenhabCoreLibraryItems::RollershutterItem
104
- OpenHAB::DSL::Items::RollershutterItem.new(item)
105
- when Java::OrgOpenhabCoreLibraryItems::PlayerItem
106
- OpenHAB::DSL::Items::PlayerItem.new(item)
107
- when Java::OrgOpenhabCoreLibraryItems::ImageItem
108
- OpenHAB::DSL::Items::ImageItem.new(item)
109
- else
110
- logger.trace("Returning undecorated item #{item.class}")
111
- item
112
- end
113
- end
114
- # rubocop: enable Metrics/MethodLength
115
- # rubocop: enable Metrics/CyclomaticComplexity
116
-
117
64
  #
118
65
  # Looks up a Thing in the OpenHAB registry replacing '_' with ':'
119
66
  #
@@ -145,10 +92,7 @@ module OpenHAB
145
92
  def self.lookup_item(name)
146
93
  logger.trace("Looking up item(#{name})")
147
94
  name = name.to_s if name.is_a? Symbol
148
- # rubocop: disable Style/GlobalVars
149
- item = $ir.get(name)
150
- # rubocop: enable Style/GlobalVars
151
- decorate_item(item)
95
+ $ir.get(name) # rubocop: disable Style/GlobalVars
152
96
  end
153
97
  end
154
98
  end
@@ -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
@@ -1,29 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'java'
4
3
  require 'openhab/log/logger'
5
- require 'openhab/dsl/monkey_patch/events/events'
4
+
5
+ # the order of these is important
6
+ require 'openhab/dsl/types/types'
7
+ require 'openhab/dsl/items/items'
6
8
  require 'openhab/dsl/monkey_patch/ruby/ruby'
7
- require 'openhab/dsl/monkey_patch/items/items'
8
- require 'openhab/dsl/monkey_patch/types/types'
9
+
10
+ require 'openhab/dsl/monkey_patch/events/events'
9
11
  require 'openhab/dsl/monkey_patch/actions/actions'
10
12
  require 'openhab/dsl/rules/rule'
13
+ require 'openhab/dsl/rules/terse'
11
14
  require 'openhab/dsl/actions'
12
15
  require 'openhab/dsl/timers'
13
16
  require 'openhab/dsl/group'
14
17
  require 'openhab/dsl/things'
15
- require 'openhab/dsl/items/items'
16
- require 'openhab/dsl/items/datetime_item'
17
- require 'openhab/dsl/items/image_item'
18
- require 'openhab/dsl/items/number_item'
19
- require 'openhab/dsl/items/player_item'
20
- require 'openhab/dsl/items/group_item'
21
18
  require 'openhab/dsl/time_of_day'
22
19
  require 'openhab/dsl/gems'
23
20
  require 'openhab/dsl/persistence'
24
21
  require 'openhab/dsl/units'
25
- require 'openhab/dsl/types/datetime'
26
- require 'openhab/dsl/types/quantity'
27
22
  require 'openhab/dsl/states'
28
23
 
29
24
  module OpenHAB
@@ -40,6 +35,7 @@ module OpenHAB
40
35
  base.send :include, OpenHAB::DSL::Items
41
36
  base.send :include, OpenHAB::DSL::Persistence
42
37
  base.send :include, OpenHAB::DSL::Rules
38
+ base.send :include, OpenHAB::DSL::Rules::Terse
43
39
  base.send :include, OpenHAB::DSL::States
44
40
  base.send :include, OpenHAB::DSL::Things
45
41
  base.send :include, OpenHAB::DSL::Timers
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'java'
4
3
  require 'singleton'
5
4
 
6
- require 'openhab/core/entity_lookup'
7
- require 'openhab/dsl/items/group_item'
8
5
  require 'openhab/dsl/lazy_array'
9
6
 
10
7
  module OpenHAB
@@ -35,8 +32,7 @@ module OpenHAB
35
32
 
36
33
  # explicit conversion to array
37
34
  def to_a
38
- items = $ir.items.grep(org.openhab.core.items.GroupItem) # rubocop:disable Style/GlobalVars
39
- Core::EntityLookup.decorate_items(items)
35
+ $ir.items.grep(org.openhab.core.items.GroupItem) # rubocop:disable Style/GlobalVars
40
36
  end
41
37
  end
42
38
 
@@ -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,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ module Items
6
+ # Mixin for implementing the comparison operator for Item types that
7
+ # support it
8
+ module ComparableItem
9
+ #
10
+ # Comparison
11
+ #
12
+ # @param [GenericItem, Types::Type, Object] other object to
13
+ # compare to
14
+ #
15
+ # If this item is +NULL+ or +UNDEF+, and +other+ is nil, they are
16
+ # considered equal
17
+ #
18
+ # If this item is +NULL+ or +UNDEF+, and other is a {GenericItem}, they
19
+ # are only considered equal if the other item is in the exact same
20
+ # state (i.e. +NULL+ != +UNDEF+)
21
+ #
22
+ # Otherwise, the state of this item is compared with +other+
23
+ #
24
+ # @return [Integer, nil] -1, 0, +1 depending on whether +other+ is
25
+ # less than, equal to, or greater than self
26
+ #
27
+ # nil is returned if the two values are incomparable
28
+ #
29
+ def <=>(other)
30
+ logger.trace("(#{self.class}) #{self} <=> #{other} (#{other.class})")
31
+ # if we're NULL or UNDEF, implement special logic
32
+ unless state?
33
+ # if comparing to nil, consider ourselves equal
34
+ return 0 if other.nil?
35
+ # if the other object is an Item, only consider equal if we're
36
+ # in the same _kind_ of UnDefType state
37
+ return raw_state == other.raw_state if other.is_a?(GenericItem) && !other.state?
38
+
39
+ # otherwise, it's a non-nil thing comparing to nil, which is undefined
40
+ return nil
41
+ end
42
+
43
+ # delegate to how the state compares to the other object
44
+ state <=> other
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module DSL
5
+ #
6
+ # Patches OpenHAB items
7
+ #
8
+ module Items
9
+ java_import org.openhab.core.library.items.ContactItem
10
+
11
+ # Alias class for ContactItem
12
+ ::Contact = ContactItem
13
+
14
+ # Adds methods to core OpenHAB ContactItem type to make it more natural
15
+ # in Ruby
16
+ class ContactItem < GenericItem
17
+ remove_method :==
18
+
19
+ #
20
+ # Return the inverted state of the contact: +CLOSED+ if the contact is
21
+ # +OPEN+, +UNDEF+ or +NULL+; +OPEN+ if the contact is +CLOSED+
22
+ #
23
+ # @return [Types::OpenClosedType] Inverted state
24
+ #
25
+ def !
26
+ return !state if state?
27
+
28
+ CLOSED
29
+ end
30
+
31
+ # @!method open?
32
+ # Check if the item state == +OPEN+
33
+ # @return [Boolean]
34
+
35
+ # @!method closed?
36
+ # Check if the item state == +CLOSED+
37
+ # @return [Boolean]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'time'
5
+
6
+ require 'openhab/dsl/items/comparable_item'
7
+
8
+ module OpenHAB
9
+ module DSL
10
+ module Items
11
+ java_import org.openhab.core.library.items.DateTimeItem
12
+
13
+ # Adds methods to core OpenHAB DateTimeItem type to make it more natural
14
+ # in Ruby
15
+ class DateTimeItem < GenericItem
16
+ extend Forwardable
17
+ include Comparable
18
+ include ComparableItem
19
+
20
+ # !@visibility private
21
+ def ==(other)
22
+ # need to check if we're referring to the same item before
23
+ # forwarding to <=> (and thus checking equality with state)
24
+ return true if equal?(other) || eql?(other)
25
+
26
+ super
27
+ end
28
+
29
+ #
30
+ # Type Coercion
31
+ #
32
+ # Coerce object to a DateTimeType
33
+ #
34
+ # @param [Types::DateTimeType, Time] other object to coerce to a
35
+ # DateTimeType
36
+ #
37
+ # @return [[Types::DateTimeType, Types::DateTimeType]]
38
+ #
39
+ def coerce(other)
40
+ logger.trace("Coercing #{self} as a request from #{other.class}")
41
+ return [other, nil] unless state?
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
+ end
46
+
47
+ # any method that exists on DateTimeType, Java's ZonedDateTime, or
48
+ # Ruby's Time class gets forwarded to state (which will forward as
49
+ # necessary)
50
+ delegate ((Types::DateTimeType.instance_methods +
51
+ java.time.ZonedDateTime.instance_methods +
52
+ Time.instance_methods) - instance_methods) => :state
53
+
54
+ # Time types need formatted as ISO8601
55
+ # @!visibility private
56
+ def format_type(command)
57
+ return command.iso8601 if command.respond_to?(:iso8601)
58
+
59
+ super
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openhab/dsl/time_of_day'
4
+
5
+ require_relative 'numeric_item'
6
+
7
+ module OpenHAB
8
+ module DSL
9
+ #
10
+ # Patches OpenHAB items
11
+ #
12
+ module Items
13
+ java_import org.openhab.core.library.items.DimmerItem
14
+
15
+ # Alias class
16
+ ::Dimmer = DimmerItem
17
+
18
+ # Adds methods to core OpenHAB DimmerItem type to make it more natural in
19
+ # Ruby
20
+ class DimmerItem < SwitchItem
21
+ include NumericItem
22
+
23
+ #
24
+ # Dim the dimmer
25
+ #
26
+ # @param [Integer] amount to dim by
27
+ #
28
+ # @return [Integer] level target for dimmer
29
+ #
30
+ def dim(amount = 1)
31
+ target = [state&.-(amount), 0].compact.max
32
+ command(target)
33
+ target
34
+ end
35
+
36
+ #
37
+ # Brighten the dimmer
38
+ #
39
+ # @param [Integer] amount to brighten by
40
+ #
41
+ # @return [Integer] level target for dimmer
42
+ #
43
+ def brighten(amount = 1)
44
+ target = [state&.+(amount), 100].compact.min
45
+ command(target)
46
+ target
47
+ end
48
+
49
+ # @!method increase
50
+ # Send the +INCREASE+ command to the item
51
+ # @return [DimmerItem] +self+
52
+
53
+ # @!method decrease
54
+ # Send the +DECREASE+ command to the item
55
+ # @return [DimmerItem] +self+
56
+ end
57
+ end
58
+ end
59
+ 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