openhab-scripting 5.10.0 → 5.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acf8ae7ed285c32bb11070e6ae64c54b9687dae7883c272be4a9ad30f399ed8c
4
- data.tar.gz: 8820ac3849f07734843d2863ff483fbde70bfe56c41981f2d48ec2e8c7bd73a8
3
+ metadata.gz: 9e7d078cc73659d0f435950d36438b67759b2e3b5c0abf80f258a36101792a0d
4
+ data.tar.gz: 2a76c20015d6320b64a2a9ea79557c7133b1101a8514fabba9241f91b455615d
5
5
  SHA512:
6
- metadata.gz: ab2e153c20c4d81b4b4b5b7d3025d1f49812099ea1040eba85b03f6fc8ce4217d84a3204e1c0917ed53c8386220b25da7d1da4bc367b51459ef74d67a52d7d44
7
- data.tar.gz: 0bdc096799e02f344f7d24c218af6ed045840c9a87ab890e81a339896801c53c6e18a6dabafd060e2c18023b69da8fdb4df9d3d58fcab3917baba6274fe992eb
6
+ metadata.gz: bc54b1fae7be3bee15b1af2c27526cf942a13741404dd1c0e61034b82d2d472703bfb48ef921d25ed608dbe3d9c964abbded85ab1d3adfd855847229c6bf2447
7
+ data.tar.gz: c454623c911c90be03464391f885b8ccebfd2789b5e9dbbe32a6f8309fdf7e1f948e2c0730373d383bf7892271ab752bf9d8c2197ed541cff7f33a692ea296ec
@@ -133,6 +133,16 @@ module OpenHAB
133
133
  # Send the {DECREASE} command to the item
134
134
  # @return [DimmerItem] `self`
135
135
 
136
+ # @!method increase!
137
+ # Send the {INCREASE} command to the item, even when
138
+ # {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
139
+ # @return [DimmerItem] `self`
140
+
141
+ # @!method decrease!
142
+ # Send the {DECREASE} command to the item, even when
143
+ # {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
144
+ # @return [DimmerItem] `self`
145
+
136
146
  # raw numbers translate directly to PercentType, not a DecimalType
137
147
  # @!visibility private
138
148
  def format_type(command)
@@ -128,15 +128,19 @@ module OpenHAB
128
128
  # Send a command to this item
129
129
  #
130
130
  # When this method is chained after the {OpenHAB::DSL::Items::Ensure::Ensurable#ensure ensure}
131
- # method, or issued inside an {OpenHAB::DSL.ensure_states ensure_states} block,
131
+ # method, or issued inside an {OpenHAB::DSL.ensure_states ensure_states} block, or after
132
+ # {OpenHAB::DSL.ensure_states! ensure_states!} have been called,
132
133
  # the command will only be sent if the item is not already in the same state.
133
134
  #
135
+ # The similar method `command!`, however, will always send the command regardless of the item's state.
136
+ #
134
137
  # @param [Command] command command to send to the item
135
138
  # @return [self, nil] nil when `ensure` is in effect and the item was already in the same state,
136
139
  # otherwise the item.
137
140
  #
138
141
  # @see DSL::Items::TimedCommand#command Timed Command
139
142
  # @see OpenHAB::DSL.ensure_states ensure_states
143
+ # @see OpenHAB::DSL.ensure_states! ensure_states!
140
144
  # @see DSL::Items::Ensure::Ensurable#ensure ensure
141
145
  #
142
146
  def command(command)
@@ -145,6 +149,7 @@ module OpenHAB
145
149
  $events.send_command(self, command)
146
150
  Proxy.new(self)
147
151
  end
152
+ alias_method :command!, :command
148
153
 
149
154
  # not an alias to allow easier stubbing and overriding
150
155
  def <<(command)
@@ -170,6 +175,7 @@ module OpenHAB
170
175
  $events.post_update(self, state)
171
176
  Proxy.new(self)
172
177
  end
178
+ alias_method :update!, :update
173
179
 
174
180
  # @!visibility private
