openhab-scripting 5.16.0 → 5.17.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: 66607fb79de6b8b718ddd8cc5cc10662809001e67915074b44360ba9f6408d31
4
- data.tar.gz: e21976073a7323b4e8bfe05a09e8959472d950ad28df26534371c857fe64699f
3
+ metadata.gz: ecc05f177e95b3a962f2b1fac6f924c5af5d6c49ed8a7e38d896c03417fe9e23
4
+ data.tar.gz: 408fa59899bb838caa9a6f3fc80ef82a4051c03fc590249ab53e0a098c5f335d
5
5
  SHA512:
6
- metadata.gz: 815f05142db0071b36cd45b9f9e81c1c033cf759823150066f2c65ec4f5eb61fdf9b1bf4dbc0e8125adf3535eb9e83b71fbbf401c2e6f1a716838fe6f37cdd29
7
- data.tar.gz: 4fe2bd7469d2d4489bd41ee9c62c6b4e7d53e6350e095c895b936813582d89e088b772bb0a44fde82aaecbfe5ff1c3fac320505001e24d0ac4519646abac5889
6
+ metadata.gz: ccbc0e426427d262cd1f2a5ed671979f5644b4c5b0da5ff34958254de6221283a9420e2b3c45384ac5aafc7feeffd41fa54740f76c4d99ccaa8adba207c32d52
7
+ data.tar.gz: 9f9a5f3b120a838f151a1f8edf5e1400f1df0a183cef5a47b921bc661889231c1b186ce2830f8cf7349ab3f89b166de5e1ffc89675628dba21799740b9029cc6
@@ -74,7 +74,7 @@ module OpenHAB
74
74
  ruby2_keywords def method_missing(method, *args)
75
75
  return super unless args.empty? && !block_given?
76
76
 
77
- logger.trace("method missing, performing openHAB Lookup for: #{method}")
77
+ logger.trace { "method missing, performing openHAB Lookup for: #{method}" }
78
78
  EntityLookup.lookup_entity(method,
79
79
  create_dummy_items: self.class.respond_to?(:create_dummy_items?) &&
80
80
  self.class.create_dummy_items?) || super
@@ -82,7 +82,7 @@ module OpenHAB
82
82
 
83
83
  # @!visibility private
84
84
  def respond_to_missing?(method, *)
85
- logger.trace("Checking if openHAB entities exist for #{method}")
85
+ logger.trace { "Checking if openHAB entities exist for #{method}" }
86
86
  EntityLookup.lookup_entity(method) || super
87
87
  end
88
88
 
@@ -121,14 +121,14 @@ module OpenHAB
121
121
  # @return [Things::Thing, nil]
122
122
  #
123
123
  def lookup_thing(uid)
124
- logger.trace("Looking up thing '#{uid}'")
124
+ logger.trace { "Looking up thing '#{uid}'" }
125
125
  uid = uid.to_s if uid.is_a?(Symbol)
126
126
 
127
127
  uid = Things::ThingUID.new(uid) unless uid.is_a?(Things::ThingUID)
128
128
  thing = $things.get(uid)
129
129
  return unless thing
130
130
 
131
- logger.trace("Retrieved Thing(#{thing}) from registry for uid: #{uid}")
131
+ logger.trace { "Retrieved Thing(#{thing}) from registry for uid: #{uid}" }
132
132
  Things::Proxy.new(thing)
133
133
  end
134
134
 
@@ -164,7 +164,7 @@ module OpenHAB
164
164
  # @return [Item, nil]
165
165
  #
166
166
  def lookup_item(name)
167
- logger.trace("Looking up item '#{name}'")
167
+ logger.trace { "Looking up item '#{name}'" }
168
168
  name = name.to_s if name.is_a?(Symbol)
169
169
  item = $ir.get(name)
170
170
  Items::Proxy.new(item) unless item.nil?
@@ -2,21 +2,21 @@
2
2
 
3
3
  require_relative "item_state_event"
4
4
 
5
+ # @deprecated OH3.4 guard only needed in OH 3.4
6
+ return unless OpenHAB::Core.version >= OpenHAB::Core::V4_0
7
+
5
8
  module OpenHAB
6
9
  module Core
7
10
  module Events
8
- # @deprecated OH3.4 if guard only needed in OH 3.4
9
- if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
10
- java_import org.openhab.core.items.events.ItemStateUpdatedEvent
11
+ java_import org.openhab.core.items.events.ItemStateUpdatedEvent
11
12
 
12
- #
13
- # {AbstractEvent} sent when an item's state has updated.
14
- #
15
- # @since openHAB 4.0
16
- #
17
- class ItemStateUpdatedEvent < ItemEvent
18
- include ItemState
19
- end
13
+ #
14
+ # {AbstractEvent} sent when an item's state has updated.
15
+ #
16
+ # @since openHAB 4.0
17
+ #
18
+ class ItemStateUpdatedEvent < ItemEvent
19
+ include ItemState
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @deprecated OH4.0 guard not needed in OH 4.1
4
+ return unless OpenHAB::Core.version >= OpenHAB::Core::V4_1
5
+
6
+ module OpenHAB
7
+ module Core
8
+ module Events
9
+ java_import org.openhab.core.items.events.ItemTimeSeriesUpdatedEvent
10
+
11
+ #
12
+ # {AbstractEvent} sent when an item received a time series update.
13
+ #
14
+ # @!attribute [r] time_series
15
+ # @return [TimeSeries] The updated time series.
16
+ #
17
+ # @since openHAB 4.1
18
+ # @see DSL::Rules::BuilderDSL#time_series_updated #time_series_updated rule trigger
19
+ #
20
+ class ItemTimeSeriesUpdatedEvent < ItemEvent; end
21
+ end
22
+ end
23
+ end
@@ -1,46 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @deprecated OH3.4 this guard is not needed on OH4
4
+ return unless OpenHAB::Core.version >= OpenHAB::Core::V4_0
5
+
3
6
  module OpenHAB
4
7
  module Core
