openhab-scripting 5.49.0 → 5.51.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: 7cd17ad8e229eaed4db0be72e682f771612f10c59a1fed7612dae537eb5df073
4
- data.tar.gz: a10d086518f1069b0f283f3ba680572f55ce4e5ef372397dde455259330b27ae
3
+ metadata.gz: f53f1018eaf8a1915bbfe5897cbe0ba0985c1ce0497bd8eacb03f7b09aaa2e2c
4
+ data.tar.gz: 458412ea19dc5cfd6e351e4cdd656b14cfd5184f84503cb27b9abfc9aaeec05c
5
5
  SHA512:
6
- metadata.gz: ffd401dad6cd239b69f6c28c394d87fbfc9bbe557f3f080520ff579034170dfaabd84f9fc883d53a1b4c2a97bdffa767964a1526010764c7b28bac427cbc3d0a
7
- data.tar.gz: d8e684891946c9b0fa67ff1b29f0a4ceabc1d1173611ff904993cf39589bc89aad7b882d647bf1eda1045d7f37210d5dc56ea04023bbc4d7638cf2f016f4c1e5
6
+ metadata.gz: 0be40fe6f7188db7f896017a78ec4c42b3259811ae2bf5a63ca3c95f9ce26f8fd414e847610cb586987fcf94f1ef0e7848f621a19c04b38cb060ea4dac163fec
7
+ data.tar.gz: d345bb2045d9c30b4e356454acd499732ac8c0ca6ec588e960d3baccd10706b4e5759d4b5dabe66942476cca9b8fb4041b64d618187c4c7bb47c839a90d445af
@@ -168,7 +168,7 @@ module OpenHAB
168
168
 
169
169
  proxied_self = Proxy.new(self)
170
170
 
171
- return yield(proxied_self) if instance_variable_defined?(:@modifying) && @modifying
171
+ return yield(proxied_self) if proxied_self.instance_variable_get(:@modifying)
172
172
 
173
173
  begin
174
174
  provider = self.provider
@@ -178,15 +178,15 @@ module OpenHAB
178
178
  provider = nil
179
179
  logger.debug { "Forcing modifications to non-managed item #{name}" }
180
180
  end
181
- @modified = false
182
- @modifying = true
181
+ proxied_self.instance_variable_set(:@modified, false)
182
+ proxied_self.instance_variable_set(:@modifying, true)
183
183
 
184
184
  r = yield(proxied_self)
185
185
 
186
- provider&.update(self) if @modified
186
+ provider&.update(self) if proxied_self.instance_variable_get(:@modified)
187
187
  r
188
188
  ensure
189
- @modifying = false
189
+ proxied_self.instance_variable_set(:@modifying, false)
190
190
  end
191
191
  end
192
192
 
@@ -197,7 +197,9 @@ module OpenHAB
197
197
  modify do
198
198
  next if label == value
199
199
 
200
- @modified = true
200
+ proxied_self = Proxy.new(self)
201
+
202
+ proxied_self.instance_variable_set(:@modified, true)
201
203
  set_label(value)
202
204
  end
203
205
  end
@@ -210,7 +212,9 @@ module OpenHAB
210
212
  value = value&.to_s
211
213
  next if category == value
212
214
 
213
- @modified = true
215
+ proxied_self = Proxy.new(self)
216
+
217
+ proxied_self.instance_variable_set(:@modified, true)
214
218
  set_category(value)
215
219
  end
216
220
  end
@@ -234,7 +238,9 @@ module OpenHAB
234
238
  values = DSL::Items::Tags.normalize(*values)
235
239
  next if values.to_set == tags.to_set
236
240
 
237
- @modified = true
241
+ proxied_self = Proxy.new(self)
242
+
243
+ proxied_self.instance_variable_set(:@modified, true)
238
244
  remove_all_tags
239
245
  add_tags(values)
240
246
  end
@@ -582,12 +582,9 @@ module OpenHAB
582
582
  # @return [String]
