openhab-scripting 4.37.1 → 4.39.1

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: e405e19fe5977dfbe708699abaf9fe3e0e953d2d16450da5b10879b6e0d3494b
4
- data.tar.gz: c1ed131f668cd5e214f56164ff10a3e9938df4aaa5f6a55efde4ba23db164f82
3
+ metadata.gz: 3ec5b89b1270a09daed465179e9643c559c51491d030f5b6b53431f942d026fb
4
+ data.tar.gz: 292889a440bfc0f08d091fe5eb31894ca78654cabd5d9684d8b803d2840dd75d
5
5
  SHA512:
6
- metadata.gz: d970bd8b607aad49f59d0746ba56711dcf34a0c199547b76008e3e7f375b6836d06841c8cbdb86f056c4f58704690950583f20b76ae1e641515ea332f594f710
7
- data.tar.gz: 7cbc491b62553a735e02f25f690a1244801fc2eac7d2a179dd1777d608a34752e5b549ecb41b73df6765c83ef717fe40d030414bb41291d1372872acaa89c9bb
6
+ metadata.gz: 30e263e6eec5bf3f0258b198817d68f5ca6d31fbca7bb7ac0187601cbd07a91122daa52991e61615003db5a6e308574136d1b1045ad288329539be3e30b0ff28
7
+ data.tar.gz: 0e00529a2b6cc75a4e33a44d97623abf2144e38e637d7a3d70bd6a68f8acd19cf7de18811d8306ee9e35effd3756ae4eb53c032106e68d47e122231bb9cc590f
@@ -73,6 +73,13 @@ module OpenHAB
73
73
  @item = item
74
74
  end
75
75
 
76
+ # @!visibility private
77
+ # this is explicitly defined, instead of aliased, because #command
78
+ # doesn't actually exist as a method, and will go through method_missing
79
+ def <<(command)
80
+ command(command)
81
+ end
82
+
76
83
  # activate +ensure_states+ before forwarding to the wrapped object
77
84
  def method_missing(method, *args, &block)
78
85
  return super unless @item.respond_to?(method)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'openhab/dsl/items/metadata'
4
4
  require 'openhab/dsl/items/persistence'
5
+ require 'openhab/dsl/items/semantics'
5
6
 
6
7
  require_relative 'item_equality'
7
8
 
@@ -10,14 +11,17 @@ module OpenHAB
10
11
  module Items
11
12
  java_import org.openhab.core.items.GenericItem
12
13
 
13
- # Adds methods to core OpenHAB DimmerItem type to make it more natural in
14
+ # Adds methods to core OpenHAB GenericItem type to make it more natural in
14
15
  # Ruby
16
+ #
17
+ # @see https://www.openhab.org/javadoc/latest/org/openhab/core/items/genericitem
15
18
  class GenericItem
16
19
  include Log
17
20
  include ItemEquality
18
21
 
19
22
  prepend Metadata
20
23
  prepend Persistence
24
+ include Semantics
21
25
 
22
26
  # rubocop:disable Naming/MethodName these mimic Java fields, which are
23
27
  # actually methods
@@ -39,80 +39,26 @@ module OpenHAB
39
39
  group.name
40
40
  end
41
41
 
42
- # Send a command to each member of the group
43
- #
44
- # @return [GroupMembers] +self+
45
- def command(command)
46
- each { |item| item << command }
47
- end
48
42
  alias << command
49
-
50
- # @!method refresh
51
- # Send the +REFRESH+ command to each member of the group
52
- # @return [GroupMembers] +self+
53
-
54
- # @!method on
55
- # Send the +ON+ command to each member of the group
56
- # @return [GroupMembers] +self+
57
-
58
- # @!method off
59
- # Send the +OFF+ command to each member of the group
60
- # @return [GroupMembers] +self+
61
-
62
- # @!method up
63
- # Send the +UP+ command to each member of the group
64
- # @return [GroupMembers] +self+
65
-
66
- # @!method down
67
- # Send the +DOWN+ command to each member of the group
68
- # @return [GroupMembers] +self+
69
-
70
- # @!method stop
71
- # Send the +STOP+ command to each member of the group
72
- # @return [GroupMembers] +self+
73
-
74
- # @!method move
75
- # Send the +MOVE+ command to each member of the group
76
- # @return [GroupMembers] +self+
77
-
78
- # @!method increase
79
- # Send the +INCREASE+ command to each member of the group
80
- # @return [GroupMembers] +self+
81
-
82
- # @!method desrease
83
- # Send the +DECREASE+ command to each member of the group
84
- # @return [GroupMembers] +self+
85
-
86
- # @!method play
87
- # Send the +PLAY+ command to each member of the group
88
- # @return [GroupMembers] +self+
89
-
90
- # @!method pause
91
- # Send the +PAUSE+ command to each member of the group
92
- # @return [GroupMembers] +self+
93
-
94
- # @!method rewind
95
- # Send the +REWIND+ command to each member of the group
96
- # @return [GroupMembers] +self+
97
-
98
- # @!method fast_forward
99
- # Send the +FASTFORWARD+ command to each member of the group
100
- # @return [GroupMembers] +self+
101
-
102
- # @!method next
103
- # Send the +NEXT+ command to each member of the group
104
- # @return [GroupMembers] +self+
105
-
106
- # @!method previous
107
- # Send the +PREVIOUS+ command to each member of the group
108
- # @return [GroupMembers] +self+
109
43
  end
