openhab-scripting 5.15.1 → 5.17.0

Sign up to get free protection for your applications and to get access to all the features.
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?