5
8
  module Events
6
- # @deprecated OH3.4 this guard is not needed on OH4
7
- if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
8
- java_import org.openhab.core.automation.events.TimerEvent
9
+ java_import org.openhab.core.automation.events.TimerEvent
9
10
 
11
+ #
12
+ # Adds methods to core openHAB TimerEvent to make it more natural in Ruby
13
+ #
14
+ # This event can be triggered by a `DateTimeTrigger`, `cron`, or `TimeOfDay` trigger.
15
+ #
16
+ # @since openHAB 4.0
17
+ #
18
+ class TimerEvent < AbstractEvent
10
19
  #
11
- # Adds methods to core openHAB TimerEvent to make it more natural in Ruby
20
+ # @!attribute [r] cron_expression
21
+ # @return [String, nil] The cron expression that triggered this event.
22
+ # `nil` when this event wasn't triggered by a cron trigger.
12
23
  #
13
- # This event can be triggered by a `DateTimeTrigger`, `cron`, or `TimeOfDay` trigger.
24
+ def cron_expression
25
+ payload&.[](:cronExpression)
26
+ end
27
+
14
28
  #
15
- # @since openHAB 4.0
29
+ # @!attribute [r] item
30
+ # @return [Item, nil] The DateTime item that triggered this event.
31
+ # `nil` when this event wasn't triggered by a DateTimeItem trigger.
16
32
  #
17
- class TimerEvent < AbstractEvent
18
- #
19
- # @!attribute [r] cron_expression
20
- # @return [String, nil] The cron expression that triggered this event.
21
- # `nil` when this event wasn't triggered by a cron trigger.
22
- #
23
- def cron_expression
24
- payload&.[](:cronExpression)
25
- end
26
-
27
- #
28
- # @!attribute [r] item
29
- # @return [Item, nil] The DateTime item that triggered this event.
30
- # `nil` when this event wasn't triggered by a DateTimeItem trigger.
31
- #
32
- def item
33
- payload&.[](:itemName)&.then { |item_name| EntityLookup.lookup_item(item_name) }
34
- end
33
+ def item
34
+ payload&.[](:itemName)&.then { |item_name| EntityLookup.lookup_item(item_name) }
35
+ end
35
36
 
36
- #
37
- # @!attribute [r] time
38
- # @return [LocalTime, nil] The configured time for this TimeOfDay trigger event.
39
- # `nil` when this event wasn't triggered by a TimeOfDay trigger.
40
- #
41
- def time
42
- payload&.[](:time)&.then { |time| LocalTime.parse(time) }
43
- end
37
+ #
38
+ # @!attribute [r] time
39
+ # @return [LocalTime, nil] The configured time for this TimeOfDay trigger event.
40
+ # `nil` when this event wasn't triggered by a TimeOfDay trigger.
41
+ #
42
+ def time
43
+ payload&.[](:time)&.then { |time| LocalTime.parse(time) }
44
44
  end
45
45
  end
46
46
  end
@@ -207,6 +207,18 @@ module OpenHAB
207
207
  type.to_s
208
208
  end
209
209
 
210
+ #
211
+ # @method time_series=(time_series)
212
+ # Set a new time series.
213
+ #
214
+ # This will trigger a {DSL::Rules::BuilderDSL#time_series_updated time_series_updated} event.
215
+ #
216
+ # @param [Core::Types::TimeSeries] time_series New time series to set.
217
+ # @return [void]
218
+ #
219
+ # @since openHAB 4.1
220
+ #
221
+
210
222
  #
211
223
  # Defers notifying openHAB of modifications to multiple attributes until the block is complete.
212
224
  #
@@ -7,7 +7,7 @@ module OpenHAB
7
7
  module Items
8
8
  # Mixin for implementing type coercion for number-like items
9
9
  module NumericItem
10
- %i[positive? negative? zero?].each do |predicate|
10
+ %i[positive? negative? zero? nonzero?].each do |predicate|
11
11
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
12
12
  def #{predicate} # def positive?
13
13
  return false unless state? # return false unless state?
@@ -83,9 +83,7 @@ module OpenHAB
83
83
  updated_since?])
84
84
 
85
85
  # @deprecated OH3.4 - in openHAB 4, just add :get_all_states_since and freeze the list above
86
- if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
87
- PERSISTENCE_METHODS << :get_all_states_since
88
- end
86
+ PERSISTENCE_METHODS << :get_all_states_since if OpenHAB::Core.version >= OpenHAB::Core::V4_0
89
87
  PERSISTENCE_METHODS.freeze
90
88
 
91
89
  private_constant :QUANTITY_METHODS, :PERSISTENCE_METHODS
@@ -386,7 +384,7 @@ module OpenHAB
386
384
  alias_method :state_changes_since, :count_state_changes_since
387
385
  alias_method :state_changes_between, :count_state_changes_between
388
386
  # @deprecated OH 3.4 - if guard is unnecessary in OH4
389
- if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
387
+ if OpenHAB::Core.version >= OpenHAB::Core::V4_0
390
388
  alias_method :all_states_since, :get_all_states_since
391
389
  alias_method :all_states_between, :get_all_states_between
392
390
  end
@@ -21,15 +21,13 @@ module OpenHAB
21
21
  # @return [Item] Item from registry, nil if item missing or requested item is a Group Type
22
22
  def [](name)
23
23
  EntityLookup.lookup_item(name)
24
- rescue org.openhab.core.items.ItemNotFoundException
25
- nil
26
24
  end
27
25
 
28
26
  # Returns true if the given item name exists
29
27
  # @param name [String] Item name to check
30
28
  # @return [true,false] true if the item exists, false otherwise
31
29
  def key?(name)
32
- !$ir.getItems(name).empty?
30
+ !$ir.get(name).nil?
33
31
  end
34
32
  alias_method :include?, :key?
35
33
  # @deprecated
@@ -226,10 +226,7 @@ module OpenHAB
226
226
 
227
227
  # @deprecated OH3.4 - the Property tag had an ID of "MeasurementProperty" in OH3.4.
