openhab-scripting 5.17.0 → 5.18.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openhab/core/items/semantics/enumerable.rb +2 -2
- data/lib/openhab/core/rules/registry.rb +2 -1
- data/lib/openhab/core/rules/rule.rb +1 -0
- data/lib/openhab/core/types/string_type.rb +1 -1
- data/lib/openhab/core/types/time_series.rb +11 -1
- data/lib/openhab/dsl/items/builder.rb +0 -1
- data/lib/openhab/dsl/items/timed_command.rb +1 -0
- data/lib/openhab/dsl/rules/builder.rb +98 -32
- data/lib/openhab/dsl/rules/name_inference.rb +9 -8
- data/lib/openhab/dsl/rules/property.rb +4 -1
- data/lib/openhab/dsl/rules/rule_triggers.rb +5 -3
- data/lib/openhab/dsl/rules/terse.rb +21 -16
- data/lib/openhab/dsl/rules/triggers/changed.rb +15 -7
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/dsl.rb +24 -2
- data/lib/openhab/rspec/mocks/persistence_service.rb +10 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfc9ae60d0f82fc677a157ac0efd58c12fc597f5ac8f3d79d7aa9c472e2c5d3a
|
4
|
+
data.tar.gz: b8bf1721d064b2f88554722518496aa6c53b89407a9fb212880972725e49901f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e50f4ce2c5832a39b3ab9c7b7a489b22697a23b20ce803a633f28ea9b44ed2661a820cdefd00bc54c71cb212a2c1a1d96c35c413937cd3ac514aec55a4c13da
|
7
|
+
data.tar.gz: a298851e7255074cb21d9fd4e495a8c8dc750425b0db3319ab17353c2e07106e0f669a40912bbe98cc6db9f252ff70ebe68b9c94fb7366c4b257200da13eefda
|
@@ -97,8 +97,8 @@ module Enumerable
|
|
97
97
|
# Send a command to every item in the collection
|
98
98
|
# @return [self, nil] nil when `ensure` is in effect and all the items were already in the same state,
|
99
99
|
# otherwise self
|
100
|
-
def command(command)
|
101
|
-
self if count { |i| i.command(command) }.positive?
|
100
|
+
def command(command, **kwargs)
|
101
|
+
self if count { |i| i.command(command, **kwargs) }.positive?
|
102
102
|
end
|
103
103
|
|
104
104
|
# Send a command to every item in the collection, even when {OpenHAB::DSL.ensure_states! ensure_states!} is in effect.
|
@@ -63,7 +63,8 @@ module OpenHAB
|
|
63
63
|
#
|
64
64
|
def remove(rule_uid)
|
65
65
|
rule_uid = rule_uid.uid if rule_uid.is_a?(Rule)
|
66
|
-
provider = Provider.registry.provider_for(rule_uid)
|
66
|
+
return nil unless (provider = Provider.registry.provider_for(rule_uid))
|
67
|
+
|
67
68
|
unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
|
68
69
|
raise "Cannot remove rule #{rule_uid} from non-managed provider #{provider.inspect}"
|
69
70
|
end
|
@@ -149,6 +149,7 @@ module OpenHAB
|
|
149
149
|
r += " #{visibility}" unless visible?
|
150
150
|
r += " #{status || "<detached>"}"
|
151
151
|
r += " (#{status_info.status_detail})" if status_info && status_info.status_detail != RuleStatusDetail::NONE
|
152
|
+
r += " description=#{description.inspect}" if description
|
152
153
|
r += " tags=#{tags.to_a.inspect}" unless tags.empty?
|
153
154
|
r += " configuration=#{configuration.properties.to_h}" if configuration && !configuration.properties.empty?
|
154
155
|
"#{r}>"
|
@@ -101,12 +101,22 @@ module OpenHAB
|
|
101
101
|
# @note This method returns self so it can be chained, unlike the Java version.
|
102
102
|
#
|
103
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.
|
104
|
+
# @param [State, String, Numeric] state The State at the given timestamp.
|
105
|
+
# If a String is given, it will be converted to {StringType}.
|
106
|
+
# If a {Numeric} is given, it will be converted to {DecimalType}.
|
105
107
|
# @return [self]
|
108
|
+
# @raise [ArgumentError] if state is not a {State}, String or {Numeric}
|
106
109
|
#
|
107
110
|
def add(instant, state)
|
108
111
|
instant = instant.to_zoned_date_time if instant.respond_to?(:to_zoned_date_time)
|
109
112
|
instant = instant.to_instant if instant.respond_to?(:to_instant)
|
113
|
+
state = case state
|
114
|
+
when State then state
|
115
|
+
when String then StringType.new(state)
|
116
|
+
when Numeric then DecimalType.new(state)
|
117
|
+
else
|
118
|
+
raise ArgumentError, "state must be a State, String or Numeric, but was #{state.class}"
|
119
|
+
end
|
110
120
|
add_instant(instant, state)
|
111
121
|
self
|
112
122
|
end
|
@@ -672,7 +672,6 @@ module OpenHAB
|
|
672
672
|
# @param (see ItemBuilder#initialize)
|
673
673
|
def initialize(*args, type: nil, function: nil, thing: nil, **kwargs)
|
674
674
|
raise ArgumentError, "invalid function #{function}" if function && !function.match?(FUNCTION_REGEX)
|
675
|
-
raise ArgumentError, "state cannot be set on GroupItems" if kwargs[:state]
|
676
675
|
|
677
676
|
super(type, *args, **kwargs)
|
678
677
|
@function = function
|
@@ -40,7 +40,17 @@ module OpenHAB
|
|
40
40
|
# The rule must have at least one trigger and one execution block.
|
41
41
|
# To create a "script" without any triggers, use {OpenHAB::DSL.script script}.
|
42
42
|
#
|
43
|
+
# When explicit `id` is not provided, the rule's ID will be inferred from the block's source location,
|
44
|
+
# and a suffix will be added to avoid clashing against existing rules.
|
45
|
+
#
|
46
|
+
# When an explicit `id` is provided and an existing rule with the same id already exists,
|
47
|
+
# the rule will not be created, and the method will return nil.
|
48
|
+
#
|
49
|
+
# To ensure that a rule is created even when the same id already exists, use {OpenHAB::DSL.rule!} or call
|
50
|
+
# {Core::Rules::Registry#remove rules.remove} to remove any existing rule prior to creating the new rule.
|
51
|
+
#
|
43
52
|
# @param [String] name The rule name
|
53
|
+
# @param [String] id The rule's ID. This can also be defined in the block using {Rules::BuilderDSL#uid uid}.
|
44
54
|
# @yield Block executed in the context of a {Rules::BuilderDSL}
|
45
55
|
# @yieldparam [Rules::BuilderDSL] rule
|
46
56
|
# Optional parameter to access the rule configuration from within execution blocks and guards.
|
@@ -48,20 +58,26 @@ module OpenHAB
|
|
48
58
|
#
|
49
59
|
# @see OpenHAB::DSL::Rules::BuilderDSL Rule BuilderDSL for details on rule triggers, guards and execution blocks
|
50
60
|
# @see Rules::Terse Terse Rules
|
61
|
+
# @see DSL.rule!
|
51
62
|
#
|
52
63
|
# @example
|
53
|
-
# require "openhab/dsl"
|
54
|
-
#
|
55
64
|
# rule "name" do
|
56
65
|
# <one or more triggers>
|
57
66
|
# <one or more execution blocks>
|
58
67
|
# <zero or more guards>
|
59
68
|
# end
|
60
69
|
#
|
61
|
-
|
70
|
+
# @example Create a rule with an explicit id, deleting any existing rule with the same id
|
71
|
+
# rule! "name", id: "my_happy_day_reminder" do
|
72
|
+
# every :day
|
73
|
+
# run { logger.info "Happy new day!" }
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
def rule(name = nil, id: nil, replace: nil, script: nil, binding: nil, &block)
|
62
77
|
raise ArgumentError, "Block is required" unless block
|
63
78
|
|
64
|
-
|
79
|
+
inferred_id = nil
|
80
|
+
id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
|
65
81
|
script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
|
66
82
|
|
67
83
|
builder = nil
|
@@ -70,6 +86,18 @@ module OpenHAB
|
|
70
86
|
builder = BuilderDSL.new(binding || block.binding)
|
71
87
|
builder.uid(id)
|
72
88
|
builder.instance_exec(builder, &block)
|
89
|
+
|
90
|
+
if replace
|
91
|
+
logger.debug { "Removing existing rule '#{builder.uid}'." } if DSL.rules.remove(builder.uid)
|
92
|
+
elsif replace.nil?
|
93
|
+
id_not_inferred = inferred_id.nil? || inferred_id != builder.uid
|
94
|
+
if id_not_inferred && (existing_rule = $rules.get(builder.uid))
|
95
|
+
logger.warn "Rule '#{builder.uid}' is not created because " \
|
96
|
+
"another rule/script/scene with the same id already exists: #{existing_rule.inspect}."
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
73
101
|
builder.guard = Guard.new(run_context: builder.caller,
|
74
102
|
only_if: builder.only_if,
|
75
103
|
not_if: builder.not_if)
|
@@ -101,7 +129,7 @@ module OpenHAB
|
|
101
129
|
# @param [String, Symbol, Semantics::Tag, Array<String, Symbol, Semantics::Tag>, nil] tags
|
102
130
|
# Fluent alias for `tag`
|
103
131
|
# @yield [] Block executed when the script is executed.
|
104
|
-
# @return [Core::Rules::Rule]
|
132
|
+
# @return [Core::Rules::Rule, nil]
|
105
133
|
#
|
106
134
|
# @example A simple script
|
107
135
|
# # return the script object into a variable
|
@@ -123,15 +151,26 @@ module OpenHAB
|
|
123
151
|
#
|
124
152
|
# rules.scripts["send_alert"].run(message: "The door is open!")
|
125
153
|
#
|
154
|
+
# @see DSL.rule
|
126
155
|
# @see Core::Rules::Rule#trigger
|
156
|
+
# @see DSL.script!
|
127
157
|
#
|
128
|
-
def script(name = nil, description: nil, id: nil, tag: nil, tags: nil, script: nil, &block)
|
158
|
+
def script(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil, &block)
|
129
159
|
raise ArgumentError, "Block is required" unless block
|
130
160
|
|
131
|
-
|
161
|
+
inferred_id = nil # rubocop:disable Lint/UselessAssignment it is used below
|
162
|
+
id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
|
132
163
|
name ||= id
|
133
164
|
script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
|
134
165
|
|
166
|
+
if replace
|
167
|
+
logger.debug { "Removing existing rule '#{id}'." } if DSL.rules.remove(id)
|
168
|
+
elsif inferred_id.nil? && (existing_rule = $rules.get(id))
|
169
|
+
logger.warn "Script '#{id}' is not created because " \
|
170
|
+
"another script/scene/rule with the same id already exists: #{existing_rule.inspect}."
|
171
|
+
return nil
|
172
|
+
end
|
173
|
+
|
135
174
|
builder = nil
|
136
175
|
ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
|
137
176
|
builder = BuilderDSL.new(block.binding)
|
@@ -159,15 +198,27 @@ module OpenHAB
|
|
159
198
|
# @param [String, Symbol, Semantics::Tag, Array<String, Symbol, Semantics::Tag>, nil] tags
|
160
199
|
# Fluent alias for `tag`
|
161
200
|
# @yield [] Block executed when the script is executed.
|
162
|
-
# @return [Core::Rules::Rule]
|
201
|
+
# @return [Core::Rules::Rule, nil]
|
202
|
+
#
|
203
|
+
# @see DSL.rule
|
204
|
+
# @see DSL.scene!
|
163
205
|
#
|
164
|
-
def scene(name = nil, description: nil, id: nil, tag: nil, tags: nil, script: nil, &block)
|
206
|
+
def scene(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil, &block)
|
165
207
|
raise ArgumentError, "Block is required" unless block
|
166
208
|
|
167
|
-
|
209
|
+
inferred_id = nil # rubocop:disable Lint/UselessAssignment
|
210
|
+
id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
|
168
211
|
name ||= id
|
169
212
|
script ||= block.source rescue nil # rubocop:disable Style/RescueModifier
|
170
213
|
|
214
|
+
if replace
|
215
|
+
logger.debug { "Removing existing rule '#{id}'." } if DSL.rules.remove(id)
|
216
|
+
elsif inferred_id.nil? && (existing_rule = $rules.get(id))
|
217
|
+
logger.warn "Scene '#{id}' is not created because " \
|
218
|
+
"another script/scene/rule with the same id already exists: #{existing_rule.inspect}."
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
|
171
222
|
builder = nil
|
172
223
|
ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
|
173
224
|
builder = BuilderDSL.new(block.binding)
|
@@ -400,7 +451,7 @@ module OpenHAB
|
|
400
451
|
# @param [String] id
|
401
452
|
# @return [void]
|
402
453
|
#
|
403
|
-
prop :
|
454
|
+
prop(:uid) { |id| Thread.current[:openhab_rule_uid] = id }
|
404
455
|
|
405
456
|
#
|
406
457
|
# @!method name(value)
|
@@ -994,13 +1045,20 @@ module OpenHAB
|
|
994
1045
|
# @param [Item, GroupItem::Members, Thing] items Objects to create trigger for.
|
995
1046
|
# @param [State, Array<State>, #===, nil] from
|
996
1047
|
# Only execute rule if previous state matches `from` state(s).
|
997
|
-
# @param [State, Array<State>, #===, nil] to
|
1048
|
+
# @param [State, Array<State>, #===, nil] to
|
998
1049
|
# Only execute rule if new state matches `to` state(s).
|
999
|
-
# @param [java.time.temporal.TemporalAmount] for
|
1000
|
-
# Duration item must remain in the same state before executing the execution blocks.
|
1001
|
-
#
|
1050
|
+
# @param [java.time.temporal.TemporalAmount, Proc, nil] for
|
1051
|
+
# Duration for which the item/thing must remain in the same state before executing the execution blocks.
|
1052
|
+
# When a proc is provided, it will be called when the rule is triggered to get the duration.
|
1053
|
+
# @param [Object, nil] attach object to be attached to the trigger
|
1002
1054
|
# @return [void]
|
1003
1055
|
#
|
1056
|
+
# @example Single item trigger
|
1057
|
+
# rule "Execute rule when a sensor changed" do
|
1058
|
+
# changed FrontMotion_Sensor
|
1059
|
+
# run { |event| logger.info("Motion detected by #{event.item.name}") }
|
1060
|
+
# end
|
1061
|
+
#
|
1004
1062
|
# @example Multiple items can be separated with a comma:
|
1005
1063
|
# rule "Execute rule when either sensor changed" do
|
1006
1064
|
# changed FrontMotion_Sensor, RearMotion_Sensor
|
@@ -1013,23 +1071,15 @@ module OpenHAB
|
|
1013
1071
|
# run { |event| logger.info("Motion detected by #{event.item.name}") }
|
1014
1072
|
# end
|
1015
1073
|
#
|
1016
|
-
# @example `
|
1017
|
-
#
|
1018
|
-
#
|
1019
|
-
# rule "Execute rule when item is changed for specified duration" do
|
1020
|
-
# changed Alarm_Mode, for: -> { Alarm_Delay.state }
|
1021
|
-
# run { logger.info("Alarm Mode Updated") }
|
1022
|
-
# end
|
1023
|
-
#
|
1024
|
-
# @example You can optionally provide `from` and `to` states to restrict the cases in which the rule executes:
|
1025
|
-
# rule "Execute rule when item is changed to specific number, from specific number, for specified duration" do
|
1026
|
-
# changed Alarm_Mode, from: 8, to: [14,12], for: 12.seconds
|
1074
|
+
# @example You can optionally provide `from` and/or `to` states to restrict the cases in which the rule executes:
|
1075
|
+
# rule "Execute rule when item is changed to specific number, from specific number" do
|
1076
|
+
# changed Alarm_Mode, from: 8, to: [14,12]
|
1027
1077
|
# run { logger.info("Alarm Mode Updated") }
|
1028
1078
|
# end
|
1029
1079
|
#
|
1030
1080
|
# @example Works with ranges:
|
1031
|
-
# rule "Execute when item changed to a range of numbers, from a range of numbers
|
1032
|
-
# changed Alarm_Mode, from: 8..10, to: 12..14
|
1081
|
+
# rule "Execute when item changed to a range of numbers, from a range of numbers" do
|
1082
|
+
# changed Alarm_Mode, from: 8..10, to: 12..14
|
1033
1083
|
# run { logger.info("Alarm Mode Updated") }
|
1034
1084
|
# end
|
1035
1085
|
#
|
@@ -1040,14 +1090,14 @@ module OpenHAB
|
|
1040
1090
|
# end
|
1041
1091
|
#
|
1042
1092
|
# @example Works with procs:
|
1043
|
-
# rule "Execute when item state is changed from an odd number, to an even number
|
1044
|
-
# changed Alarm_Mode, from: proc { |from| from.odd? }, to: proc {|to| to.even? }
|
1093
|
+
# rule "Execute when item state is changed from an odd number, to an even number" do
|
1094
|
+
# changed Alarm_Mode, from: proc { |from| from.odd? }, to: proc {|to| to.even? }
|
1045
1095
|
# run { logger.info("Alarm Mode Updated") }
|
1046
1096
|
# end
|
1047
1097
|
#
|
1048
1098
|
# @example Works with lambdas:
|
1049
|
-
# rule "Execute when item state is changed from an odd number, to an even number
|
1050
|
-
# changed Alarm_Mode, from: -> from { from.odd? }, to: -> to { to.even? }
|
1099
|
+
# rule "Execute when item state is changed from an odd number, to an even number" do
|
1100
|
+
# changed Alarm_Mode, from: -> from { from.odd? }, to: -> to { to.even? }
|
1051
1101
|
# run { logger.info("Alarm Mode Updated") }
|
1052
1102
|
# end
|
1053
1103
|
#
|
@@ -1057,6 +1107,22 @@ module OpenHAB
|
|
1057
1107
|
# run { logger.info("Alarm armed") }
|
1058
1108
|
# end
|
1059
1109
|
#
|
1110
|
+
# @example Delay the trigger until the item has been in the same state for 10 seconds
|
1111
|
+
# rule "Execute rule when item is changed for specified duration" do
|
1112
|
+
# changed Closet_Door, to: CLOSED, for: 10.seconds
|
1113
|
+
# run do
|
1114
|
+
# Closet_Light.off
|
1115
|
+
# end
|
1116
|
+
# end
|
1117
|
+
#
|
1118
|
+
# @example `for` parameter can be a proc that returns a duration:
|
1119
|
+
# Alarm_Delay << 20
|
1120
|
+
#
|
1121
|
+
# rule "Execute rule when item is changed for specified duration" do
|
1122
|
+
# changed Alarm_Mode, for: -> { Alarm_Delay.state.to_i.seconds }
|
1123
|
+
# run { logger.info("Alarm Mode Updated") }
|
1124
|
+
# end
|
1125
|
+
#
|
1060
1126
|
# @example Works with Things:
|
1061
1127
|
# rule "Execute rule when thing is changed" do
|
1062
1128
|
# changed things["astro:sun:home"], :from => :online, :to => :uninitialized
|
@@ -26,8 +26,9 @@ module OpenHAB
|
|
26
26
|
class << self
|
27
27
|
# get the block's source location, and simplify to a simple filename
|
28
28
|
def infer_rule_id_from_block(block)
|
29
|
-
file = File.basename(block.source_location.first)
|
30
|
-
"
|
29
|
+
file = File.basename(block.source_location.first, ".rb")
|
30
|
+
file = "script:#{$ctx["ruleUID"]}" if $ctx&.key?("ruleUID") && file == "<script>"
|
31
|
+
"#{file}:#{block.source_location.last}".tr(".", "_")
|
31
32
|
end
|
32
33
|
|
33
34
|
# formulate a readable rule name such as "TestSwitch received command ON" if possible
|
@@ -47,8 +48,6 @@ module OpenHAB
|
|
47
48
|
infer_rule_name_from_trigger(*config.ruby_triggers.first)
|
48
49
|
end
|
49
50
|
|
50
|
-
private
|
51
|
-
|
52
51
|
# formulate a readable rule name from a single trigger if possible
|
53
52
|
def infer_rule_name_from_trigger(trigger, items = nil, kwargs = {})
|
54
53
|
case trigger
|
@@ -71,6 +70,8 @@ module OpenHAB
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
73
|
+
private
|
74
|
+
|
74
75
|
# formulate a readable rule name from an item-type trigger
|
75
76
|
def infer_rule_name_from_item_trigger(trigger, items, kwargs)
|
76
77
|
kwargs.delete(:command) if kwargs[:command] == [nil]
|
@@ -85,10 +86,10 @@ module OpenHAB
|
|
85
86
|
|
86
87
|
trigger_name = trigger.to_s.tr("_", " ")
|
87
88
|
item_names = items.map do |item|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
case item
|
90
|
+
when GroupItem::Members then "#{item.group.name}.members"
|
91
|
+
when Core::Items::Item then item.name
|
92
|
+
else item.to_s
|
92
93
|
end
|
93
94
|
end
|
94
95
|
name = "#{format_array(item_names)} #{trigger_name}"
|
@@ -13,8 +13,10 @@ module OpenHAB
|
|
13
13
|
# and a setter with any number of arguments or a block.
|
14
14
|
#
|
15
15
|
# @param [String] name of the property
|
16
|
+
# @yield Block to call when the property is set
|
17
|
+
# @yieldparam [Object] value the value being set
|
16
18
|
#
|
17
|
-
def prop(name)
|
19
|
+
def prop(name, &assignment_block)
|
18
20
|
# rubocop rules are disabled because this method is dynamically defined on the calling
|
19
21
|
# object making calls to other methods in this module impossible, or if done on methods
|
20
22
|
# in this module than instance variable belong to the module not the calling class
|
@@ -30,6 +32,7 @@ module OpenHAB
|
|
30
32
|
elsif block
|
31
33
|
instance_variable_set(:"@#{name}", block)
|
32
34
|
end
|
35
|
+
assignment_block&.call(instance_variable_get(:"@#{name}"))
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -41,9 +41,9 @@ module OpenHAB
|
|
41
41
|
#
|
42
42
|
# @return [org.openhab.core.automation.Trigger] openHAB trigger
|
43
43
|
#
|
44
|
-
def append_trigger(type:, config:, attach: nil, conditions: nil)
|
44
|
+
def append_trigger(type:, config:, attach: nil, conditions: nil, label: nil)
|
45
45
|
config.transform_keys!(&:to_s)
|
46
|
-
RuleTriggers.trigger(type: type, config: config).tap do |trigger|
|
46
|
+
RuleTriggers.trigger(type: type, config: config, label: label).tap do |trigger|
|
47
47
|
logger.trace("Appending trigger (#{trigger.inspect}) attach (#{attach}) conditions(#{conditions})")
|
48
48
|
@triggers << trigger
|
49
49
|
@attachments[trigger.id] = attach if attach
|
@@ -56,15 +56,17 @@ module OpenHAB
|
|
56
56
|
#
|
57
57
|
# @param [String] type of trigger
|
58
58
|
# @param [Map] config map
|
59
|
+
# @param [String] label for the trigger
|
59
60
|
#
|
60
61
|
# @return [org.openhab.core.automation.Trigger] configured by type and supplied config
|
61
62
|
#
|
62
|
-
def self.trigger(type:, config:)
|
63
|
+
def self.trigger(type:, config:, label: nil)
|
63
64
|
logger.trace("Creating trigger of type '#{type}' config: #{config}")
|
64
65
|
org.openhab.core.automation.util.TriggerBuilder.create
|
65
66
|
.with_id(uuid)
|
66
67
|
.with_type_uid(type)
|
67
68
|
.with_configuration(Core::Configuration.new(config))
|
69
|
+
.with_label(label)
|
68
70
|
.build
|
69
71
|
end
|
70
72
|
|
@@ -44,22 +44,27 @@ module OpenHAB
|
|
44
44
|
# @see BuilderDSL#$1
|
45
45
|
def def_terse_rule(trigger)
|
46
46
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
47
|
-
def #{trigger}(*args, id: nil, name: nil, description: nil,
|
48
|
-
tag: nil, tags: nil, on_load: false, **kwargs, &block)
|
49
|
-
raise ArgumentError, "Block is required" unless block
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
+
replace = nil # replace = nil
|
52
|
+
unless id # unless id
|
53
|
+
replace = false # replace = false
|
54
|
+
id = NameInference.infer_rule_id_from_block(block) # id = NameInference.infer_rule_id_from_block(block)
|
55
|
+
end # end
|
56
|
+
script = block.source rescue nil # script = block.source rescue nil
|
57
|
+
caller_binding = block.binding # caller_binding = block.binding
|
58
|
+
rule name, id: id, replace: replace, script: script, # rule name, id: id, replace: replace, script: script
|
59
|
+
binding: caller_binding do # binding: caller_binding do
|
60
|
+
self.on_load if on_load # self.on_load if on_load
|
61
|
+
self.description(description) if description # self.description(description) if description
|
62
|
+
self.tags(*Array.wrap(tag), *Array.wrap(tags)) # self.tags(*Array.wrap(tag), *Array.wrap(tags))
|
63
|
+
#{trigger}(*args, **kwargs) # changed(*args, **kwargs)
|
64
|
+
run(&block) # run(&block)
|
65
|
+
end # end
|
66
|
+
end # end
|
67
|
+
module_function #{trigger.inspect} # module_function :changed
|
63
68
|
RUBY
|
64
69
|
end
|
65
70
|
end
|
@@ -19,18 +19,26 @@ module OpenHAB
|
|
19
19
|
# @param [Core::Items::Item, Core::Items::GroupItem::Members] item item to create trigger for
|
20
20
|
# @param [Core::Types::State, Symbol, #===, nil] from state to restrict trigger to
|
21
21
|
# @param [Core::Types::State, Symbol, #===, nil] to state to restrict trigger to
|
22
|
-
# @param [Duration, nil] duration duration to delay trigger until to state is met
|
22
|
+
# @param [Duration, Proc, nil] duration duration to delay trigger until to state is met
|
23
23
|
# @param [Object] attach object to be attached to the trigger
|
24
24
|
#
|
25
25
|
# @return [org.openhab.core.automation.Trigger] openHAB triggers
|
26
26
|
#
|
27
27
|
def trigger(item:, from:, to:, duration:, attach:)
|
28
28
|
if duration
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
if logger.trace?
|
30
|
+
item_name = item.respond_to?(:name) ? item.name : item.to_s
|
31
|
+
logger.trace("Creating Changed Wait Change Trigger for Item(#{item_name}) Duration(#{duration}) " \
|
32
|
+
"To(#{to}) From(#{from}) Attach(#{attach})")
|
33
|
+
end
|
32
34
|
conditions = Conditions::Duration.new(to: to, from: from, duration: duration)
|
33
|
-
|
35
|
+
label = NameInference.infer_rule_name_from_trigger(:changed,
|
36
|
+
[item],
|
37
|
+
from: from,
|
38
|
+
to: to,
|
39
|
+
duration: duration)
|
40
|
+
|
41
|
+
changed_trigger(item: item, from: nil, to: nil, attach: attach, conditions: conditions, label: label)
|
34
42
|
else
|
35
43
|
# swap from/to w/ nil if from/to need to be processed in Ruby
|
36
44
|
# rubocop:disable Style/ParallelAssignment
|
@@ -64,7 +72,7 @@ module OpenHAB
|
|
64
72
|
# @param [Object] attach object to be attached to the trigger
|
65
73
|
# @return [org.openhab.core.automation.Trigger]
|
66
74
|
#
|
67
|
-
def changed_trigger(item:, from:, to:, attach: nil, conditions: nil)
|
75
|
+
def changed_trigger(item:, from:, to:, attach: nil, conditions: nil, label: nil)
|
68
76
|
type, config = case item
|
69
77
|
when GroupItem::Members
|
70
78
|
group(group: item, from: from, to: to)
|
@@ -74,7 +82,7 @@ module OpenHAB
|
|
74
82
|
else
|
75
83
|
item(item: item, from: from, to: to)
|
76
84
|
end
|
77
|
-
append_trigger(type: type, config: config, attach: attach, conditions: conditions)
|
85
|
+
append_trigger(type: type, config: config, attach: attach, conditions: conditions, label: label)
|
78
86
|
end
|
79
87
|
|
80
88
|
#
|
@@ -301,7 +301,7 @@ module OpenHAB
|
|
301
301
|
Core.automation_manager.add_trigger_type(org.openhab.core.automation.type.TriggerType.new(
|
302
302
|
WATCH_TRIGGER_MODULE_ID,
|
303
303
|
nil,
|
304
|
-
"
|
304
|
+
"a path change event is detected",
|
305
305
|
"Triggers when a path change event is detected",
|
306
306
|
nil,
|
307
307
|
org.openhab.core.automation.Visibility::VISIBLE,
|
data/lib/openhab/dsl/version.rb
CHANGED
data/lib/openhab/dsl.rb
CHANGED
@@ -56,8 +56,14 @@ module OpenHAB
|
|
56
56
|
# @!group Rule Creation
|
57
57
|
|
58
58
|
# (see Rules::Builder#rule)
|
59
|
-
def rule(name = nil, **kwargs, &block)
|
60
|
-
rules.build { rule(name, **kwargs, &block) }
|
59
|
+
def rule(name = nil, id: nil, **kwargs, &block)
|
60
|
+
rules.build { rule(name, id: id, **kwargs, &block) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Creates a rule that will remove existing rules with the same id, even when the id has been inferred.
|
64
|
+
# @see rule
|
65
|
+
def rule!(name = nil, id: nil, **kwargs, &block)
|
66
|
+
rules.build { rule(name, id: id, replace: true, **kwargs, &block) }
|
61
67
|
end
|
62
68
|
|
63
69
|
# (see Rules::Builder#scene)
|
@@ -65,11 +71,27 @@ module OpenHAB
|
|
65
71
|
rules.build { scene(name, description: description, id: id, tag: tag, tags: tags, **kwargs, &block) }
|
66
72
|
end
|
67
73
|
|
74
|
+
# Creates a scene that will remove existing rules/scenes with the same id, even when the id has been inferred.
|
75
|
+
# @see scene
|
76
|
+
def scene!(name = nil, description: nil, id: nil, tag: nil, tags: nil, **kwargs, &block)
|
77
|
+
rules.build do
|
78
|
+
scene(name, description: description, id: id, tag: tag, tags: tags, replace: true, **kwargs, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
68
82
|
# (see Rules::Builder#script)
|
69
83
|
def script(name = nil, description: nil, id: nil, tag: nil, tags: nil, **kwargs, &block)
|
70
84
|
rules.build { script(name, description: description, id: id, tag: tag, tags: tags, **kwargs, &block) }
|
71
85
|
end
|
72
86
|
|
87
|
+
# Creates a script that will remove existing rules/scripts with the same id, even when the id has been inferred.
|
88
|
+
# @see script
|
89
|
+
def script!(name = nil, description: nil, id: nil, tag: nil, tags: nil, **kwargs, &block)
|
90
|
+
rules.build do
|
91
|
+
script(name, description: description, id: id, tag: tag, tags: tags, replace: true, **kwargs, &block)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
73
95
|
# @!group Rule Support
|
74
96
|
|
75
97
|
# rubocop:disable Layout/LineLength
|
@@ -7,6 +7,15 @@ module OpenHAB
|
|
7
7
|
include org.openhab.core.persistence.ModifiablePersistenceService
|
8
8
|
include Singleton
|
9
9
|
|
10
|
+
OPERATOR_TO_SYMBOL = {
|
11
|
+
EQ: :==,
|
12
|
+
NEQ: :!=,
|
13
|
+
GT: :>,
|
14
|
+
LT: :<,
|
15
|
+
GTE: :>=,
|
16
|
+
LTE: :<=
|
17
|
+
}.freeze
|
18
|
+
|
10
19
|
class HistoricItem
|
11
20
|
include org.openhab.core.persistence.HistoricItem
|
12
21
|
|
@@ -134,9 +143,7 @@ module OpenHAB
|
|
134
143
|
|
135
144
|
range = first_index...last_index
|
136
145
|
|
137
|
-
operator = filter.operator
|
138
|
-
operator = "==" if operator == "="
|
139
|
-
|
146
|
+
operator = OPERATOR_TO_SYMBOL[filter.operator]
|
140
147
|
block = lambda do |i|
|
141
148
|
next if filter.state && !item_history[i].state.send(operator, filter.state)
|
142
149
|
|
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.
|
4
|
+
version: 5.18.1
|
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-
|
13
|
+
date: 2024-04-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -485,7 +485,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
485
485
|
- !ruby/object:Gem::Version
|
486
486
|
version: '0'
|
487
487
|
requirements: []
|
488
|
-
rubygems_version: 3.5.
|
488
|
+
rubygems_version: 3.5.7
|
489
489
|
signing_key:
|
490
490
|
specification_version: 4
|
491
491
|
summary: JRuby Helper Libraries for openHAB Scripting
|