openhab-scripting 5.16.0 → 5.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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