228
228
  # This was corrected in OH4.
229
- # Make sure we compare against pre-release versions
230
- if id == "Property" && Gem::Version.new(Core::VERSION) < Gem::Version.new("4.0.0.M1")
231
- id = "MeasurementProperty"
232
- end
229
+ id = "MeasurementProperty" if id == "Property" && Core.version < Core::V4_0
233
230
 
234
231
  # @deprecated OH3.4 missing registry
235
232
  if Provider.registry
@@ -15,7 +15,12 @@ module OpenHAB
15
15
  include Singleton
16
16
 
17
17
  class Profile
18
- include org.openhab.core.thing.profiles.StateProfile
18
+ # @deprecated OH 4.0 only include TimeSeriesProfile in OH 4.1, because it extends StateProfile
19
+ if OpenHAB::Core.version >= OpenHAB::Core::V4_1
20
+ include org.openhab.core.thing.profiles.TimeSeriesProfile
21
+ else
22
+ include org.openhab.core.thing.profiles.StateProfile
23
+ end
19
24
 
20
25
  def initialize(callback, context, uid, thread_locals, block)
21
26
  unless callback.class.ancestors.include?(Things::ProfileCallback)
@@ -64,6 +69,14 @@ module OpenHAB
64
69
  process_event(:state_from_item, state: state)
65
70
  end
66
71
 
72
+ # @deprecated OH 4.0 guard is only needed for < OH 4.1
73
+ if OpenHAB::Core.version >= OpenHAB::Core::V4_1
74
+ # @!visibility private
75
+ def onTimeSeriesFromHandler(time_series)
76
+ process_event(:time_series_from_handler, time_series: time_series)
77
+ end
78
+ end
79
+
67
80
  private
68
81
 
69
82
  def process_event(event, **params)
@@ -77,6 +90,8 @@ module OpenHAB
77
90
  params[:channel_uid] = @callback.link.linked_uid
78
91
  params[:state] ||= nil
79
92
  params[:command] ||= nil
93
+ # @deprecated OH 4.0 guard is only needed for < OH 4.1
94
+ params[:time_series] ||= nil if OpenHAB::Core.version >= OpenHAB::Core::V4_1
80
95
 
81
96
  kwargs = {}
82
97
  @block.parameters.each do |(param_type, name)|
@@ -132,7 +132,9 @@ module OpenHAB
132
132
  builder = DSL::Sitemaps::Builder.new(self, builder_proxy, update: update)
133
133
  if block.arity == 1
134
134
  builder_proxy.__setobj__(builder)
135
- yield builder_proxy
135
+ DSL::ThreadLocal.thread_local(openhab_create_dummy_items: true) do
136
+ yield builder_proxy
137
+ end
136
138
  else
137
139
  builder.instance_eval(&block)
138
140
  end
@@ -58,7 +58,7 @@ module OpenHAB
58
58
  end
59
59
 
60
60
  # @deprecated OH3.4 this whole section is not needed in OH4+. Also see Thing#config_eql?
61
- if Gem::Version.new(Core::VERSION) < Gem::Version.new("4.0.0")
61
+ if Core.version < Core::V4_0
62
62
  # @!visibility private
63
63
  module ChannelComparable
64
64
  # @!visibility private
@@ -40,6 +40,11 @@ module OpenHAB
40
40
  state = link.item.format_update(state)
41
41
  super(state)
42
42
  end
43
+
44
+ # @!method send_time_series(time_series)
45
+ # Send a time series to the framework.
46
+ # @param [TimeSeries] time_series
47
+ # @since openHAB 4.1
43
48
  end
44
49
  end
45
50
  end
@@ -165,6 +165,12 @@ module OpenHAB
165
165
  ThingType.registry.get_thing_type(thing_type_uid)
166
166
  end
167
167
 
168
+ # @!attribute [r] bridge
169
+ # @return [Thing, nil]
170
+ def bridge
171
+ bridge_uid && EntityLookup.lookup_thing(bridge_uid)
172
+ end
173
+
168
174
  # @return [String]
169
175
  def inspect
