openhab-scripting 5.15.1 → 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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/entity_lookup.rb +5 -5
  3. data/lib/openhab/core/events/item_state_updated_event.rb +11 -11
  4. data/lib/openhab/core/events/item_time_series_updated_event.rb +23 -0
  5. data/lib/openhab/core/events/timer_event.rb +32 -32
  6. data/lib/openhab/core/items/generic_item.rb +12 -0
  7. data/lib/openhab/core/items/numeric_item.rb +1 -1
  8. data/lib/openhab/core/items/persistence.rb +2 -4
  9. data/lib/openhab/core/items/registry.rb +1 -3
  10. data/lib/openhab/core/items/semantics.rb +25 -15
  11. data/lib/openhab/core/profile_factory.rb +16 -1
  12. data/lib/openhab/core/sitemaps/provider.rb +3 -1
  13. data/lib/openhab/core/things/channel.rb +1 -1
  14. data/lib/openhab/core/things/profile_callback.rb +5 -0
  15. data/lib/openhab/core/things/thing.rb +7 -1
  16. data/lib/openhab/core/types/time_series.rb +121 -0
  17. data/lib/openhab/core.rb +14 -1
  18. data/lib/openhab/core_ext/java/instant.rb +14 -0
  19. data/lib/openhab/core_ext/java/list.rb +1 -1
  20. data/lib/openhab/dsl/config_description/builder.rb +1 -1
  21. data/lib/openhab/dsl/rules/builder.rb +42 -7
  22. data/lib/openhab/dsl/rules/name_inference.rb +7 -0
  23. data/lib/openhab/dsl/rules/property.rb +7 -7
  24. data/lib/openhab/dsl/rules/terse.rb +32 -15
  25. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +5 -4
  26. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +98 -100
  27. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
  28. data/lib/openhab/dsl/sitemaps/builder.rb +41 -6
  29. data/lib/openhab/dsl/version.rb +1 -1
  30. data/lib/openhab/dsl.rb +6 -2
  31. data/lib/openhab/log.rb +2 -2
  32. data/lib/openhab/rspec/helpers.rb +7 -4
  33. data/lib/openhab/rspec/mocks/synchronous_executor.rb +2 -1
  34. data/lib/openhab/rspec/mocks/thing_handler.rb +4 -0
  35. data/lib/openhab/yard/coderay.rb +1 -1
  36. data/lib/openhab/yard.rb +0 -2
  37. metadata +6 -129
@@ -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,15 +20,15 @@ module OpenHAB
20
20
  # in this module than instance variable belong to the module not the calling class
21
21
  define_method(name) do |*args, &block|
22
22
  if args.empty? && block.nil? == true
23
- instance_variable_get("@#{name}")
23
+ instance_variable_get(:"@#{name}")
24
24
  else
25
25
  logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
26
26
  if args.length == 1
27
- instance_variable_set("@#{name}", args.first)
27
+ instance_variable_set(:"@#{name}", args.first)
28
28
  elsif args.length > 1
29
- instance_variable_set("@#{name}", args)
29
+ instance_variable_set(:"@#{name}", args)
30
30
  elsif block
31
- instance_variable_set("@#{name}", block)
31
+ instance_variable_set(:"@#{name}", block)
32
32
  end
33
33
  end
34
34
  end
@@ -47,7 +47,7 @@ module OpenHAB
47
47
  define_method(name) do |*args, &block|
48
48
  array_name ||= name
49
49
  if args.empty? && block.nil? == true
50
- instance_variable_get("@#{array_name}")
50
+ instance_variable_get(:"@#{array_name}")
51
51
  else
52
52
  logger.trace("Property '#{name}' called with args(#{args}) and block(#{block})")
53
53
  if args.length == 1
@@ -59,14 +59,14 @@ module OpenHAB
59
59
  end
60
60
  yield insert if block_given?
61
61
  insert = wrapper.new(insert) if wrapper
62
- instance_variable_set("@#{array_name}", (instance_variable_get("@#{array_name}") || []) << insert)
62
+ instance_variable_set(:"@#{array_name}", (instance_variable_get(:"@#{array_name}") || []) << insert)
63
63
  end
64
64
  end
65
65
 
66
66
  return unless array_name
67
67
 
68
68
  define_method(array_name) do
69
- instance_variable_get("@#{array_name}")
69
+ instance_variable_get(:"@#{array_name}")
70
70
  end
71
71
  end
72
72
  end
@@ -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
@@ -174,10 +175,10 @@ module OpenHAB
174
175
  def self.duration_to_map(duration)
175
176
  if duration.to_millis_part.zero? && duration.to_nanos_part.zero? && duration.to_days.zero?
176
177
  %i[second minute hour].each do |unit|
177
- to_unit_part = duration.public_send("to_#{unit}s_part")
178
+ to_unit_part = duration.public_send(:"to_#{unit}s_part")
178
179
  next unless to_unit_part.positive?