175
181
  def format_command(command)
@@ -39,25 +39,51 @@ module OpenHAB
39
39
  # Send the {PLAY} command to the item
40
40
  # @return [PlayerItem] `self`
41
41
 
42
+ # @!method play!
43
+ # Send the {PLAY} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
44
+ # @return [PlayerItem] `self`
45
+
42
46
  # @!method pause
43
47
  # Send the {PAUSE} command to the item
44
48
  # @return [PlayerItem] `self`
45
49
 
50
+ # @!method pause!
51
+ # Send the {PAUSE} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
52
+ # @return [PlayerItem] `self`
53
+
46
54
  # @!method rewind
47
55
  # Send the {REWIND} command to the item
48
56
  # @return [PlayerItem] `self`
49
57
 
58
+ # @!method rewind
59
+ # Send the {REWIND} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
60
+ # @return [PlayerItem] `self`
61
+
50
62
  # @!method fast_forward
51
63
  # Send the {FASTFORWARD} command to the item
52
64
  # @return [PlayerItem] `self`
53
65
 
66
+ # @!method fast_forward!
67
+ # Send the {FASTFORWARD} command to the item, even when
68
+ # {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
69
+ # @return [PlayerItem] `self`
70
+
54
71
  # @!method next
55
72
  # Send the {NEXT} command to the item
56
73
  # @return [PlayerItem] `self`
57
74
 
75
+ # @!method next!
76
+ # Send the {NEXT} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
77
+ # @return [PlayerItem] `self`
78
+
58
79
  # @!method previous
59
80
  # Send the {PREVIOUS} command to the item
60
81
  # @return [PlayerItem] `self`
82
+
83
+ # @!method previous!
84
+ # Send the {PREVIOUS} command to the item, even when
85
+ # {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
86
+ # @return [PlayerItem] `self`
61
87
  end
62
88
  end
63
89
  end
@@ -41,18 +41,34 @@ module OpenHAB
41
41
  # Send the {UP} command to the item
42
42
  # @return [RollershutterItem] `self`
43
43
 
44
+ # @!method up!
45
+ # Send the {UP} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
46
+ # @return [RollershutterItem] `self`
47
+
44
48
  # @!method down
45
49
  # Send the {DOWN} command to the item
46
50
  # @return [RollershutterItem] `self`
47
51
 
52
+ # @!method down!
53
+ # Send the {DOWN} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
54
+ # @return [RollershutterItem] `self`
55
+
48
56
  # @!method stop
49
57
  # Send the {STOP} command to the item
50
58
  # @return [RollershutterItem] `self`
51
59
 
60
+ # @!method stop!
61
+ # Send the {STOP} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
62
+ # @return [RollershutterItem] `self`
63
+
52
64
  # @!method move
53
65
  # Send the {MOVE} command to the item
54
66
  # @return [RollershutterItem] `self`
55
67
 
68
+ # @!method move!
69
+ # Send the {MOVE} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
70
+ # @return [RollershutterItem] `self`
71
+
56
72
  # raw numbers translate directly to PercentType, not a DecimalType
57
73
  # @!visibility private
58
74
  def format_type(command)
@@ -101,6 +101,15 @@ module Enumerable
101
101
  self if count { |i| i.command(command) }.positive?
102
102
  end
103
103
 
104
+ # Send a command to every item in the collection, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
105
+ # @return [self]
106
+ def command!(command)
107
+ # We cannot alias this to #command above, otherwise it will call
108
+ # DSL::Items::Ensure::Item#command which checks for ensure_states
109
+ each { |i| i.command!(command) }
110
+ self
111
+ end
112
+
104
113
  # Update the state of every item in the collection
105
114
  # @return [self, nil] nil when `ensure` is in effect and all the items were already in the same state,
106
115
  # otherwise self
@@ -108,6 +117,16 @@ module Enumerable
108
117
  self if count { |i| i.update(state) }.positive?
109
118
  end
110
119
 