170
176
  r = "#<OpenHAB::Core::Things::Thing #{uid}"
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @deprecated OH4.0 this guard is not needed on OH4.1
4
+ return unless OpenHAB::Core.version >= OpenHAB::Core::V4_1
5
+
6
+ require "forwardable"
7
+
8
+ module OpenHAB
9
+ module Core
10
+ module Types
11
+ TimeSeries = org.openhab.core.types.TimeSeries
12
+
13
+ #
14
+ # {TimeSeries} is used to transport a set of states together with their timestamp.
15
+ #
16
+ # The states are sorted chronologically. The entries can be accessed like an array.
17
+ #
18
+ # @since openHAB 4.1
19
+ #
20
+ # @example
21
+ # time_series = TimeSeries.new # defaults to :add policy
22
+ # .add(Time.at(2), DecimalType.new(2))
23
+ # .add(Time.at(1), DecimalType.new(1))
24
+ # .add(Time.at(3), DecimalType.new(3))
25
+ # logger.info "first entry: #{time_series.first.state}" # => 1
26
+ # logger.info "last entry: #{time_series.last.state}" # => 3
27
+ # logger.info "second entry: #{time_series[1].state}" # => 2
28
+ # logger.info "sum: #{time_series.sum(&:state)}" # => 6
29
+ #
30
+ # @see DSL::Rules::BuilderDSL#time_series_updated #time_series_updated rule trigger
31
+ #
32
+ class TimeSeries
33
+ extend Forwardable
34
+
35
+ # @!attribute [r] policy
36
+ # Returns the persistence policy of this series.
37
+ # @see org.openhab.core.types.TimeSeries#getPolicy()
38
+ # @return [org.openhab.core.types.TimeSeries.Policy]
39
+
40
+ # @!attribute [r] begin
41
+ # Returns the timestamp of the first element in this series.
42
+ # @return [Instant]
43
+
44
+ # @!attribute [r] end
45
+ # Returns the timestamp of the last element in this series.
46
+ # @return [Instant]
47
+
48
+ # @!attribute [r] size
49
+ # Returns the number of elements in this series.
50
+ # @return [Integer]
51
+
52
+ #
53
+ # Create a new instance of TimeSeries
54
+ #
55
+ # @param [:add, :replace, org.openhab.core.types.TimeSeries.Policy] policy
56
+ # The persistence policy of this series.
57
+ #
58
+ def initialize(policy = :replace)
59
+ policy = Policy.value_of(policy.to_s.upcase) if policy.is_a?(Symbol)
60
+ super
61
+ end
62
+
63
+ # Returns true if the series' policy is `ADD`.
64
+ # @return [true,false]
65
+ def add?
66
+ policy == Policy::ADD
67
+ end
68
+
69
+ # Returns true if the series' policy is `REPLACE`.
70
+ # @return [true,false]
71
+ def replace?
72
+ policy == Policy::REPLACE
73
+ end
74
+
75
+ # @!visibility private
76
+ def inspect
77
+ "#<OpenHAB::Core::Types::TimeSeries " \
78
+ "policy=#{policy} " \
79
+ "begin=#{self.begin} " \
80
+ "end=#{self.end} " \
81
+ "size=#{size}>"
82
+ end
83
+
84
+ #
85
+ # Returns the content of this series.
86
+ # @return [Array<org.openhab.core.types.TimeSeries.Entry>]
87
+ #
88
+ def states
89
+ get_states.to_array.to_a.freeze
90
+ end
91
+
92
+ # rename raw methods so we can overwrite them
93
+ # @!visibility private
94
+ alias_method :add_instant, :add
95
+
96
+ #
97
+ # Adds a new element to this series.
98
+ #
99
+ # Elements can be added in an arbitrary order and are sorted chronologically.
100
+ #
101
+ # @note This method returns self so it can be chained, unlike the Java version.
102
+ #
103
+ # @param [Instant, #to_zoned_date_time, #to_instant] instant An instant for the given state.
104
+ # @param [State] state The State at the given timestamp.
105
+ # @return [self]
106
+ #
107
+ def add(instant, state)
108
+ instant = instant.to_zoned_date_time if instant.respond_to?(:to_zoned_date_time)
109
+ instant = instant.to_instant if instant.respond_to?(:to_instant)
110
+ add_instant(instant, state)
111
+ self
112
+ end
113
+
114
+ # any method that exists on Array gets forwarded to states
115
+ delegate (Array.instance_methods - instance_methods) => :states
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ TimeSeries = OpenHAB::Core::Types::TimeSeries unless Object.const_defined?(:TimeSeries)
data/lib/openhab/core.rb CHANGED
@@ -7,7 +7,20 @@ module OpenHAB
7
7
  # @return [String]
8
8
  VERSION = org.openhab.core.OpenHAB.version.freeze
9
9
 
10
- raise "`openhab-scripting` requires openHAB >= 3.4.0" unless Gem::Version.new(VERSION) >= Gem::Version.new("3.4.0")
10
+ # @!visibility private
11
+ V4_0 = Gem::Version.new("4.0.0").freeze
12
+ # @!visibility private
13
+ V4_1 = Gem::Version.new("4.1.0").freeze
14
+ # @!visibility private
15
+ V4_2 = Gem::Version.new("4.2.0").freeze
16
+
17
+ # @return [Gem::Version] Returns the current openHAB version as a Gem::Version object
18
+ # @!visibility private
19
+ def self.version
20
+ @version ||= Gem::Version.new(VERSION).freeze
21
+ end
22
+
23
+ raise "`openhab-scripting` requires openHAB >= 3.4.0" unless version >= Gem::Version.new("3.4.0")
11
24
 
12
25
  # @return [Integer] Number of seconds to wait between checks for automation manager
13
26
  CHECK_DELAY = 10
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module CoreExt
5
+ module Java
6
+ java_import java.time.Instant
7
+
8
+ # Extensions to {java.time.Instant}
9
+ class Instant < java.lang.Object; end
10
+ end
11
+ end
12
+ end
13
+
14
+ Instant = OpenHAB::CoreExt::Java::Instant unless Object.const_defined?(:Instant)
@@ -1089,7 +1089,7 @@ module OpenHAB
1089
1089
  raise ArgumentError, "items must be an Item, GroupItem::Members, Thing, or ThingUID"
1090
1090
  end
1091
1091
 
1092
- logger.trace("Creating changed trigger for entity(#{item}), to(#{to.inspect}), from(#{from.inspect})")
1092
+ logger.trace { "Creating changed trigger for entity(#{item}), to(#{to.inspect}), from(#{from.inspect})" }
1093
1093
 
1094
1094
  Array.wrap(from).each do |from_state|
1095
1095
  Array.wrap(to).each do |to_state|
@@ -1381,7 +1381,7 @@ module OpenHAB
1381
1381
  levels.each do |level|
1382
1382
  logger.warn "Rule engine doesn't start until start level 40" if level < 40
1383
1383
  config = { startlevel: level }
1384
- logger.trace("Creating a SystemStartlevelTrigger with startlevel=#{level}")
1384
+ logger.trace { "Creating a SystemStartlevelTrigger with startlevel=#{level}" }
1385
1385
  Triggers::Trigger.new(rule_triggers: @rule_triggers)
1386
1386
  .append_trigger(type: "core.SystemStartlevelTrigger", config: config, attach: attach)
1387
1387
  end
@@ -1480,7 +1480,7 @@ module OpenHAB
1480
1480
  raise ArgumentError, "items must be an Item or GroupItem::Members"
1481
1481
  end
1482
1482
  commands.each do |cmd|
1483
- logger.trace "Creating received command trigger for items #{item.inspect} and commands #{cmd.inspect}"
1483
+ logger.trace { "Creating received command trigger for items #{item.inspect} and commands #{cmd.inspect}" }
1484
1484
 
1485
1485
  command_trigger.trigger(item: item, command: cmd, attach: attach)
