openhab-scripting 5.2.0 → 5.4.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: 3d56223cd6766da527070ec31571d7a22cffa7d69ec754a1a1dbeb06c9354d56
4
- data.tar.gz: c635cf86c119c54c4b665f28cd91b0804a58c868d23f7a99420d4183f60bf195
3
+ metadata.gz: 0522f086fca640c17a05634e13924dd9e39fc0630fba03954d4c0ffcfc1739c7
4
+ data.tar.gz: 9c01b1545d9e999ecc9ff0836691ef858794085ffb09433a3636c7594251e13b
5
5
  SHA512:
6
- metadata.gz: 79e7ac98695e1fb75a6bf100226a555d2d1d8f7a96efa0779b42439e262bfb63777ee99545782885f509c08f21dc77b2b504fd13078a5e5bc1d82ce456e3cca9
7
- data.tar.gz: d735f987f2540cba7b358a4f0550ed723ef807b0a4c5e12ab21177cc844f65a2eec1080778b996e702cd72a5d744b1a7c97fe52ba5679a17a13b4988ccd2bf76
6
+ metadata.gz: c1c7e125bb92764cc330924cacc30b03bf8759633bf34e51000897614af32efa2bcddfd2c48e5514be160d6c2d625eb38449c4d6203c5ca418bf67868d302aa2
7
+ data.tar.gz: 61742a93f67041588c6f6af954f95dd7515d8ee2d913812f5ac32212a8ddc49f979da4712125d1b15ca327b130ec81102308edbe5689f43e386d24b46f185357
@@ -74,19 +74,19 @@ module OpenHAB
74
74
  #
75
75
  # Returns all Scenes (rules tagged with "Scene")
76
76
  #
77
- # @return [Array<Rule>] A list of all the scenes
77
+ # @return [TaggedArray] A list of all the scenes
78
78
  #
79
79
  def scenes
80
- tagged("Scene")
80
+ @scenes ||= TaggedArray.new("Scene")
81
81
  end
82
82
 
83
83
  #
84
84
  # Returns all Scripts (rules tagged with "Script")
85
85
  #
86
- # @return [Array<Rule>] A list of all the scripts
86
+ # @return [TaggedArray] A list of all the scripts
87
87
  #
88
88
  def scripts
89
- tagged("Script")
89
+ @scripts ||= TaggedArray.new("Script")
90
90
  end
91
91
  end
92
92
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Rules
8
+ #
9
+ # Provides access to a set of openHAB {Rule rules}, and acts like an array.
10
+ #
11
+ class TaggedArray
12
+ include LazyArray
13
+
14
+ def initialize(tag)
15
+ @tag = tag
16
+ end
17
+
18
+ #
19
+ # Gets a specific Rule
20
+ #
21
+ # @param [String] uid Rule UID
22
+ # @return [Rule, nil]
23
+ #
24
+ def [](uid)
25
+ rule = $rules.get(uid)
26
+ rule.tagged?(@tag) ? rule : nil
27
+ end
28
+ alias_method :include?, :[]
29
+ alias_method :key?, :[]
30
+ # @deprecated
31
+ alias_method :has_key?, :[]
32
+
33
+ #
34
+ # Explicit conversion to array
35
+ #
36
+ # @return [Array<Rule>]
37
+ #
38
+ def to_a
39
+ $rules.all.to_a.tagged(@tag)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module CoreExt
5
+ module Ruby
6
+ # @!visibility private
7
+ module Object
8
+ class << self
9
+ attr_reader :top_self
10
+ end
11
+
12
+ # @!visibility private
13
+ module ClassMethods
14
+ # capture methods defined at top level (which get added to Object)
15
+ def method_added(method)
16
+ return super unless equal?(::Object)
17
+
18
+ if DSL.private_instance_methods.include?(method)
19
+ # Duplicate methods that conflict with DSL onto `main`'s singleton class,
20
+ # so that they'll take precedence over DSL's method.
21
+ Object.top_self.singleton_class.define_method(method, instance_method(method))
22
+ end
23
+
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -22,6 +22,12 @@ module OpenHAB
22
22
  # group_item Equipment, tags: Semantics::HVAC, thing: "binding:thing"
23
23
  # string_item Mode, tags: Semantics::Control, channel: "mode"
24
24
  # end
