openhab-scripting 2.16.0 → 2.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +12 -16
  3. data/lib/openhab/core/entity_lookup.rb +162 -0
  4. data/lib/openhab/core/openhab_setup.rb +31 -0
  5. data/lib/openhab/core/osgi.rb +61 -0
  6. data/lib/openhab/dsl/actions.rb +105 -0
  7. data/lib/openhab/dsl/dsl.rb +47 -0
  8. data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
  9. data/lib/openhab/dsl/group.rb +100 -0
  10. data/lib/openhab/dsl/items/items.rb +46 -0
  11. data/lib/openhab/dsl/items/number_item.rb +352 -0
  12. data/lib/openhab/dsl/items/string_item.rb +120 -0
  13. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
  14. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
  15. data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
  16. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
  17. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
  18. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
  19. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
  20. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
  21. data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
  22. data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
  23. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
  24. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
  25. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
  26. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
  27. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
  28. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +7 -0
  29. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
  30. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
  31. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
  32. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
  33. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
  34. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
  35. data/lib/openhab/dsl/monkey_patch/types/types.rb +8 -0
  36. data/lib/openhab/dsl/persistence.rb +25 -0
  37. data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
  38. data/lib/openhab/dsl/rules/guard.rb +134 -0
  39. data/lib/openhab/dsl/rules/property.rb +102 -0
  40. data/lib/openhab/dsl/rules/rule.rb +116 -0
  41. data/lib/openhab/dsl/rules/rule_config.rb +151 -0
  42. data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
  43. data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
  44. data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
  45. data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
  46. data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
  47. data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
  48. data/lib/openhab/dsl/states.rb +61 -0
  49. data/lib/openhab/dsl/things.rb +91 -0
  50. data/lib/openhab/dsl/time_of_day.rb +228 -0
  51. data/lib/openhab/dsl/timers.rb +77 -0
  52. data/lib/openhab/dsl/types/quantity.rb +290 -0
  53. data/lib/openhab/dsl/units.rb +39 -0
  54. data/lib/openhab/log/configuration.rb +21 -0
  55. data/lib/openhab/log/logger.rb +172 -0
  56. data/lib/openhab/version.rb +1 -1
  57. metadata +55 -58
  58. data/lib/openhab/configuration.rb +0 -16
  59. data/lib/openhab/core/cron.rb +0 -27
  60. data/lib/openhab/core/debug.rb +0 -34
  61. data/lib/openhab/core/dsl.rb +0 -51
  62. data/lib/openhab/core/dsl/actions.rb +0 -107
  63. data/lib/openhab/core/dsl/entities.rb +0 -140
  64. data/lib/openhab/core/dsl/group.rb +0 -93
  65. data/lib/openhab/core/dsl/items/items.rb +0 -51
  66. data/lib/openhab/core/dsl/items/number_item.rb +0 -323
  67. data/lib/openhab/core/dsl/items/string_item.rb +0 -122
  68. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
  69. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
  70. data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
  71. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
  72. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
  73. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
  74. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
  75. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -182
  76. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
  77. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
  78. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
  79. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
  80. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
  81. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
  82. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
  83. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -7
  84. data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +0 -43
  85. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -60
  86. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
  87. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
  88. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
  89. data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +0 -58
  90. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -8
  91. data/lib/openhab/core/dsl/persistence.rb +0 -27
  92. data/lib/openhab/core/dsl/property.rb +0 -96
  93. data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -348
  94. data/lib/openhab/core/dsl/rule/guard.rb +0 -136
  95. data/lib/openhab/core/dsl/rule/rule.rb +0 -117
  96. data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
  97. data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
  98. data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
  99. data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
  100. data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
  101. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
  102. data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
  103. data/lib/openhab/core/dsl/states.rb +0 -63
  104. data/lib/openhab/core/dsl/things.rb +0 -93
  105. data/lib/openhab/core/dsl/time_of_day.rb +0 -229
  106. data/lib/openhab/core/dsl/timers.rb +0 -79
  107. data/lib/openhab/core/dsl/types/quantity.rb +0 -292
  108. data/lib/openhab/core/dsl/units.rb +0 -41
  109. data/lib/openhab/core/log.rb +0 -170
  110. data/lib/openhab/core/patch_load_path.rb +0 -7
  111. data/lib/openhab/core/startup_delay.rb +0 -23
  112. data/lib/openhab/osgi.rb +0 -59
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openhab/log/logger'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ #
9
+ # Module holds rule triggers
10
+ #
11
+ module Triggers
12
+ include OpenHAB::Log
13
+
14
+ #
15
+ # Struct capturing data necessary for a conditional trigger
16
+ #
17
+ TriggerDelay = Struct.new(:to, :from, :duration, :timer, :tracking_to, keyword_init: true) do
18
+ def timer_active?
19
+ timer&.is_active
20
+ end
21
+ end
22
+
23
+ #
24
+ # Creates a trigger item, group and thing changed
25
+ #
26
+ # @param [Object] items array of objects to create trigger for
27
+ # @param [to] to state for object to change for
28
+ # @param [from] from <description>
29
+ # @param [OpenHAB::Core::Duration] for Duration to delay trigger until to state is met
30
+ #
31
+ # @return [Trigger] OpenHAB trigger
32
+ #
33
+ def changed(*items, to: nil, from: nil, for: nil)
34
+ items.flatten.each do |item|
35
+ logger.trace("Creating changed trigger for entity(#{item}), to(#{to}), from(#{from})")
36
+ # for is a reserved word in ruby, so use local_variable_get :for
37
+ if (wait_duration = binding.local_variable_get(:for))
38
+ changed_wait(item, to: to, from: from, duration: wait_duration)
39
+ else
40
+ # Place in array and flatten to support multiple to elements or single or nil
41
+ [to].flatten.each do |to_state|
42
+ create_changed_trigger(item, from, to_state)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ #
51
+ # Create a TriggerDelay for for an item or group that is changed for a specific duration
52
+ #
53
+ # @param [Object] item to create trigger delay for
54
+ # @param [OpenHAB::Core::Duration] duration to delay trigger for until condition is met
55
+ # @param [Item State] to OpenHAB Item State item or group needs to change to
56
+ # @param [Item State] from OpenHAB Item State item or group needs to be coming from
57
+ #
58
+ # @return [Array] Array of current TriggerDelay objects
59
+ #
60
+ def changed_wait(item, duration:, to: nil, from: nil)
61
+ # If GroupItems specified, use the group state trigger instead
62
+ if item.is_a? GroupItems
63
+ config = { 'groupName' => item.group.name }
64
+ trigger = Trigger::GROUP_STATE_CHANGE
65
+ else
66
+ config = { 'itemName' => item.name }
67
+ trigger = Trigger::ITEM_STATE_CHANGE
68
+ end
69
+ logger.trace("Creating Changed Wait Change Trigger for #{config}")
70
+ trigger = append_trigger(trigger, config)
71
+ @trigger_delays[trigger.id] = TriggerDelay.new(to: to, from: from, duration: duration)
72
+ end
73
+
74
+ #
75
+ # Create a changed trigger
76
+ #
77
+ # @param [Object] item to create changed trigger on
78
+ # @param [String] from state to restrict trigger to
79
+ # @param [String] to state restrict trigger to
80
+ #
81
+ #
82
+ def create_changed_trigger(item, from, to)
83
+ trigger, config = case item
84
+ when GroupItems then create_group_changed_trigger(item, from, to)
85
+ when Thing then create_thing_changed_trigger(item, from, to)
86
+ else create_item_changed_trigger(item, from, to)
87
+ end
88
+ append_trigger(trigger, config)
89
+ end
90
+
91
+ #
92
+ # Create a changed trigger for a thing
93
+ #
94
+ # @param [Thing] thing to detected changed states on
95
+ # @param [String] from state to restrict trigger to
96
+ # @param [String] to state to restrict trigger to
97
+ #
98
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
99
+ # second element is a Hash configuring trigger
100
+ #
101
+ def create_thing_changed_trigger(thing, from, to)
102
+ trigger_for_thing(thing, Trigger::THING_CHANGE, to, from)
103
+ end
104
+
105
+ #
106
+ # Create a changed trigger for an item
107
+ #
108
+ # @param [Item] item to detected changed states on
109
+ # @param [String] from state to restrict trigger to
110
+ # @param [String] to to restrict trigger to
111
+ #
112
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
113
+ # second element is a Hash configuring trigger
114
+ #
115
+ def create_item_changed_trigger(item, from, to)
116
+ config = { 'itemName' => item.name }
117
+ config['state'] = to.to_s if to
118
+ config['previousState'] = from.to_s if from
119
+ trigger = Trigger::ITEM_STATE_CHANGE
120
+ [trigger, config]
121
+ end
122
+
123
+ #
124
+ # Create a changed trigger for group items
125
+ #
126
+ # @param [Group] group to detected changed states on
127
+ # @param [String] from state to restrict trigger to
128
+ # @param [String] to to restrict trigger to
129
+ #
130
+ # @return [Array<Hash,String>] first element is a String specifying trigger type
131
+ # second element is a Hash configuring trigger
132
+ #
133
+ def create_group_changed_trigger(group, from, to)
134
+ config = { 'groupName' => group.group.name }
135
+ config['state'] = to.to_s if to
136
+ config['previousState'] = from.to_s if from
137
+ trigger = Trigger::GROUP_STATE_CHANGE
138
+ [trigger, config]
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openhab/log/logger'
4
+ require 'openhab/dsl/rules/triggers/trigger'
5
+
6
+ module OpenHAB
7
+ module DSL
8
+ module Rules
9
+ #
10
+ # Channel triggers
11
+ #
12
+ module Triggers
13
+ include OpenHAB::Log
14
+
15
+ #
16
+ # Creates a channel trigger
17
+ #
18
+ # @param [Array] channels array to create triggers for on form of 'binding_id:type_id:thing_id#channel_id'
19
+ # or 'channel_id' if thing is provided
20
+ # @param [thing] thing to create trigger for if not specified with the channel
21
+ # @param [String] triggered specific triggering condition to match for trigger
22
+ #
23
+ #
24
+ def channel(*channels, thing: nil, triggered: nil)
25
+ channels.flatten.each do |channel|
26
+ channel = [thing, channel].join(':') if thing
27
+ logger.trace("Creating channel trigger for channel(#{channel}), thing(#{thing}), trigger(#{triggered})")
28
+ [triggered].flatten.each do |trigger|
29
+ create_channel_trigger(channel, trigger)
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ #
37
+ # Create a trigger for a channel
38
+ #
39
+ # @param [Channel] channel to look for triggers
40
+ # @param [Trigger] trigger specific channel trigger to match
41
+ #
42
+ #
43
+ def create_channel_trigger(channel, trigger)
44
+ config = { 'channelUID' => channel }
45
+ config['event'] = trigger.to_s unless trigger.nil?
46
+ config['channelUID'] = channel
47
+ logger.trace("Creating Change Trigger for #{config}")
48
+ @triggers << Trigger.trigger(type: Trigger::CHANNEL_EVENT, config: config)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openhab/log/logger'
4
+
5
+ module OpenHAB
6
+ module DSL
7
+ module Rules
8
+ #
9
+ # Module holds rule triggers
10
+ #
11
+ module Triggers
12
+ include OpenHAB::Log
13
+
14
+ #
15
+ # Create a trigger for when an item or group receives a command
16
+ #
17
+ # The commands/commands parameters are replicated for DSL fluency
18
+ #
19
+ # @param [Array] items Array of items to create trigger for
20
+ # @param [Array] command commands to match for trigger
21
+ # @param [Array] commands commands to match for trigger
22
+ #
23
+ #
24
+ def received_command(*items, command: nil, commands: nil)
25
+ items.flatten.each do |item|
26
+ logger.trace("Creating received command trigger for item(#{item})"\
27
+ "command(#{command}) commands(#{commands})")
28
+
29
+ # Combine command and commands, doing union so only a single nil will be in the combined array.
30
+ combined_commands = combine_commands(command, commands)
31
+ create_received_trigger(combined_commands, item)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ #
38
+ # Create a received trigger based on item type
39
+ #
40
+ # @param [Array] commands to create trigger for
41
+ # @param [Object] item to create trigger for
42
+ #
43
+ #
44
+ def create_received_trigger(commands, item)
45
+ commands.each do |command|
46
+ if item.is_a? GroupItems
47
+ config, trigger = create_group_command_trigger(item)
48
+ else
49
+ config, trigger = create_item_command_trigger(item)
50
+ end
51
+ config['command'] = command.to_s unless command.nil?
52
+ append_trigger(trigger, config)
53
+ end
54
+ end
55
+
56
+ #
57
+ # Create trigger for item commands
58
+ #
59
+ # @param [Item] item to create trigger for
60
+ #
61
+ # @return [Array<Hash,Trigger>] first element is hash of trigger config properties
62
+ # second element is trigger type
63
+ #
64
+ def create_item_command_trigger(item)
65
+ config = { 'itemName' => item.name }
66
+ trigger = Trigger::ITEM_COMMAND
67
+ [config, trigger]
68
+ end
69
+
70
+ #
71
+ # Create trigger for group items
72
+ #
73
+ # @param [Group] group to create trigger for
74
+ #
75
+ # @return [Array<Hash,Trigger>] first element is hash of trigger config properties
76
+ # second element is trigger type
77
+ #
78
+ def create_group_command_trigger(group)
79
+ config = { 'groupName' => group.group.name }
80
+ trigger = Trigger::GROUP_COMMAND
81
+ [config, trigger]
82
+ end
83
+
84
+ #
85
+ # Combine command and commands into a single array
86
+ #
87
+ # @param [Array] command list of commands to trigger on
88
+ # @param [Array] commands list of commands to trigger on
89
+ #
90
+ # @return [Array] Combined flattened and compacted list of commands
91
+ #
92
+ def combine_commands(command, commands)
93
+ combined_commands = ([command] | [commands]).flatten
94
+
95
+ # If either command or commands has a value and one is nil, we need to remove nil from the array.
96
+ # If it is only now a single nil value, we leave the nil in place, so that we create a trigger
97
+ # That isn't looking for a specific command.
98
+ combined_commands = combined_commands.compact unless combined_commands.all?(&:nil?)
99
+ combined_commands
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ require 'openhab/dsl/time_of_day'
5
+
6
+ module OpenHAB
7
+ module DSL
8
+ module Rules
9
+ #
10
+ # Cron type rules
11
+ #
12
+ module Triggers
13
+ java_import org.openhab.core.automation.util.TriggerBuilder
14
+ java_import org.openhab.core.config.core.Configuration
15
+
16
+ #
17
+ # Returns a default map for cron expressions that fires every second
18
+ # This map is usually updated via merge by other methods to refine cron type triggers.
19
+ #
20
+ # @return [Hash] Map with symbols for :seconds, :minute, :hour, :dom, :month, :dow
21
+ # configured to fire every second
22
+ #
23
+ def cron_expression_map
24
+ {
25
+ second: '*',
26
+ minute: '*',
27
+ hour: '*',
28
+ dom: '?',
29
+ month: '*',
30
+ dow: '?'
31
+ }
32
+ end
33
+ # Rubocop check is disabled because YARD cannot process the method if placed in front of
34
+ # the method definition
35
+ # rubocop:disable Style/AccessModifierDeclarations
36
+ module_function :cron_expression_map
37
+ # rubocop:enable Style/AccessModifierDeclarations
38
+
39
+ # @return [Hash] Map of days of the week from symbols to to OpenHAB cron strings
40
+ DAY_OF_WEEK_MAP = {
41
+ monday: 'MON',
42
+ tuesday: 'TUE',
43
+ wednesday: 'WED',
44
+ thursday: 'THU',
45
+ friday: 'FRI',
46
+ saturday: 'SAT',
47
+ sunday: 'SUN'
48
+ }.freeze
49
+
50
+ private_constant :DAY_OF_WEEK_MAP
51
+
52
+ # @return [Hash] Converts the DAY_OF_WEEK_MAP to map used by Cron Expression
53
+ DAY_OF_WEEK_EXPRESSION_MAP = DAY_OF_WEEK_MAP.transform_values { |v| cron_expression_map.merge(dow: v) }
54
+
55
+ private_constant :DAY_OF_WEEK_EXPRESSION_MAP
56
+
57
+ # @return [Hash] Create a set of cron expressions based on different time intervals
58
+ EXPRESSION_MAP = {
59
+ second: cron_expression_map,
60
+ minute: cron_expression_map.merge(second: '0'),
61
+ hour: cron_expression_map.merge(second: '0', minute: '0'),
62
+ day: cron_expression_map.merge(second: '0', minute: '0', hour: '0'),
63
+ week: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dow: 'MON'),
64
+ month: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dom: '1'),
65
+ year: cron_expression_map.merge(second: '0', minute: '0', hour: '0', dom: '1', month: '1')
66
+ }.merge(DAY_OF_WEEK_EXPRESSION_MAP)
67
+ .freeze
68
+
69
+ private_constant :EXPRESSION_MAP
70
+
71
+ #
72
+ # Create a rule that executes at the specified interval
73
+ #
74
+ # @param [Object] value Symbol or Duration to execute this rule
75
+ # @param [Object] at TimeOfDay or String representing TimeOfDay in which to execute rule
76
+ #
77
+ #
78
+ def every(value, at: nil)
79
+ cron_expression = case value
80
+ when Symbol then cron_from_symbol(value, at)
81
+ when Java::JavaTime::Duration then cron_from_duration(value, at)
82
+ else raise ArgumentExpression, 'Unknown interval'
83
+ end
84
+ cron(cron_expression)
85
+ end
86
+
87
+ #
88
+ # Create a OpenHAB Cron trigger
89
+ #
90
+ # @param [String] expression OpenHAB style cron expression
91
+ #
92
+ def cron(expression)
93
+ @triggers << Trigger.trigger(type: Trigger::CRON, config: { 'cronExpression' => expression })
94
+ end
95
+
96
+ private
97
+
98
+ #
99
+ # Create a cron map from a duration
100
+ #
101
+ # @param [java::time::Duration] duration
102
+ # @param [Object] at TimeOfDay or String representing time of day
103
+ #
104
+ # @return [Hash] map describing cron expression
105
+ #
106
+ def cron_from_duration(duration, at)
107
+ raise ArgumentError, '"at" cannot be used with duration' if at
108
+
109
+ map_to_cron(duration_to_map(duration))
110
+ end
111
+
112
+ #
113
+ # Create a cron map from a symbol
114
+ #
115
+ # @param [Symbol] symbol
116
+ # @param [Object] at TimeOfDay or String representing time of day
117
+ #
118
+ # @return [Hash] map describing cron expression created from symbol
119
+ #
120
+ def cron_from_symbol(symbol, at)
121
+ expression_map = EXPRESSION_MAP[symbol]
122
+ expression_map = at_condition(expression_map, at) if at
123
+ map_to_cron(expression_map)
124
+ end
125
+
126
+ #
127
+ # Map cron expression to to cron string
128
+ #
129
+ # @param [Map] map of cron expression
130
+ #
131
+ # @return [String] OpenHAB cron string
132
+ #
133
+ def map_to_cron(map)
134
+ %i[second minute hour dom month dow].map { |field| map.fetch(field) }.join(' ')
135
+ end
136
+
137
+ #
138
+ # Convert a Java Duration to a map for the map_to_cron method
139
+ #
140
+ # @param duration [Java::JavaTime::Duration] The duration object
141
+ #
142
+ # @return [Hash] a map suitable for map_to_cron
143
+ #
144
+ def duration_to_map(duration)
145
+ if duration.to_millis_part.zero? && duration.to_nanos_part.zero? && duration.to_days.zero?
146
+ %i[second minute hour].each do |unit|
147
+ to_unit_part = duration.public_send("to_#{unit}s_part")
148
+ next unless to_unit_part.positive?
149
+
150
+ to_unit = duration.public_send("to_#{unit}s")
151
+ break unless to_unit_part == to_unit
152
+
153
+ return EXPRESSION_MAP[unit].merge(unit => "*/#{to_unit}")
154
+ end
155
+ end
156
+ raise ArgumentError, "Cron Expression not supported for duration: #{duration}"
157
+ end
158
+
159
+ #
160
+ # If an at time is provided, parse that and merge the new fields into the expression.
161
+ #
162
+ # @param [<Type>] expression_map <description>
163
+ # @param [<Type>] at_time <description>
164
+ #
165
+ # @return [<Type>] <description>
166
+ #
167
+ def at_condition(expression_map, at_time)
168
+ if at_time
169
+ tod = at_time.is_a?(TimeOfDay::TimeOfDay) ? at_time : TimeOfDay::TimeOfDay.parse(at_time)
170
+ expression_map = expression_map.merge(hour: tod.hour, minute: tod.minute, second: tod.second)
171
+ end
172
+ expression_map
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end