1486
1486
  end
@@ -1699,7 +1699,7 @@ module OpenHAB
1699
1699
  # end
1700
1700
  #
1701
1701
  def trigger(type, attach: nil, **configuration)
1702
- logger.trace("Creating trigger (#{type}) with configuration(#{configuration})")
1702
+ logger.trace { "Creating trigger (#{type}) with configuration(#{configuration})" }
1703
1703
  Triggers::Trigger.new(rule_triggers: @rule_triggers)
1704
1704
  .append_trigger(type: type, config: configuration, attach: attach)
1705
1705
  end
@@ -1802,13 +1802,48 @@ module OpenHAB
1802
1802
  raise ArgumentError, "items must be an Item, GroupItem::Members, Thing, or ThingUID"
1803
1803
  end
1804
1804
 
1805
- logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
1805
+ logger.trace { "Creating updated trigger for item(#{item}) to(#{to})" }
1806
1806
  [to].flatten.map do |to_state|
1807
1807
  updated.trigger(item: item, to: to_state, attach: attach)
1808
1808
  end
1809
1809
  end.flatten
1810
1810
  end
1811
1811
 
1812
+ #
1813
+ # Creates a time series updated trigger
1814
+ #
1815
+ # The `event` passed to run blocks will be a {OpenHAB::Core::Events::ItemTimeSeriesUpdatedEvent}
1816
+ #
1817
+ # @param [Item] items Items to create trigger for.
1818
+ # @param [Object] attach Object to be attached to the trigger.
1819
+ # @return [void]
1820
+ #
1821
+ # @since openHAB 4.1
1822
+ # @see Core::Types::TimeSeries TimeSeries
1823
+ # @see Core::Items::GenericItem#time_series= GenericItem#time_series=
1824
+ #
1825
+ # @example
1826
+ # rule 'Execute rule when item time series is updated' do
1827
+ # time_series_updated MyItem
1828
+ # run do |event|
1829
+ # logger.info("Item time series updated: #{event.item.name}.")
1830
+ # logger.info(" TimeSeries size: #{event.time_series.size}, policy: #{event.time_series.policy}")
1831
+ # event.time_series.each do |entry|
1832
+ # timestamp = entry.timestamp.to_time.strftime("%Y-%m-%d %H:%M:%S")
1833
+ # logger.info(" Entry: #{timestamp}: State: #{entry.state}")
1834
+ # end
1835
+ # end
1836
+ # end
1837
+ #
1838
+ def time_series_updated(*items, attach: nil)
1839
+ @ruby_triggers << [:time_series_updated, items]
1840
+ items.map do |item|
1841
+ raise ArgumentError, "items must be an Item or GroupItem::Members" unless item.is_a?(Core::Items::Item)
1842
+
1843
+ event("openhab/items/#{item.name}/timeseriesupdated", types: "ItemTimeSeriesUpdatedEvent", attach: attach)
1844
+ end
1845
+ end
1846
+
1812
1847
  #
1813
1848
  # Create a trigger to watch a path
1814
1849
  #
@@ -1987,7 +2022,7 @@ module OpenHAB
1987
2022
  elsif !execution_blocks?
1988
2023
  logger.warn "Rule '#{uid}' has no execution blocks, not creating rule"
1989
2024
  elsif !enabled
1990
- logger.trace "Rule '#{uid}' marked as disabled, not creating rule."
2025
+ logger.trace { "Rule '#{uid}' marked as disabled, not creating rule." }
1991
2026
  else
1992
2027
  return true
1993
2028
  end
@@ -2024,7 +2059,7 @@ module OpenHAB
2024
2059
  duplicate_index += 1
2025
2060
  rule.uid = "#{base_uid} (#{duplicate_index})"
2026
2061
  end
2027
- logger.trace("Adding rule: #{rule}")
2062
+ logger.trace { "Adding rule: #{rule}" }
2028
2063
  unmanaged_rule = Core.automation_manager.add_unmanaged_rule(rule)
2029
2064
  provider.add(unmanaged_rule)
2030
2065
  unmanaged_rule
@@ -64,6 +64,8 @@ module OpenHAB
64
64
  infer_rule_name_from_item_registry_trigger(trigger)
65
65
  when :thing_added, :thing_removed, :thing_updated
66
66
  infer_rule_name_from_thing_trigger(trigger)
67
+ when :time_series_updated
68
+ infer_rule_name_from_time_series_trigger(items)
67
69
  when :on_start
68
70
  infer_rule_name_from_on_start_trigger(items)
69
71
  end
@@ -136,6 +138,11 @@ module OpenHAB
136
138
  }[trigger]
137
139
  end
138
140
 
141
+ # formulate a readable rule name from a time series updated trigger
142
+ def infer_rule_name_from_time_series_trigger(items)
143
+ "#{format_array(items.map(&:name))} time series updated"
144
+ end
145
+
139
146
  # formulate a readable rule name from an on_start trigger
140
147
  def infer_rule_name_from_on_start_trigger(levels)
141
148
  levels = levels.map { |level| "#{level} (#{start_level_description(level)})" }
@@ -20,29 +20,46 @@ module OpenHAB
20
20
  class << self
21
21
  # @!visibility private
22
22
  # @!macro def_terse_rule
23
- # @!method $1(*args, name :nil, id: nil, on_load: false, **kwargs, &block)
23
+ # @!method $1(
24
+ # *args,
25
+ # id: nil,
26
+ # name :nil,
27
+ # description: nil,
28
+ # tag: nil,
29
+ # tags: nil,
30
+ # on_load: false,
31
+ # **kwargs,
32
+ # &block)
24
33
  # Create a new rule with a $1 trigger.
25
- # @param name [String] The name for the rule.
26
34
  # @param id [String] The ID for the rule.