179
180
 
180
- to_unit = duration.public_send("to_#{unit}s")
181
+ to_unit = duration.public_send(:"to_#{unit}s")
181
182
  break unless to_unit_part == to_unit
182
183
 
183
184
  return EXPRESSION_MAP[unit].merge(unit => "*/#{to_unit}")
@@ -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
@@ -116,7 +116,7 @@ module OpenHAB
116
116
  icon_color: nil,
117
117
  visibility: nil,
118
118
  &block)
119
- unless SitemapBuilder.factory.respond_to?("create_#{type}")
119
+ unless SitemapBuilder.factory.respond_to?(:"create_#{type}")
120
120
  raise ArgumentError,
121
121
  "#{type} is not a valid widget type"
122
122
  end
@@ -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)
@@ -183,7 +183,7 @@ module OpenHAB
183
183
 
184
184
  # @!visibility private
185
185
  def build
186
- widget = SitemapBuilder.factory.send("create_#{@type}")
186
+ widget = SitemapBuilder.factory.send(:"create_#{@type}")
187
187
  item = @item
188
188
  item = item.name if item.respond_to?(:name)
189
189
  widget.item = item if item
@@ -281,9 +281,41 @@ module OpenHAB
281
281
  class SwitchBuilder < WidgetBuilder
282
282
  # Mappings from command to label
283
283
  #
284
- # Keys can be any {Core::Types::Command command}, values are strings.
285
- # If an array is given, the same value is used for both command and label.
284
+ # If a hash is given, the keys are the commands and the values are the labels.
285
+ # The keys can be any {Core::Types::Command command}, string or symbol.
286
+ # They will be converted to strings.
287
+ #
288
+ # If an array is given:
289
+ # - Scalar elements define the command, and the label is the same as the command.
290
+ # - Array elements contain the command, label, and optional third element for the icon.
291
+ # - Hash elements contain the command, label, and optional icon defined by the corresponding keys.
292
+ #
293
+ # @since openHAB 4.1 added support for icons
294
+ #
295
+ # @example A Hash to specify different command and label
296
+ # switch mappings: { off: "Off", cool: "Cool", heat: "Heat" }
297
+ #
298
+ # @example A simple array with the same command and label
299
+ # switch mappings: %w[off cool heat]
300
+ #
301
+ # @example An array of arrays containing the command, label, and icon
302
+ # switch mappings: [
303
+ # %w[off Off f7:power],
304
+ # %w[cool Cool f7:snow],
305
+ # %w[heat Heat f7:flame],
306
+ # %w[auto Auto] # no icon
307
+ # ]
308
+ #
309
+ # @example An array of hashes for the command, label, and icon
310
+ # switch mappings: [
311
+ # {command: "off", label: "Off", icon: "f7:power"},
312
+ # {command: "cool", label: "Cool", icon: "f7:snow"},
313
+ # {command: "heat", label: "Heat", icon: "f7:flame"},
314
+ # {command: "auto", label: "Auto"} # no icon
315
+ # ]
316
+ #
286
317
  # @return [Hash, Array, nil]
318
+ # @see LinkableWidgetBuilder#switch
287
319
  # @see https://www.openhab.org/docs/ui/sitemaps.html#mappings
288
320
  attr_accessor :mappings
289
321
 
@@ -300,10 +332,13 @@ module OpenHAB
300
332
  # @!visibility private
301
333
  def build
302
334
  widget = super
303
- mappings&.each do |cmd, label|
335
+ mappings&.each do |cmd, label, icon|
304
336
  mapping = SitemapBuilder.factory.create_mapping
337
+ cmd, label, icon = cmd.values_at(:command, :label, :icon) if cmd.is_a?(Hash)
305
338
  mapping.cmd = cmd.to_s
306
339
  mapping.label = label&.to_s || cmd.to_s
340
+ # @deprecated OH 4.1 the if check is not needed in OH4.1+
341
+ mapping.icon = icon if icon
307
342
  widget.mappings.add(mapping)
308
343
  end
309
344
  widget
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.15.1"
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:|
data/lib/openhab/log.rb CHANGED
@@ -210,7 +210,7 @@ module OpenHAB
210
210
  # @return [true,false]
211
211
  #
212
212
  def def_level_predicate(level)
213
- define_method("#{level}?") { @slf4j_logger.send("is_#{level}_enabled") }
213
+ define_method(:"#{level}?") { @slf4j_logger.send(:"is_#{level}_enabled") }
214
214
  end
215
215
  end
216
216
 
@@ -318,7 +318,7 @@ module OpenHAB
318
318
  raise ArgumentError, "Unknown Severity #{severity}" unless LEVELS.include? severity
319
319
 
320
320
  # Dynamically check enablement of underlying logger
321
- return unless send("#{severity}?")
321
+ return unless send(:"#{severity}?")
322
322
 
323
323
  # Process block if no message provided
324
324
  msg = yield if msg.nil? && block_given?