110
44
 
111
45
  include Enumerable
112
46
  include ComparableItem
47
+ prepend Semantics # make Semantics#points take precedence over Enumerable#points for GroupItem
113
48
 
114
49
  remove_method :==
115
50
 
51
+ # Override Enumerable because we want to send them to the base item if possible
52
+ #
53
+ # @return [GroupMembers] +self+
54
+ %i[command update].each do |method|
55
+ define_method(method) do |command|
56
+ return base_item.__send__(method, command) if base_item
57
+
58
+ super(command)
59
+ end
60
+ end
61
+
116
62
  #
117
63
  # Get an Array-like object representing the members of the group
118
64
  #
@@ -167,6 +113,7 @@ module OpenHAB
167
113
  super
168
114
  end
169
115
 
116
+ # Is this ever called?
170
117
  # give the base item type a chance to format commands
171
118
  # @!visibility private
172
119
  def format_type(command)
@@ -69,13 +69,20 @@ module OpenHAB
69
69
  end # end
70
70
  RUBY
71
71
 
72
- logger.trace("Defining GroupItem::GroupMembers##{command} for #{value}")
73
- GroupItem::GroupMembers.class_eval <<~RUBY, __FILE__, __LINE__ + 1
72
+ logger.trace("Defining Enumerable##{command} for #{value}")
73
+ Enumerable.class_eval <<~RUBY, __FILE__, __LINE__ + 1
74
74
  def #{command} # def on