35
+ # @param name [String] The name for the rule.
36
+ # @param description [String, nil] The description for the rule.
37
+ # @param tag [String, Symbol, Semantics::Tag, Array<String, Symbol, Semantics::Tag>, nil]
38
+ # Tags to assign to the script
39
+ # @param tags [String, Symbol, Semantics::Tag, Array<String, Symbol, Semantics::Tag>, nil]
40
+ # Fluent alias for `tag`
27
41
  # @param on_load [true, false] If the rule should _also_ trigger immediately when the script loads.
28
42
  # @yield The execution block for the rule.
29
43
  # @return [void]
30
44
  # @see BuilderDSL#$1
31
45
  def def_terse_rule(trigger)
32
46
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
33
- def #{trigger}(*args, name: nil, id: nil, on_load: false, **kwargs, &block) # def changed(*args, name: nil, id: nil, on_load: false, **kwargs, &block)
34
- raise ArgumentError, "Block is required" unless block # raise ArgumentError, "Block is required" unless block
35
- #
36
- id ||= NameInference.infer_rule_id_from_block(block) # id ||= NameInference.infer_rule_id_from_block(block)
37
- script = block.source rescue nil # script = block.source rescue nil
38
- caller_binding = block.binding # caller_binding = block.binding
39
- rule name, id: id, script: script, binding: caller_binding do # rule name, id: id, script: script, binding: caller_binding do
40
- self.on_load if on_load # self.on_load if on_load
41
- #{trigger}(*args, **kwargs) # changed(*args, **kwargs)
42
- run(&block) # run(&block)
43
- end # end
44
- end # end
45
- module_function #{trigger.inspect} # module_function :changed
47
+ def #{trigger}(*args, id: nil, name: nil, description: nil, # def changed(*args, id: nil, name: nil, description: nil,
48
+ tag: nil, tags: nil, on_load: false, **kwargs, &block) # tag: nil, tags: nil, on_load: false, **kwargs, &block)
49
+ raise ArgumentError, "Block is required" unless block # raise ArgumentError, "Block is required" unless block
50
+ #
51
+ id ||= NameInference.infer_rule_id_from_block(block) # id ||= NameInference.infer_rule_id_from_block(block)
52
+ script = block.source rescue nil # script = block.source rescue nil
53
+ caller_binding = block.binding # caller_binding = block.binding
54
+ rule name, id: id, script: script, binding: caller_binding do # rule name, id: id, script: script, binding: caller_binding do
55
+ self.on_load if on_load # self.on_load if on_load
56
+ self.description(description) if description # self.description(description) if description
57
+ self.tags(*Array.wrap(tag), *Array.wrap(tags)) # self.tags(*Array.wrap(tag), *Array.wrap(tags))
58
+ #{trigger}(*args, **kwargs) # changed(*args, **kwargs)
59
+ run(&block) # run(&block)
60
+ end # end
61
+ end # end
62
+ module_function #{trigger.inspect} # module_function :changed
46
63
  RUBY
47
64
  end
48
65
  end
@@ -12,7 +12,8 @@ module OpenHAB
12
12
  #
13
13
  class Cron < Trigger
14
14
  # Trigger ID for Cron Triggers
15
- CRON_TRIGGER_MODULE_ID = if Gem::Version.new(OpenHAB::Core::VERSION) >= Gem::Version.new("4.0.0")
15
+ # @deprecated OH 3.4
16
+ CRON_TRIGGER_MODULE_ID = if OpenHAB::Core.version >= OpenHAB::Core::V4_0
16
17
  "timer.GenericCronTrigger"
17
18
  else
18
19
  # @deprecated OH3.4 We need to use a custom CronTrigger handler
@@ -211,7 +212,7 @@ module OpenHAB
211
212
  #
212
213
  def trigger(config:, attach:)
213
214
  # @deprecated OH3.4 needs a custom CronTriggerHandlerFactory
214
- if Gem::Version.new(OpenHAB::Core::VERSION) < Gem::Version.new("4.0.0")
215
+ if OpenHAB::Core.version < OpenHAB::Core::V4_0
215
216
  CronHandler::CronTriggerHandlerFactory.instance # ensure it's registered
216
217
  end
217
218
  append_trigger(type: CRON_TRIGGER_MODULE_ID, config: config, attach: attach)
@@ -1,120 +1,118 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @deprecated OH3.4 this module is not needed in OH4+
4
- if Gem::Version.new(OpenHAB::Core::VERSION) < Gem::Version.new("4.0.0")
5
-
6
- require "singleton"
7
-
8
- require_relative "cron"
9
-
10
- module OpenHAB
11
- module DSL
12
- module Rules
13
- module Triggers
14
- # @!visibility private
15
- #
16
- # Cron trigger handler that provides trigger ID
17
- #
18
- module CronHandler
19
- # Cron Trigger Handler that provides trigger IDs
20
- # Unfortunatly because the CronTriggerHandler in openHAB core is marked internal
21
- # the entire thing must be recreated here
22
- class CronTriggerHandler < org.openhab.core.automation.handler.BaseTriggerModuleHandler
23
- include org.openhab.core.scheduler.SchedulerRunnable
24
- include org.openhab.core.automation.handler.TimeBasedTriggerHandler
25
-
26
- # Provides access to protected fields
27
- field_accessor :callback
28
-
29
- # Creates a new CronTriggerHandler
30
- # @param [org.openhab.core.automation.Trigger] trigger openHAB trigger associated with handler
31
- #
32
- def initialize(trigger)
33
- @trigger = trigger
34
- @scheduler = OSGi.service("org.openhab.core.scheduler.CronScheduler")
35
- @schedule = nil
36
- @expression = trigger.configuration.get("cronExpression")
37
- super(trigger)
38
- end
4
+ return unless OpenHAB::Core.version < OpenHAB::Core::V4_0
5
+
6
+ require "singleton"
7
+
8
+ require_relative "cron"
9
+
10
+ module OpenHAB
11
+ module DSL
12
+ module Rules
13
+ module Triggers
14
+ # @!visibility private
15
+ #
16
+ # Cron trigger handler that provides trigger ID
17
+ #
18
+ module CronHandler
19
+ # Cron Trigger Handler that provides trigger IDs
20
+ # Unfortunatly because the CronTriggerHandler in openHAB core is marked internal
21
+ # the entire thing must be recreated here
22
+ class CronTriggerHandler < org.openhab.core.automation.handler.BaseTriggerModuleHandler
23
+ include org.openhab.core.scheduler.SchedulerRunnable
24
+ include org.openhab.core.automation.handler.TimeBasedTriggerHandler
25
+
26
+ # Provides access to protected fields
27
+ field_accessor :callback
28
+
29
+ # Creates a new CronTriggerHandler
30
+ # @param [org.openhab.core.automation.Trigger] trigger openHAB trigger associated with handler
31
+ #
32
+ def initialize(trigger)
33
+ @trigger = trigger
34
+ @scheduler = OSGi.service("org.openhab.core.scheduler.CronScheduler")
35
+ @schedule = nil
36
+ @expression = trigger.configuration.get("cronExpression")
37
+ super(trigger)
38
+ end
39
39
 