583
583
  def inspect
584
584
  s = "#<OpenHAB::Core::Items::#{type}Item#{type_details} #{name} #{label.inspect} state=#{raw_state.inspect}"
585
- # @deprecated OH 4.3 Remove if guard when dropping support for OH 4.3
586
- if respond_to?(:last_state)
587
- s += " last_state=#{last_state.inspect}" if last_state
588
- s += " last_state_update=#{last_state_update}" if last_state_update
589
- s += " last_state_change=#{last_state_change}" if last_state_change
590
- end
585
+ s += " last_state=#{last_state.inspect}" if last_state
586
+ s += " last_state_update=#{last_state_update}" if last_state_update
587
+ s += " last_state_change=#{last_state_change}" if last_state_change
591
588
  s += " category=#{category.inspect}" if category
592
589
  s += " tags=#{tags.to_a.inspect}" unless tags.empty?
593
590
  s += " groups=#{group_names}" unless group_names.empty?
@@ -173,18 +173,34 @@ module OpenHAB
173
173
  # Manually trigger the rule
174
174
  #
175
175
  # @param [Object, nil] event The event to pass to the rule's execution blocks.
176
+ # @param [Boolean] async Run the rule asynchronously.
177
+ # When `true`, the method returns right away and the rule continues running in a separate thread.
176
178
  # @param [Boolean] consider_conditions Whether to check the conditions of the called rules.
177
179
  # @param [kwargs] context The context to pass to the conditions and the actions of the rule.
178
- # @return [Hash] A copy of the rule context, including possible return values.
180
+ # @return [Hash, java.util.concurrent.Future<Hash>] A copy of the rule context,
181
+ # including possible return values.
182
+ # When `async` is true, a {java.util.concurrent.Future Future} object is returned
183
+ # that will resolve to the context once the rule has finished executing.
184
+ # To wait for the rule to complete and retrieve the context, call `#get` on the returned Future.
185
+ # @raise [NotImplementedError] if asynchronous execution isn't supported by the `RuleManager` implementation.
179
186
  #
180
- def trigger(event = nil, consider_conditions: false, **context)
187
+ # @since openHAB 5.2 The `async` parameter was added to enable asynchronous rule execution.
188
+ #
189
+ def trigger(event = nil, async: false, consider_conditions: false, **context)
181
190
  event ||= org.openhab.core.automation.events.AutomationEventFactory
182
191
  .createExecutionEvent(uid, nil, "manual")
183
192
  context.transform_keys!(&:to_s)
184
193
  # Unwrap any proxies and pass raw objects (items, things)
185
194
  context.transform_values! { |value| value.is_a?(Delegator) ? value.__getobj__ : value }
186
195
  context["event"] = event
187
- Rules.manager.run_now(uid, consider_conditions, context)
196
+
197
+ return Rules.manager.run_now(uid, consider_conditions, context) unless async
198
+
199
+ begin
200
+ Rules.manager.run_async(uid, consider_conditions, context)
201
+ rescue java.lang.UnsupportedOperationException, NoMethodError
202
+ raise NotImplementedError
203
+ end
188
204
  end
189
205
  alias_method :run, :trigger
190
206
  end
@@ -23,7 +23,7 @@ module OpenHAB
23
23
  #
24
24
  def [](uid)
25
25
  rule = $rules.get(uid)
26
- rule.tagged?(@tag) ? rule : nil
26
+ rule if rule&.tagged?(@tag)
27
27
  end
28
28
  alias_method :include?, :[]
29
29
  alias_method :key?, :[]
data/lib/openhab/core.rb CHANGED
@@ -156,6 +156,42 @@ module OpenHAB
156
156
  ]
157
157
  end.freeze
158
158
  end