75
75
  each(&:#{command}) # each(&:on)
76
76
  end # end
77
77
  RUBY
78
78
 
79
+ # Override the inherited methods from Enumerable and send it to the base_item
80
+ GroupItem.class_eval <<~RUBY, __FILE__, __LINE__ + 1
81
+ def #{command} # def on
82
+ method_missing(:#{command}) # method_missing(:on)
83
+ end # end
84
+ RUBY
85
+
79
86
  logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
80
87
  MonkeyPatch::Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
81
88
  def #{command}? # def refresh?
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Additions to Enumerable to allow easily filtering and commanding groups of items
4
+ module Enumerable
5
+ # Returns a new array of items that have at least one of the given tags
6
+ def tagged(*tags)
7
+ reject { |i| (tags & i.tags.to_a).empty? }
8
+ end
9
+
10
+ # Returns a new array of items that do not have any of the given tags
11
+ def not_tagged(*tags)
12
+ select { |i| (tags & i.tags.to_a).empty? }
13
+ end
14
+
15
+ # Returns a new array of items that are a member of at least one of the given groups
16
+ def member_of(*groups)
17
+ reject { |i| (groups.map(&:name) & i.group_names).empty? }
18
+ end
19
+
20
+ # Returns a new array of items that are not a member of any of the given groups
21
+ def not_member_of(*groups)
22
+ select { |i| (groups.map(&:name) & i.group_names).empty? }
23
+ end
24
+
25
+ # Send a command to every item in the collection
26
+ def command(command)
27
+ each { |i| i.command(command) }
28
+ end
29
+
30
+ # Update the state of every item in the collection
31
+ def update(state)
32
+ each { |i| i.update(state) }
33
+ end
34
+
35
+ # Returns the group members the elements
36
+ def members
37
+ select { |e| e.respond_to? :members }.flat_map(&:members)
38
+ end
39
+
40
+ # @!method refresh
41
+ # Send the +REFRESH+ command to every item in the collection
42
+
43
+ # @!method on
44
+ # Send the +ON+ command to every item in the collection
45
+
46
+ # @!method off
47
+ # Send the +OFF+ command to every item in the collection
48
+
49
+ # @!method up
50
+ # Send the +UP+ command to every item in the collection
51
+
52
+ # @!method down
53
+ # Send the +DOWN+ command to every item in the collection
54
+
55
+ # @!method stop
56
+ # Send the +STOP+ command to every item in the collection
57
+
58
+ # @!method move
59
+ # Send the +MOVE+ command to every item in the collection
60
+
61
+ # @!method increase
62
+ # Send the +INCREASE+ command to every item in the collection
63
+
64
+ # @!method decrease
65
+ # Send the +DECREASE+ command to every item in the collection
66
+
67
+ # @!method play
68
+ # Send the +PLAY+ command to every item in the collection
69
+
70
+ # @!method pause
71
+ # Send the +pause+ command to every item in the collection
72
+
73
+ # @!method rewind
74
+ # Send the +REWIND+ command to every item in the collection
75
+
76
+ # @!method fast_forward
77
+ # Send the +FAST_FORWARD+ command to every item in the collection
78
+
79
+ # @!method next
80
+ # Send the +NEXT+ command to every item in the collection
81
+
82
+ # @!method previous
83
+ # Send the +PREVIOUS+ command to every item in the collection
84
+
85
+ # @!visibility private
86
+ # can't use `include`, because Enumerable has already been included
87
+ # in other classes
88
+ def ensure
89
+ OpenHAB::DSL::Ensure::GenericItemDelegate.new(self)
90
+ end
91
+ end
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'semantics/enumerable'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Items
8
+ # Module for implementing semantics helper methods on [GenericItem]
9
+ #
10
+ # Wraps https://www.openhab.org/javadoc/latest/org/openhab/core/model/script/actions/semantics,
11
+ # as well as adding a few additional convenience methods.
12
+ # Also includes Classes for each semantic tag.
13
+ #
14
+ # Be warned that the Semantic model is stricter than can actually be
15
+ # described by tags and groups on an Item. It makes assumptions that any
16
+ # given item only belongs to one semantic type (Location, Equipment, Point).
17
+ #
18
+ # See https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.semantics/model/SemanticTags.csv
19
+ module Semantics
20
+ # @!visibility private
21
+ # import the actual semantics action
22
+ SemanticsAction = org.openhab.core.model.script.actions.Semantics
23
+ private_constant :SemanticsAction
24
+
25
+ # import all the semantics constants
26
+ [org.openhab.core.semantics.model.point.Points,
27
+ org.openhab.core.semantics.model.property.Properties,
28
+ org.openhab.core.semantics.model.equipment.Equipments,
29
+ org.openhab.core.semantics.model.location.Locations].each do |parent_tag|
30
+ parent_tag.stream.for_each do |tag|
31
+ const_set(tag.simple_name.to_sym, tag.ruby_class)
32
+ end
33
+ end
34
+
35
+ # put ourself into the global namespace, replacing the action
36
+ ::Semantics = self # rubocop:disable Naming/ConstantName
37
+
38
+ # Checks if this Item is a Location
39
+ #
40
+ # This is implemented as checking if the item's semantic_type
41
+ # is a Location. I.e. an Item has a single semantic_type.
42
+ #
43
+ # @return [true, false]
44
+ def location?
45
+ SemanticsAction.location?(self)
46
+ end
47
+
48
+ # Checks if this Item is an Equipment
49
+ #
50
+ # This is implemented as checking if the item's semantic_type
51
+ # is an Equipment. I.e. an Item has a single semantic_type.
52
+ #
53
+ # @return [true, false]
54
+ def equipment?
55
+ SemanticsAction.equipment?(self)
56
+ end
57
+
58
+ # Checks if this Item is a Point
59
+ #
60
+ # This is implemented as checking if the item's semantic_type
61
+ # is a Point. I.e. an Item has a single semantic_type.
62
+ #
63
+ # @return [true, false]
64
+ def point?
65
+ SemanticsAction.point?(self)
66
+ end
67
+
68
+ # Checks if this Item has any semantic tags
69
+ # @return [true, false]
70
+ def semantic?
71
+ !!semantic_type
72
+ end
73
+
74
+ # Gets the related Location Item of this Item.
75
+ #
76
+ # Returns +self+ if this Item is a Location. Otherwise, checks ancestor
77
+ # groups one level at a time, returning the first Location Item found.
78
+ #
79
+ # @return [GenericItem, nil]
80
+ def location
81
+ SemanticsAction.get_location(self)
82
+ end
83
+
84
+ # Returns the sub-class of [Location] related to this Item.
85
+ #
86
+ # In other words, the semantic_type of this Item's Location.
87
+ #
88
+ # @return [Class]
89
+ def location_type
90
+ SemanticsAction.get_location_type(self)&.ruby_class
91
+ end
92
+
93
+ # Gets the related Equipment Item of this Item.
94
+ #
95
+ # Returns +self+ if this Item is an Equipment. Otherwise, checks ancestor
96
+ # groups one level at a time, returning the first Equipment Item found.
97
+ #
98
+ # @return [GenericItem, nil]
99
+ def equipment
100
+ SemanticsAction.get_equipment(self)
101
+ end
102
+
103
+ # Returns the sub-class of [Equipment] related to this Item.
104
+ #
105
+ # In other words, the semantic_type of this Item's Equipment.
106
+ #
107
+ # @return [Class]
108
+ def equipment_type
109
+ SemanticsAction.get_equipment_type(self)&.ruby_class
110
+ end
111
+
112
+ # Returns the sub-class of [Point] this Item is tagged with.
113
+ #
114
+ # @return [Class]
115
+ def point_type
116
+ SemanticsAction.get_point_type(self)&.ruby_class
117
+ end
118
+
119
+ # Returns the sub-class of [Property] this Item is tagged with.
120
+ # @return [Class]
121
+ def property_type
122
+ SemanticsAction.get_property_type(self)&.ruby_class
123
+ end
124
+
125
+ # Returns the sub-class of [Tag] this Item is tagged with.
126
+ #
127
+ # It will only return the first applicable Tag, preferring
128
+ # a sub-class of [Location], [Equipment], or [Point] first,
129
+ # and if none of those are found, looks for a [Property].
130
+ # @return [Class]
131
+ def semantic_type
132
+ SemanticsAction.get_semantic_type(self)&.ruby_class
133
+ end
134
+
135
+ # Return the related Point Items.
136
+ #
137
+ # Searches this Equipment Item for Points that are tagged appropriately.
138
+ #
139
+ # If called on a Point Item, it will automatically search for sibling Points
140
+ # (and remove itself if found).
141
+ #
142
+ # @example Get all points for a TV
143
+ # eGreatTV.points
144
+ # @example Search an Equipment item for its switch
145
+ # eGuestFan.points(Semantics::Switch) # => [GuestFan_Dimmer]
146
+ # @example Search a Thermostat item for its current temperature item
147
+ # eFamilyThermostat.points(Semantics::Status, Semantics::Temperature)
148
+ # # => [FamilyThermostat_AmbTemp]
149
+ # @example Search a Thermostat item for is setpoints
150
+ # eFamilyThermostat.points(Semantics::Control, Semantics::Temperature)
151
+ # # => [FamilyThermostat_HeatingSetpoint, FamilyThermostat_CoolingSetpoint]
152
+ # @example Given a A/V receiver's input item, search for its power item
153
+ # FamilyReceiver_Input.points(Semantics::Switch) # => [FamilyReceiver_Switch]
154
+ #
155
+ # @param [Class] point_or_property_types
156
+ # Pass 1 or 2 classes that are sub-classes of [Point] or [Property].
157
+ # Note that when comparing against semantic tags, it does a sub-class check.
158
+ # So if you search for [Control], you'll get items tagged with [Switch].
159
+ # @return [Array<GenericItem>]
160
+ def points(*point_or_property_types)
161
+ return members.points(*point_or_property_types) if equipment? || location?
162
+
163
+ # automatically search the parent equipment (or location?!) for sibling points
164
+ result = (equipment || location)&.points(*point_or_property_types) || []
165
+ # remove self. but avoid state comparisons
166
+ result.delete_if { |item| item.eql?(self) }
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ # Additions to Enumerable to allow easily filtering groups of items based on the semantic model
174
+ module Enumerable
175
+ # Returns a new array of items that are a semantics Location (optionally of the given type)
176
+ def sublocations(type = nil)
177
+ if type && !(type < OpenHAB::DSL::Items::Semantics::Location)
178
+ raise ArgumentError, 'type must be a subclass of Location'
179
+ end
180
+
181
+ result = select(&:location?)
182
+ result.select! { |i| i.location_type <= type } if type
183
+
184
+ result
185
+ end
186
+
187
+ # Returns a new array of items that are a semantics equipment (optionally of the given type)
188
+ #
189
+ # @example Get all TVs in a room
190
+ # lGreatRoom.equipments(Semantics::Screen)
191
+ def equipments(type = nil)
192
+ if type && !(type < OpenHAB::DSL::Items::Semantics::Equipment)
193
+ raise ArgumentError, 'type must be a subclass of Equipment'
194
+ end
195
+
196
+ result = select(&:equipment?)
197
+ result.select! { |i| i.equipment_type <= type } if type
198
+
199
+ result
200
+ end
201
+
202
+ # Returns a new array of items that are semantics points (optionally of a given type)
203
+ #
204
+ # @example Get all the power switch items for every equipment in a room
205
+ # lGreatRoom.equipments.points(Semantics::Switch)
206
+ def points(*point_or_property_types) # rubocop:disable Metrics
207
+ unless (0..2).cover?(point_or_property_types.length)
208
+ raise ArgumentError, "wrong number of arguments (given #{point_or_property_types.length}, expected 0..2)"
209
+ end
210
+ unless point_or_property_types.all? do |tag|
211
+ tag < OpenHAB::DSL::Items::Semantics::Point || tag < OpenHAB::DSL::Items::Semantics::Property
212
+ end
213
+ raise ArgumentError, 'point_or_property_types must all be a subclass of Point or Property'
214
+ end
215
+ if point_or_property_types.count { |tag| tag < OpenHAB::DSL::Items::Semantics::Point } > 1 ||
216
+ point_or_property_types.count { |tag| tag < OpenHAB::DSL::Items::Semantics::Property } > 1
217
+ raise ArgumentError, 'point_or_property_types cannot both be a subclass of Point or Property'
218
+ end
219
+
220
+ select do |point|
221
+ point.point? && point_or_property_types.all? do |tag|
222
+ (tag < OpenHAB::DSL::Items::Semantics::Point && point.point_type <= tag) ||
223
+ (tag < OpenHAB::DSL::Items::Semantics::Property && point.property_type&.<=(tag))
224
+ end
225
+ end
226
+ end
227
+ end
@@ -35,7 +35,7 @@ module OpenHAB
35
35
  #
36
36
  # @param [String] expression OpenHAB style cron expression
37
37
  # @param [Object] attach object to be attached to the trigger
38
- # @param [Hash] elements cron expression elements (second, minute, hour, dom, month, dow, year)
38
+ # @param [Hash] fields cron expression elements (second, minute, hour, dom, month, dow, year)
39
39
  #
40
40
  def cron(expression = nil, attach: nil, **fields)
41
41
  if fields.any?
@@ -124,7 +124,7 @@ module OpenHAB
124
124
  #
125
125
  # Create a cron map from a MonthDay
126
126
  #
127
- # @param [Java::JavaTime::MonthDay] month_day
127
+ # @param [Java::JavaTime::MonthDay] monthday a {MonthDay} object
128
128
  # @param [Object] at TimeOfDay or String representing time of day
129
129
  #
130
130
  # @return [Hash] map describing cron expression
@@ -152,7 +152,7 @@ module OpenHAB
152
152
  #
153
153
  # Create a cron map from cron elements
154
154
  #
155
- # @param [Hash] elements Cron fields (second, minute, hour, dom, month, dow, year)
155
+ # @param [Hash] fields Cron fields (second, minute, hour, dom, month, dow, year)
156
156
  #
157
157
  # @return [Hash] map describing cron expression
158
158
  #
@@ -33,7 +33,7 @@ module OpenHAB
33
33
  # Check if all the given items have a state (not UNDEF or NULL)
34
34
  #
35
35
  # @param [Array] items whose state must be non-nil
36
- # @param [<Type>] check_things when true, also ensures that all linked things are online
36
+ # @param [<Type>] things when true, also ensures that all linked things are online
37
37
  #
38
38
  # @return [Boolean] true if all the items have a state, false otherwise
39
39
  #
@@ -51,7 +51,7 @@ module OpenHAB
51
51
  #
52
52
  # Create a StateStorage object that stores the states of the given items
53
53
  #
54
- # @param [Array<Item>] *items A list of items
54
+ # @param [Array<Item>] items A list of items
55
55
  #
56
56
  # @return [StateStorage] A state storage object
57
57
  #
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '4.37.1'
8
+ VERSION = '4.39.1'
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.37.1
4
+ version: 4.39.1
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: 2022-04-09 00:00:00.000000000 Z
11
+ date: 2022-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,8 @@ files:
80
80
  - lib/openhab/dsl/items/persistence.rb
81
81
  - lib/openhab/dsl/items/player_item.rb
82
82
  - lib/openhab/dsl/items/rollershutter_item.rb
83
+ - lib/openhab/dsl/items/semantics.rb
84
+ - lib/openhab/dsl/items/semantics/enumerable.rb
83
85
  - lib/openhab/dsl/items/string_item.rb
84
86
  - lib/openhab/dsl/items/switch_item.rb
85
87
  - lib/openhab/dsl/items/timed_command.rb