40
- #
41
- # Set the callback to execute when cron trigger fires
42
- # @param [Object] callback to run
43
- #
44
- def setCallback(callback) # rubocop:disable Naming/MethodName
45
- synchronized do
46
- super(callback)
47
- @schedule = @scheduler.schedule(self, @expression)
48
- logger.trace("Scheduled cron job '#{@expression}' for trigger '#{@trigger.id}'.")
49
- end
40
+ #
41
+ # Set the callback to execute when cron trigger fires
42
+ # @param [Object] callback to run
43
+ #
44
+ def setCallback(callback) # rubocop:disable Naming/MethodName
45
+ synchronized do
46
+ super(callback)
47
+ @schedule = @scheduler.schedule(self, @expression)
48
+ logger.trace("Scheduled cron job '#{@expression}' for trigger '#{@trigger.id}'.")
50
49
  end
50
+ end
51
51
 
52
- #
53
- # Get the temporal adjuster
54
- # @return [CronAdjuster]
55
- #
56
- def getTemporalAdjuster # rubocop:disable Naming/MethodName
57
- org.openhab.core.scheduler.CronAdjuster.new(@expression)
58
- end
52
+ #
53
+ # Get the temporal adjuster
54
+ # @return [CronAdjuster]
55
+ #
56
+ def getTemporalAdjuster # rubocop:disable Naming/MethodName
57
+ org.openhab.core.scheduler.CronAdjuster.new(@expression)
58
+ end
59
59
 
60
- #
61
- # Execute the callback
62
- #
63
- def run
64
- callback&.triggered(@trigger, { "module" => @trigger.id })
65
- end
60
+ #
61
+ # Execute the callback
62
+ #
63
+ def run
64
+ callback&.triggered(@trigger, { "module" => @trigger.id })
65
+ end
66
66
 
67
- #
68
- # Dispose of the handler
69
- # cancel the cron scheduled task
70
- #
71
- def dispose
72
- synchronized do
73
- super
74
- return unless @schedule
67
+ #
68
+ # Dispose of the handler
69
+ # cancel the cron scheduled task
70
+ #
71
+ def dispose
72
+ synchronized do
73
+ super
74
+ return unless @schedule
75
75
 
76
- @schedule.cancel(true)
77
- @schedule = nil
78
- end
79
- logger.trace("cancelled job for trigger '#{@trigger.id}'.")
76
+ @schedule.cancel(true)
77
+ @schedule = nil
80
78
  end
79
+ logger.trace("cancelled job for trigger '#{@trigger.id}'.")
81
80
  end
81
+ end
82
82
 
83
- # Implements the ScriptedTriggerHandlerFactory interface to create a new Cron Trigger Handler
84
- class CronTriggerHandlerFactory
85
- include Singleton
86
- include org.openhab.core.automation.module.script.rulesupport.shared.factories.ScriptedTriggerHandlerFactory # rubocop:disable Layout/LineLength
87
-
88
- def initialize
89
- Core.automation_manager.add_trigger_handler(
90
- Cron::CRON_TRIGGER_MODULE_ID,
91
- self
92
- )
93
-
94
- Core.automation_manager.add_trigger_type(org.openhab.core.automation.type.TriggerType.new(
95
- Cron::CRON_TRIGGER_MODULE_ID,
96
- nil,
97
- "A specific instant occurs",
98
- "Triggers when the specified instant occurs",
99
- nil,
100
- org.openhab.core.automation.Visibility::VISIBLE,
101
- nil
102
- ))
103
- logger.trace("Added script cron trigger handler")
104
- end
83
+ # Implements the ScriptedTriggerHandlerFactory interface to create a new Cron Trigger Handler
84
+ class CronTriggerHandlerFactory
85
+ include Singleton
86
+ include org.openhab.core.automation.module.script.rulesupport.shared.factories.ScriptedTriggerHandlerFactory
87
+
88
+ def initialize
89
+ Core.automation_manager.add_trigger_handler(
90
+ Cron::CRON_TRIGGER_MODULE_ID,
91
+ self
92
+ )
93
+
94
+ Core.automation_manager.add_trigger_type(org.openhab.core.automation.type.TriggerType.new(
95
+ Cron::CRON_TRIGGER_MODULE_ID,
96
+ nil,
97
+ "A specific instant occurs",
98
+ "Triggers when the specified instant occurs",
99
+ nil,
100
+ org.openhab.core.automation.Visibility::VISIBLE,
101
+ nil
102
+ ))
103
+ logger.trace("Added script cron trigger handler")
104
+ end
105
105
 
106
- # Invoked by openHAB core to get a trigger handler for the supplied trigger
107
- # @param [org.openhab.core.automation.Trigger] trigger
108
- #
109
- # @return [WatchTriggerHandler] trigger handler for supplied trigger
110
- def get(trigger)
111
- CronTriggerHandler.new(trigger)
112
- end
106
+ # Invoked by openHAB core to get a trigger handler for the supplied trigger
107
+ # @param [org.openhab.core.automation.Trigger] trigger
108
+ #
109
+ # @return [CronTriggerHandler] trigger handler for supplied trigger
110
+ def get(trigger)
111
+ CronTriggerHandler.new(trigger)
113
112
  end