159
+
160
+ #
161
+ # Returns the current start level of the openHAB runtime.
162
+ #
163
+ # Start levels represent runtime startup progress as integer values:
164
+ #
165
+ # - `10` - OSGi application start level reached (bundles activated).
166
+ # - `20` - Model entities (items, things, links, persistence config) loaded.
167
+ # - `30` - Item states restored from persistence service, where applicable.
168
+ # - `40` - Rules loaded and parsed; script engine factories available.
169
+ # - `50` - Rule engine executed all "system started" rules and is active.
170
+ # - `70` - User interface is up and running.
171
+ # - `80` - All things have been initialized.
172
+ # - `100` - Startup is fully complete.
173
+ #
174
+ # @example Checking if startup is complete
175
+ # if OpenHAB::Core.startlevel == 100
176
+ # logger.info "openHAB startup complete!"
177
+ # end
178
+ #
179
+ # @example Checking if things are initialized
180
+ # if OpenHAB::Core.startlevel >= 80
181
+ # logger.info "Things are ready."
182
+ # end
183
+ #
184
+ # @return [Integer, nil] The current start level integer, or `nil` if the
185
+ # StartLevelService is unavailable.
186
+ #
187
+ # @see OpenHAB::DSL::Rules::BuilderDSL#on_start on_start rule trigger
188
+ # @see OpenHAB::Core::Events::StartlevelEvent StartlevelEvent
189
+ #
190
+ def startlevel
191
+ @start_level_service ||= OSGi.service("org.openhab.core.service.StartLevelService")
192
+ @start_level_service&.start_level
193
+ end
194
+ alias_method :start_level, :startlevel
159
195
  end
160
196
 
161
197
  import_default_presets unless defined?($ir)
@@ -16,6 +16,8 @@ module OpenHAB
16
16
  # @param [Range] range A range to check
17
17
  # @return [true,false]
18
18
  #
19
+ # @see TimePredicates#within? to check if a time is within a certain distance of another time
20
+ #
19
21
  def between?(min, max = nil)
20
22
  range = if max
21
23
  Range.new(min, max, false)
@@ -13,6 +13,7 @@ module OpenHAB
13
13
  class Instant < java.lang.Object
14
14
  extend Forwardable
15
15
  include Time
16
+ include TimePredicates
16
17
  include Between
17
18
 
18
19
  class << self # rubocop:disable Lint/EmptyClass
@@ -10,6 +10,7 @@ module OpenHAB
10
10
  # Extensions to {java.time.LocalDate}
11
11
  class LocalDate
12
12
  include Time
13
+ include TimePredicates
13
14
  include Between
14
15
  include Ephemeris
15
16
 
@@ -35,6 +35,7 @@ module OpenHAB
35
35
  # end
36
36
  #
37
37
  class LocalTime
38
+ include TimePredicates
38
39
  include Between
39
40
 
40
41
  # @!parse include Time
@@ -9,6 +9,7 @@ module OpenHAB
9
9
 
10
10
  # Extensions to {java.time.Month}
11
11
  class Month
12
+ include TimePredicates
12
13
  include Between
13
14
 
14
15
  # @!parse include Time
@@ -9,6 +9,7 @@ module OpenHAB
9
9
 
10
10
  # Extensions to {java.time.MonthDay}
11
11
  class MonthDay
12
+ include TimePredicates
12
13
  include Between
13
14
  include Ephemeris
14
15
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../time_predicates"
4
+
3
5
  module OpenHAB
4
6
  module CoreExt
5
7
  module Java
@@ -24,6 +26,7 @@ module OpenHAB
24
26
 
25
27
  # @!visibility private
26
28
  def self.included(klass)
29
+ klass.prepend(OpenHAB::CoreExt::TimePredicates)
27
30
  klass.singleton_class.prepend(ClassMethods)
28
31
  klass.remove_method(:==)
29
32
  klass.alias_method(:inspect, :to_s)
@@ -13,6 +13,7 @@ module OpenHAB
13
13
  class ZonedDateTime
14
14
  extend Forwardable
15
15
  include Time
16
+ include TimePredicates
16
17
  include Between
17
18
 
18
19
  class << self # rubocop:disable Lint/EmptyClass