25
+ #
26
+ # # dimension Temperature inferred
27
+ # number_item OutdoorTemp, format: "%.1f %unit%", unit: "°F"
28
+ #
29
+ # # unit lx, dimension Illuminance, format "%s %unit%" inferred
30
+ # number_item OutdoorBrightness, state: 10_000 | "lx"
25
31
  # end
26
32
  #
27
33
  module Builder
@@ -156,9 +162,22 @@ module OpenHAB
156
162
  # @return [String, nil]
157
163
  attr_accessor :label
158
164
  # Unit dimension (for number items only)
165
+ #
166
+ # If {unit} is provided, and {dimension} is not, it will be inferred.
167
+ #
159
168
  # @return [String, nil]
160
169
  attr_accessor :dimension
170
+ # Unit (for number items only)
171
+ #
172
+ # Due to {format} inference, setting the unit is cross-compatible with
173
+ # openHAB 3.4 and 4.0.
174
+ #
175
+ # @return [String, nil]
176
+ attr_reader :unit
161
177
  # The formatting pattern for the item's state
178
+ #
179
+ # If {unit} is provided, and {format} is not, it will be inferred.
180
+ #
162
181
  # @return [String, nil]
163
182
  attr_accessor :format
164
183
  # The icon to be associated with the item
@@ -179,13 +198,16 @@ module OpenHAB
179
198
  # @return [Core::Items::Metadata::NamespaceHash]
180
199
  attr_reader :metadata
181
200
  # Initial state
201
+ #
202
+ # If {state} is set to a {QuantityType}, and {unit} is not set, it will be inferred.
203
+ #
182
204
  # @return [Core::Types::State]
183
- attr_accessor :state
205
+ attr_reader :state
184
206
 
185
207
  class << self
186
208
  # @!visibility private
187
209
  def item_factory
188
- @item_factory ||= org.openhab.core.library.CoreItemFactory.new
210
+ @item_factory ||= OpenHAB::OSGi.service("org.openhab.core.items.ItemFactory")
189
211
  end
190
212
 
191
213
  #
@@ -214,6 +236,7 @@ module OpenHAB
214
236
  end
215
237
 
216
238
  # @param dimension [Symbol, nil] The unit dimension for a {NumberItem} (see {ItemBuilder#dimension})
239
+ # @param unit [Symbol, String, nil] The unit for a {NumberItem} (see {ItemBuilder#unit})
217
240
  # @param format [String, nil] The formatting pattern for the item's state (see {ItemBuilder#format})
218
241
  # @param icon [Symbol, nil] The icon to be associated with the item (see {ItemBuilder#icon})
219
242
  # @param group [String,