114
113
  end
115
114
  end
116
115
  end
117
116
  end
118
117
  end
119
-
120
118
  end
@@ -310,7 +310,7 @@ module OpenHAB
310
310
  logger.trace("Added watch trigger handler")
311
311
  end
312
312
 
313
- # Invoked by openHAB core to get a trigger handler for the supllied trigger
313
+ # Invoked by openHAB core to get a trigger handler for the supplied trigger
314
314
  # @param [org.openhab.core.automation.Trigger] trigger
315
315
  #
316
316
  # @return [WatchTriggerHandler] trigger handler for supplied trigger
@@ -144,7 +144,7 @@ module OpenHAB
144
144
  if @builder_proxy
145
145
  old_obj = @builder_proxy.__getobj__
146
146
  @builder_proxy.__setobj__(self)
147
- begin
147
+ DSL::ThreadLocal.thread_local(openhab_create_dummy_items: true) do
148
148
  yield @builder_proxy
149
149
  ensure
150
150
  @builder_proxy.__setobj__(old_obj)
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.16.0"
7
+ VERSION = "5.17.0"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -84,14 +84,17 @@ module OpenHAB
84
84
  # @param [String, nil] label The label for the profile. When nil, the profile will not be visible in the UI.
85
85
  # @param [org.openhab.core.config.core.ConfigDescription, nil] config_description
86
86
  # The configuration description for the profile so that it can be configured in the UI.
87
- # @yield [event, command: nil, state: nil, callback:, link:, item:, channel_uid:, configuration:, context:]
87
+ # @yield [event, command: nil, state: nil, time_series: nil, callback:, link:, item:, channel_uid:, configuration:, context:]
88
88
  # All keyword params are optional. Any that aren't defined won't be passed.
89
- # @yieldparam [:command_from_item, :state_from_item, :command_from_handler, :state_from_handler] event
89
+ # @yieldparam [:command_from_item, :state_from_item, :command_from_handler, :state_from_handler, :time_series_from_handler] event
90
90
  # The event that needs to be processed.
91
91
  # @yieldparam [Command, nil] command
92
92
  # The command being sent for `:command_from_item` and `:command_from_handler` events.
93
93
  # @yieldparam [State, nil] state
94
94
  # The state being sent for `:state_from_item` and `:state_from_handler` events.
95
+ # @yieldparam [TimeSeries] time_series
96
+ # The time series for `:time_series_from_handler` events.
97
+ # Only available since openHAB 4.1.
95
98
  # @yieldparam [Core::Things::ProfileCallback] callback
96
99
  # The callback to be used to customize the action taken.
97
100
  # @yieldparam [Core::Things::ItemChannelLink] link
@@ -105,6 +108,7 @@ module OpenHAB
105
108
  #
106
109
  # @see org.openhab.core.thing.profiles.Profile
107
110
  # @see org.openhab.core.thing.profiles.StateProfile
111
+ # @see org.openhab.core.thing.profiles.TimeSeriesProfile
108
112
  #
109
113
  # @example Vetoing a command
110
114
  # profile(:veto_closing_shades) do |event, item:, command:|
@@ -21,7 +21,8 @@ module OpenHAB
21
21
  attr_accessor :main_thread
22
22
 
23
23
  def initialize
24
- super(1)
24
+ # Allocate a (hopefully) big enough pool size to accommodate scheduled tasks
25
+ super(10)
25
26
  end
26
27
 
27
28
  def submit(runnable)
@@ -37,6 +37,10 @@ module OpenHAB
37
37
  callback&.state_updated(channel_uid, command) if command.is_a?(Core::Types::State)
38
38
  end
39
39
 
40
+ def send_time_series(channel_uid, time_series)
41
+ @callback&.send_time_series(channel_uid, time_series)
42
+ end
43
+
40
44
  def set_callback(callback)
41
45
  @callback = callback
42
46
  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.16.0
4
+ version: 5.17.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: 2024-01-10 00:00:00.000000000 Z
13
+ date: 2024-01-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -258,6 +258,7 @@ files:
258
258
  - lib/openhab/core/events/item_state_changed_event.rb
259
259
  - lib/openhab/core/events/item_state_event.rb
260
260
  - lib/openhab/core/events/item_state_updated_event.rb
261
+ - lib/openhab/core/events/item_time_series_updated_event.rb
261
262
  - lib/openhab/core/events/thing_status_info_event.rb
262
263
  - lib/openhab/core/events/timer_event.rb
263
264
  - lib/openhab/core/items.rb
@@ -348,6 +349,7 @@ files:
348
349
  - lib/openhab/core/types/rewind_fastforward_type.rb
349
350
  - lib/openhab/core/types/stop_move_type.rb
350
351
  - lib/openhab/core/types/string_type.rb
352
+ - lib/openhab/core/types/time_series.rb
351
353
  - lib/openhab/core/types/type.rb
352
354
  - lib/openhab/core/types/un_def_type.rb
353
355
  - lib/openhab/core/types/up_down_type.rb
@@ -357,6 +359,7 @@ files:
357
359
  - lib/openhab/core_ext/ephemeris.rb
358
360
  - lib/openhab/core_ext/java/class.rb
359
361
  - lib/openhab/core_ext/java/duration.rb
362
+ - lib/openhab/core_ext/java/instant.rb
360
363
  - lib/openhab/core_ext/java/list.rb
361
364
  - lib/openhab/core_ext/java/local_date.rb
362
365
  - lib/openhab/core_ext/java/local_time.rb
@@ -482,7 +485,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
482
485
  - !ruby/object:Gem::Version
483
486
  version: '0'
484
487
  requirements: []
485
- rubygems_version: 3.5.4
488
+ rubygems_version: 3.5.5
486
489
  signing_key:
487
490
  specification_version: 4
488
491
  summary: JRuby Helper Libraries for openHAB Scripting