@@ -3,11 +3,14 @@
3
3
  require "forwardable"
4
4
  require "date"
5
5
 
6
+ require_relative "../time_predicates"
7
+
6
8
  # Extensions to Date
7
9
  class Date
8
10
  extend Forwardable
9
11
  include OpenHAB::CoreExt::Between
10
12
  include OpenHAB::CoreExt::Ephemeris
13
+ include OpenHAB::CoreExt::TimePredicates
11
14
 
12
15
  #
13
16
  # Extends {#+} to allow adding a {java.time.temporal.TemporalAmount TemporalAmount}
@@ -3,6 +3,8 @@
3
3
  require "date"
4
4
  require "forwardable"
5
5
 
6
+ require_relative "../time_predicates"
7
+
6
8
  # DateTime inherits from Date, but is more similar to Time semantically.
7
9
  # So it avoid alias_method chain bombs, and to ensure the correct end methods
8
10
  # exist here, we define the important methods from Time here as well.
@@ -12,6 +14,7 @@ class DateTime < Date
12
14
  extend Forwardable
13
15
  include OpenHAB::CoreExt::Between
14
16
  include OpenHAB::CoreExt::Ephemeris
17
+ include OpenHAB::CoreExt::TimePredicates
15
18
 
16
19
  # (see Time#plus_with_temporal)
17
20
  def plus_with_temporal(other)
@@ -2,11 +2,14 @@
2
2
 
3
3
  require "forwardable"
4
4
 
5
+ require_relative "../time_predicates"
6
+
5
7
  # Extensions to Time
6
8
  class Time
7
9
  extend Forwardable
8
10
  include OpenHAB::CoreExt::Between
9
11
  include OpenHAB::CoreExt::Ephemeris
12
+ include OpenHAB::CoreExt::TimePredicates
10
13
 
11
14
  #
12
15
  # @!method +(other)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module CoreExt
5
+ # Predicate helpers for date/time-like objects.
6
+ module TimePredicates
7
+ #
8
+ # Checks whether the object is within a maximum allowable distance (epsilon)
9
+ # of a specific anchor time.
10
+ #
11
+ # @example Check if a timestamp is within 5 minutes of right now
12
+ # event_time.within?(5.minutes)
13
+ #
14
+ # @example Check if a timestamp is within 30 seconds of an explicit execution deadline
15
+ # log_time.within?(30.seconds, of: deadline)
16
+ #
17
+ # @param [java.time.temporal.TemporalAmount, Numeric] epsilon the maximum allowable time difference/distance
18
+ # @param [ZonedDateTime, Time] of the anchor time to compare against (defaults to now)
19
+ # @return [true, false] true if the absolute difference between self and the anchor is less than epsilon
20
+ #
21
+ def within?(epsilon, of: ZonedDateTime.now)
22
+ # Convert times to a common float representation (like epoch seconds) to do the math
23
+ # Or use native Java duration differences if keeping it in the Java ecosystem
24
+ (of - self).to_f.abs < epsilon.to_f
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1512,6 +1512,8 @@ module OpenHAB
1512
1512
  # end
1513
1513
  #
1514
1514
  # @see https://www.openhab.org/docs/configuration/rules-dsl.html#system-based-triggers System based triggers
1515
+ # @see OpenHAB::Core::Events::StartlevelEvent
1516
+ # @see OpenHAB::Core.startlevel
1515
1517
  #
1516
1518
  def on_start(at_level: nil, at_levels: nil, attach: nil)
1517
1519
  levels = Array.wrap(at_level) | Array.wrap(at_levels)
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.49.0"
7
+ VERSION = "5.51.0"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -737,8 +737,8 @@ module OpenHAB
737
737
  # @example
738
738
  # persistence(:influxdb) do
739
739
  # Item1.persist
740
- # Item1.changed_since(1.hour)
741
- # Item1.average_since(12.hours)
740
+ # Item1.changed_since?(1.hour.ago)
741
+ # Item1.average_since(12.hours.ago)
742
742
  # end
743
743
  #
744
744
  # @param [Object] service Persistence service either as a String or a Symbol
@@ -417,10 +417,23 @@ module OpenHAB
417
417
  # end
418
418
  #
419
419
  def spec_log_lines
420
- File.open(log_file, "rb") do |f|
421
- f.seek(@log_index) if @log_index
422
- f.read.split("\n")
420
+ lines = []
421
+
422
+ # Give the underlying Log4j file channel up to ~50ms to flush its buffer to disk
423
+ 5.times do
424
+ lines = File.open(log_file, "rb") do |f|
425
+ f.seek(@log_index) if @log_index
426
+ f.read.split("\n")
427
+ end
428
+
429
+ # If we read lines, break early. If it's still empty, yield execution to the
430
+ # JVM thread scheduler so the file appender thread can finish flushing.
431
+ break unless lines.empty?
432
+
433
+ sleep 0.01
423
434
  end
435
+
436
+ lines
424
437
  end
425
438
 
426
439
  private
@@ -366,6 +366,7 @@ module OpenHAB
366
366
  "org.openhab.core.model.rule.runtime" => nil,
367
367
  "org.openhab.core.model.rule" => nil,
368
368
  "org.openhab.core.model.sitemap.runtime" => nil,
369
+ "org.openhab.core.ui" => nil,
369
370
  "org.openhab.core.voice" => nil
370
371
  }.freeze
371
372
  private_constant :BLOCKED_COMPONENTS
@@ -805,11 +806,14 @@ module OpenHAB
805
806
  <f:feature>openhab-core-model-script</f:feature>
806
807
  <f:feature>openhab-core-model-sitemap</f:feature>
807
808
  <f:feature>openhab-core-model-thing</f:feature>
809
+ <f:feature>openhab-core-model-yaml</f:feature>
808
810
  <f:feature>openhab-core-storage-json</f:feature>
809
811
  <f:feature>openhab-core-ui-icon</f:feature>
810
812
  <f:feature>openhab-transport-http</f:feature>
811
813
  <f:feature prerequisite="true">wrapper</f:feature>
812
814
  <f:bundle>mvn:org.openhab.core.bundles/org.openhab.core.karaf/#{version}</f:bundle>
815
+ <!-- openhab-core-model-yaml imports org.openhab.core.ui.components since OH 5.2 -->
816
+ <f:bundle>mvn:org.openhab.core.bundles/org.openhab.core.ui/#{version}</f:bundle>
813
817
  </feature>
814
818
  </replacement>
815
819
  </featureReplacements>
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.49.0
4
+ version: 5.51.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
@@ -11,6 +11,20 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bigdecimal
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '4.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '4.0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: bundler
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -31,6 +45,34 @@ dependencies:
31
45
  - - "<"
32
46
  - !ruby/object:Gem::Version
33
47
  version: '5.0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: csv
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: irb
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.4'
34
76
  - !ruby/object:Gem::Dependency
35
77
  name: marcel
36
78
  requirement: !ruby/object:Gem::Requirement
@@ -255,6 +297,7 @@ files:
255
297
  - lib/openhab/core_ext/ruby/range.rb
256
298
  - lib/openhab/core_ext/ruby/symbol.rb
257
299
  - lib/openhab/core_ext/ruby/time.rb
300
+ - lib/openhab/core_ext/time_predicates.rb
258
301
  - lib/openhab/dsl.rb
259
302
  - lib/openhab/dsl/config_description/builder.rb
260
303
  - lib/openhab/dsl/debouncer.rb
@@ -360,7 +403,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
360
403
  - !ruby/object:Gem::Version
361
404
  version: '0'
362
405
  requirements: []
363
- rubygems_version: 4.0.15
406
+ rubygems_version: 4.0.18
364
407
  specification_version: 4
365
408
  summary: JRuby Helper Libraries for openHAB Scripting
366
409
  test_files: []