@@ -246,6 +269,7 @@ module OpenHAB
246
269
  def initialize(type, name = nil, label = nil,
247
270
  provider:,
248
271
  dimension: nil,
272
+ unit: nil,
249
273
  format: nil,
250
274
  icon: nil,
251
275
  group: nil,
@@ -274,6 +298,7 @@ module OpenHAB
274
298
  @label = label
275
299
  @dimension = dimension
276
300
  @format = format
301
+ self.unit = unit
277
302
  @icon = icon
278
303
  @groups = []
279
304
  @tags = []
@@ -291,7 +316,7 @@ module OpenHAB
291
316
  self.alexa(alexa) if alexa
292
317
  self.ga(ga) if ga
293
318
  self.homekit(homekit) if homekit
294
- @state = state
319
+ self.state = state
295
320
 
296
321
  self.group(*group)
297
322
  self.group(*groups)
@@ -434,6 +459,39 @@ module OpenHAB
434
459
  @expire += ",command=#{command}" if command
435
460
  end
436
461
 
462
+ # @!attribute [w] unit
463
+ #
464
+ # Unit (for number items only).
465
+ #
466
+ # If dimension or format are not yet set, they will be inferred.
467
+ #
468
+ # @return [String, nil]
469
+ def unit=(unit)
470
+ @unit = unit
471
+
472
+ self.dimension ||= unit && org.openhab.core.types.util.UnitUtils.parse_unit(unit)&.then do |u|
473
+ org.openhab.core.types.util.UnitUtils.get_dimension_name(u)
474
+ end
475
+ self.format ||= unit && (if Gem::Version.new(Core::VERSION) >= Gem::Version.new("4.0.0.M3")
476
+ "%s %unit%"
477
+ else
478
+ "%s #{unit.gsub("%", "%%")}"
479
+ end)
480
+ end
481
+
482
+ # @!attribute [w] state
483
+ #
484
+ # Initial state
485
+ #
486
+ # If {state} is set to a {QuantityType}, and {unit} is not set, it will be inferred.
487
+ #
488
+ # @return [Core::Types::State]
489
+ def state=(state)
490
+ @state = state
491
+
492
+ self.unit ||= state.unit.to_s if state.is_a?(QuantityType)
493
+ end
494
+
437
495
  # @!visibility private
438
496
  def build
439
497
  item = create_item
@@ -450,6 +508,7 @@ module OpenHAB
450
508
  item.metadata["autoupdate"] = autoupdate.to_s unless autoupdate.nil?
451
509
  item.metadata["expire"] = expire if expire
452
510
  item.metadata["stateDescription"] = { "pattern" => format } if format
511
+ item.metadata["unit"] = unit if unit
453
512
  item.state = item.format_update(state) unless state.nil?
454
513
  item
455
514
  end
@@ -488,6 +547,12 @@ module OpenHAB
488
547
  class GroupItemBuilder < ItemBuilder
489
548
  include Builder
490
549
 
550
+ # This has to be duplicated here, since {Builder} includes DSL, so DSL#unit
551
+ # will be seen first, but we really want ItemBuilder#unit
552
+
553
+ # (see ItemBuilder#unit)
554
+ attr_reader :unit
555
+
491
556
  Builder.public_instance_methods.each do |m|
492
557
  next unless Builder.instance_method(m).owner == Builder
493
558
 
@@ -35,8 +35,7 @@ module OpenHAB
35
35
  super()
36
36
  set_name(config.name)
37
37
  set_description(config.description)
38
- tags = DSL::Items::ItemBuilder.normalize_tags(*config.tags)
39
- set_tags(tags.to_set)
38
+ set_tags(config.tags.to_set)
40
39
  set_triggers(config.triggers)
41
40
  self.uid = config.uid
42
41
  @run_context = config.caller
@@ -104,7 +104,37 @@ module OpenHAB
104
104
  ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
105
105
  builder = BuilderDSL.new(block.binding)
106
106
  builder.uid(id)
107
- builder.tags(["Script"])
107
+ builder.tags("Script")
108
+ builder.name(name)
109
+ builder.script(&block)
110
+ logger.trace { builder.inspect }
111
+ builder.build(provider, script)
112
+ end
113
+ end
114
+
115
+ #
116
+ # Create a new scene
117
+ #
118
+ # A scene is a rule with no triggers. It can be called by various other actions,
119
+ # such as the Run Rules action.
120
+ #
121
+ # @param [String] name A descriptive name
122
+ # @param [String] id The script's ID
123
+ # @yield [] Block executed when the script is executed.
124
+ # @return [Core::Rules::Rule]
125
+ #
126
+ def scene(name = nil, id: nil, script: nil, &block)
127
+ raise ArgumentError, "Block is required" unless block
128
+
129
+ id ||= NameInference.infer_rule_id_from_block(block)
130
+ name ||= id
131
+ script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
132
+
133
+ builder = nil
134
+ ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
135
+ builder = BuilderDSL.new(block.binding)
136
+ builder.uid(id)
137
+ builder.tags("Scene")
108
138
  builder.name(name)
109
139
  builder.script(&block)
110
140
  logger.trace { builder.inspect }
@@ -354,7 +384,7 @@ module OpenHAB
354
384
  prop :description
355
385
 
356
386
  #
357
- # @!method tags(tags)
387
+ # @!method tags(*tags)
358
388
  #
359
389
  # Set the rule's tags.
360
390
  #
@@ -1082,6 +1112,7 @@ module OpenHAB
1082
1112
 
1083
1113
  raise ArgumentError, "Missing cron expression or elements" unless expression
1084
1114
 
1115
+ add_tag("Schedule")
1085
1116
  cron = Cron.new(rule_triggers: @rule_triggers)
1086
1117
  cron.trigger(config: { "cronExpression" => expression }, attach: attach)
1087
1118
  end
@@ -1180,6 +1211,7 @@ module OpenHAB
1180
1211
  if value == :day && at.is_a?(Item)
1181
1212
  raise ArgumentError, "Attachments are not supported with dynamic datetime triggers" unless attach.nil?
1182
1213
 
1214
+ add_tag("Schedule")
1183
1215
  return trigger("timer.DateTimeTrigger", itemName: at.name, timeOnly: true)
1184
1216
  end
1185
1217
 
@@ -1561,6 +1593,7 @@ module OpenHAB
1561
1593
  #
1562
1594
  def at(item)
1563
1595
  item = item.name if item.is_a?(Item)
1596
+ add_tag("Schedule")
1564
1597
  trigger("timer.DateTimeTrigger", itemName: item.to_s)
1565
1598
  end
1566
1599
 
@@ -1847,6 +1880,15 @@ module OpenHAB
1847
1880
 
1848
1881
  private
1849
1882
 
1883
+ # Adds a single tag to this rule
1884
+ # @param [String] tag The tag (it will not be normalized)
1885
+ # @return [void]
1886
+ def add_tag(tag)
1887
+ # have to normalize tags first
1888
+ @tags = DSL::Items::ItemBuilder.normalize_tags(*tags)
1889
+ @tags << tag unless @tags.include?(tag)
1890
+ end
1891
+
1850
1892
  # Calls the on_load block, with a delay if specified
1851
1893
  # @yield block to execute on load time
1852
1894
  # @yieldparam [String] module The module ID that identifies this on_load event
@@ -1871,7 +1913,8 @@ module OpenHAB
1871
1913
  # @return [true,false] true if it should be created, false otherwise
1872
1914
  #
1873
1915
  def create_rule?
1874
- return true if tags.include?("Script")
1916
+ @tags = DSL::Items::ItemBuilder.normalize_tags(*tags)
1917
+ return true unless (tags & %w[Script Scene]).empty?
1875
1918
 
1876
1919
  if !triggers?
1877
1920
  logger.warn "Rule '#{uid}' has no triggers, not creating rule"
@@ -51,7 +51,7 @@ module OpenHAB
51
51
  # @return [CronAdjuster]
52
52
  #
53
53
  def getTemporalAdjuster # rubocop:disable Naming/MethodName
54
- org.openhab.core.scheduler.CronAdjuster.new(expression)
54
+ org.openhab.core.scheduler.CronAdjuster.new(@expression)
55
55
  end
56
56
 
57
57
  #
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.2.0"
7
+ VERSION = "5.4.0"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -59,6 +59,11 @@ module OpenHAB
59
59
  rules.build { rule(name, **kwargs, &block) }
60
60
  end
61
61
 
62
+ # (see Rules::Builder#scene)
63
+ def scene(name = nil, id: nil, **kwargs, &block)
64
+ rules.build { scene(name, id: id, **kwargs, &block) }
65
+ end
66
+
62
67
  # (see Rules::Builder#script)
63
68
  def script(name = nil, id: nil, **kwargs, &block)
64
69
  rules.build { script(name, id: id, **kwargs, &block) }
@@ -975,5 +980,8 @@ OpenHAB::Core::Items.import_into_global_namespace
975
980
 
976
981
  # Extend `main` with DSL methods
977
982
  singleton_class.include(OpenHAB::DSL)
983
+ # Patch Object to work around https://github.com/openhab/openhab-jruby/issues/4
984
+ Object.extend(OpenHAB::CoreExt::Ruby::Object::ClassMethods)
985
+ OpenHAB::CoreExt::Ruby::Object.instance_variable_set(:@top_self, self)
978
986
 
979
987
  logger.debug "openHAB JRuby Scripting Library Version #{OpenHAB::DSL::VERSION} Loaded"
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.2.0
4
+ version: 5.4.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-05-02 00:00:00.000000000 Z
13
+ date: 2023-06-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -447,6 +447,7 @@ files:
447
447
  - lib/openhab/core/rules/provider.rb
448
448
  - lib/openhab/core/rules/registry.rb
449
449
  - lib/openhab/core/rules/rule.rb
450
+ - lib/openhab/core/rules/tagged_array.rb
450
451
  - lib/openhab/core/script_handling.rb
451
452
  - lib/openhab/core/things.rb
452
453
  - lib/openhab/core/things/channel.rb
@@ -504,6 +505,7 @@ files:
504
505
  - lib/openhab/core_ext/ruby/date_time.rb
505
506
  - lib/openhab/core_ext/ruby/module.rb
506
507
  - lib/openhab/core_ext/ruby/numeric.rb
508
+ - lib/openhab/core_ext/ruby/object.rb
507
509
  - lib/openhab/core_ext/ruby/range.rb
508
510
  - lib/openhab/core_ext/ruby/symbol.rb
509
511
  - lib/openhab/core_ext/ruby/time.rb