120
+ # Update the state of every item in the collection, even when
121
+ # {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
122
+ # @return [self]
123
+ def update!(state)
124
+ # We cannot alias this to #update above, otherwise it will call
125
+ # DSL::Items::Ensure::Item#update which checks for ensure_states
126
+ each { |i| i.update!(state) }
127
+ self
128
+ end
129
+
111
130
  # @!method refresh
112
131
  # Send the {REFRESH} command to every item in the collection
113
132
  # @return [self]
@@ -67,9 +67,17 @@ module OpenHAB
67
67
  # Send the {ON} command to the item
68
68
  # @return [SwitchItem] `self`
69
69
 
70
+ # @!method on!
71
+ # Send the {ON} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
72
+ # @return [SwitchItem] `self`
73
+
70
74
  # @!method off
71
75
  # Send the {OFF} command to the item
72
76
  # @return [SwitchItem] `self`
77
+
78
+ # @!method off!
79
+ # Send the {OFF} command to the item, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
80
+ # @return [SwitchItem] `self`
73
81
  end
74
82
  end
75
83
  end
@@ -65,13 +65,19 @@ module OpenHAB
65
65
  ruby2_keywords def #{command}(*args, &block) # ruby2_keywords def on(*args, &block)
66
66
  command(#{value}, *args, &block) # command(ON, *args, &block)
67
67
  end # end
68
+ ruby2_keywords def #{command}!(*args, &block) # ruby2_keywords def on!(*args, &block)
69
+ command!(#{value}, *args, &block) # command!(ON, *args, &block)
70
+ end # end
68
71
  RUBY
69
72
 
70
73
  logger.trace("Defining Enumerable##{command} for #{value}")
71
74
  Enumerable.class_eval <<~RUBY, __FILE__, __LINE__ + 1
72
- def #{command} # def on
73
- each(&:#{command}) # each(&:on)
74
- end # end
75
+ def #{command} # def on
76
+ each(&:#{command}) # each(&:on)
77
+ end # end
78
+ def #{command}! # def on!
79
+ each(&:#{command}!) # each(&:on!)
80
+ end # end
75
81
  RUBY
76
82
 
77
83
  logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
@@ -14,9 +14,10 @@ module OpenHAB
14
14
  # @param [Command] command
15
15
  #
16
16
  def handle_command(command)
17
- @dummy_channel_item ||= DSL::Items::ItemBuilder.item_factory.create_item(link.channel.accepted_item_type,
18
- "")
19
- command = @dummy_channel_item.format_command(command)
17
+ unless instance_variable_defined?(:@dummy_channel_item)
18
+ @dummy_channel_item = DSL::Items::ItemBuilder.item_factory.create_item(link.channel.accepted_item_type, "")
19
+ end
20
+ command = @dummy_channel_item.format_command(command) if @dummy_channel_item
20
21
  super(command)
21
22
  end
22
23
 
@@ -24,7 +24,7 @@ module OpenHAB
24
24
 
25
25
  # Extensions for {::Item} to implement {Ensure}'s functionality
26
26
  #
27
- # @see OpenHAB::DSL.ensure ensure
27
+ # @see OpenHAB::DSL::Items::Ensure::Ensurable#ensure ensure
28
28
  # @see OpenHAB::DSL.ensure_states ensure_states
29
29
  module Item
30
30
  include Ensurable
@@ -210,7 +210,18 @@ module OpenHAB
210
210
  thing_type,
211
211
  self.class.config_description_registry
212
212
  )
213
+
214
+ predefined_channels = self.class.thing_factory_helper
215
+ .create_channels(thing_type, uid, self.class.config_description_registry)
216
+ .to_h { |channel| [channel.uid, channel] }
217
+ new_channels = channels.to_h { |channel| [channel.uid, channel] }
218
+ merged_channels = predefined_channels.merge(new_channels) do |_key, predefined_channel, new_channel|
219
+ predefined_channel.configuration.merge!(new_channel.configuration)
220
+ predefined_channel
221
+ end
222
+ @channels = merged_channels.values
213
223
  end
224
+
214
225
  builder = org.openhab.core.thing.binding.builder.ThingBuilder
215
226
  .create(thing_type_uid, uid)
216
227
  .with_label(label)
@@ -219,15 +230,7 @@ module OpenHAB
219
230
  .with_bridge(bridge_uid)
220
231
  .with_channels(channels)
221
232
 
222
- if thing_type
223
- # can't use with_channels, or it will wipe out custom channels from above
224
- self.class.thing_factory_helper.create_channels(thing_type,
225
- uid,
226
- self.class.config_description_registry).each do |channel|
227
- builder.with_channel(channel)
228
- end
229
- builder.with_properties(thing_type.properties)
230
- end
233
+ builder.with_properties(thing_type.properties) if thing_type
231
234
 
232
235
  builder.build
233
236
  end
@@ -263,8 +266,14 @@ module OpenHAB
263
266
  :default_tags,
264
267
  :properties,
265
268
  :description,
266
- :auto_update_policy,
267
- :accepted_item_type
269
+ :auto_update_policy
270
+
271
+ class << self
272
+ # @!visibility private
273
+ def channel_type_registry
274
+ @channel_type_registry ||= OSGi.service("org.openhab.core.thing.type.ChannelTypeRegistry")
275
+ end
276
+ end
268
277
 
269
278
  #
270
279
  # Constructor for ChannelBuilder
@@ -284,7 +293,7 @@ module OpenHAB
284
293
  # The default tags for this channel.
285
294
  # @param [:default, :recommend, :veto, org.openhab.core.thing.type.AutoUpdatePolicy] auto_update_policy
286
295
  # The channel's auto update policy.
287
- # @param [String] accepted_item_type The accepted item type.
296
+ # @param [String] accepted_item_type The accepted item type. If nil, infer the item type from the channel type.
288
297
  #
289
298
  def initialize(uid,
290
299
  type,
@@ -343,6 +352,12 @@ module OpenHAB
343
352
  .build
344
353
  end
345
354
 
355
+ # @!attribute [r] accepted_item_type
356
+ # @return [String] The accepted item type.
357
+ def accepted_item_type
358
+ @accepted_item_type ||= self.class.channel_type_registry.get_channel_type(type)&.item_type
359
+ end
360
+
346
361
  private
347
362
 
348
363
  def kind
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.10.0"
7
+ VERSION = "5.11.0"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -557,10 +557,49 @@ module OpenHAB
557
557
  # to reduce repetitions
558
558
  #
559
559
 
560
+ #
561
+ # Permanently enable conditional execution of commands and updates for the current thread.
562
+ #
563
+ # When conditional executions are enabled, commands and updates will only be sent if the
564
+ # item's current state is not the same as the command or updated state.
565
+ # This eliminates the need to chain the command and update calls through
566
+ # {DSL::Items::Ensure::Ensurable#ensure ensure}.
567
+ #
568
+ # When conditional executions are enabled either by this method or within a block of {ensure_states},
569
+ # commands and updates can still be forcefully executed using the corresponding bang methods, e.g.
570
+ # `Item1.on!`, `Item1.command!(50)`, or `Item1.update!(ON)`.
571
+ #
572
+ # @note This method is only intended for use at the top level of rule
573
+ # scripts. If it's used within library methods, or hap-hazardly within
574
+ # rules, things can get very confusing because the prior state won't be
575
+ # properly restored.
576
+ #
577
+ # @param [Boolean] active Whether to enable or disable conditional executions.
578
+ # @return [Boolean] The previous ensure_states setting.
579
+ #
580
+ # @example Make ensure_states the default for the rest of the script
581
+ # ensure_states!
582
+ #
583
+ # # From now, all commands are "ensured", i.e. only sent when the current state is different
584
+ # Item1.on
585
+ # Item2.command(ON)
586
+ #
587
+ # # While ensure_states! is active, we can still forcibly send a command
588
+ # # regardless of the item's current state
589
+ # Item2.on!
590
+ #
591
+ # @see ensure_states
592
+ #
593
+ def ensure_states!(active: true)
594
+ old = Thread.current[:openhab_ensure_states]
595
+ Thread.current[:openhab_ensure_states] = active
596
+ old
597
+ end
598
+
560
599
  #
561
600
  # Global method that takes a block and for the duration of the block
562
601
  # all commands sent will check if the item is in the command's state
563
- # before sending the command.
602
+ # before sending the command. This also applies to updates.
564
603
  #
565
604
  # @yield
566
605
  # @return [Object] The result of the block.
@@ -603,11 +642,10 @@ module OpenHAB
603
642
  # end
604
643
  #
605
644
  def ensure_states
606
- old = Thread.current[:openhab_ensure_states]
607
- Thread.current[:openhab_ensure_states] = true
645
+ old = ensure_states!
608
646
  yield
609
647
  ensure
610
- Thread.current[:openhab_ensure_states] = old
648
+ ensure_states!(active: old)
611
649
  end
612
650
 
613
651
  #
@@ -841,7 +879,7 @@ module OpenHAB
841
879
  # elements, the {Core::Items::Metadata::Hash} will be passed as an argument. Therefore it's
842
880
  # recommended that you use a Proc, not a Lambda, for permissive argument matching.
843
881
  #
844
- # @return [void]
882
+ # @return [Hash] the prior provider configuration.
845
883
  #
846
884
  # @see provider
847
885
  # @see OpenHAB::Core::Provider.current Provider.current for how the current provider is calculated
@@ -5,26 +5,36 @@ module OpenHAB
5
5
  # based on https://stackoverflow.com/questions/1197224/source-shell-script-into-environment-within-a-ruby-script#19826329
6
6
  # @!visibility private
7
7
  module Shell
8
- module_function
8
+ # @!visibility private
9
+ DEFAULT_PRINTENV_COMMAND = "printenv -0"
10
+ @printenv_command = DEFAULT_PRINTENV_COMMAND
11
+ @printenv_separator = "\0"
9
12
 
10
- # Read in the bash environment, after an optional command.
11
- # Returns Array of key/value pairs.
12
- def shell_env(cmd = nil)
13
- cmd = "#{cmd} > /dev/null; " if cmd
14
- env = `#{cmd}printenv -0`
15
- env.split("\0").map { |l| l.split("=", 2) }
16
- end
13
+ class << self
14
+ # Read in the bash environment, after an optional command.
15
+ # Returns Array of key/value pairs.
16
+ def shell_env(cmd = nil)
17
+ cmd = "#{cmd} > #{IO::NULL}; " if cmd
18
+ env = `#{cmd}#{@printenv_command} 2> #{IO::NULL}`
19
+ if !$?.success? && @printenv_command.equal?(DEFAULT_PRINTENV_COMMAND)
20
+ @printenv_command = "printenv"
21
+ @printenv_separator = "\n"
22
+ env = `#{cmd}#{@printenv_command}`
23
+ end
24
+ env.split(@printenv_separator).map { |l| l.split("=", 2) }
25
+ end
17
26
 
18
- # Source a given file, and compare environment before and after.
19
- # Returns Hash of any keys that have changed.
20
- def shell_source(file)
21
- (shell_env(". #{File.realpath(file)}") - shell_env).to_h
22
- end
27
+ # Source a given file, and compare environment before and after.
28
+ # Returns Hash of any keys that have changed.
29
+ def shell_source(file)
30
+ (shell_env(". #{File.realpath(file)}") - shell_env).to_h
31
+ end
23
32
 
24
- # Find variables changed as a result of sourcing the given file,
25
- # and update in ENV.
26
- def source_env_from(file)
27
- shell_source(file).each { |k, v| ENV[k] = v }
33
+ # Find variables changed as a result of sourcing the given file,
34
+ # and update in ENV.
35
+ def source_env_from(file)
36
+ shell_source(file).each { |k, v| ENV[k] = v }
37
+ end
28
38
  end
29
39
  end
30
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.10.0
4
+ version: 5.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-10-25 00:00:00.000000000 Z
13
+ date: 2023-10-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler