Class: OpenHAB::DSL::Rules::Builder

Inherits:
Object
  • Object
show all
Includes:
Core::EntityLookup, Terse
Defined in:
lib/openhab/dsl/rules/builder.rb

Overview

A rules builder allows you to create openHAB rules.

Note that all methods on this module are also availabe directly on OpenHAB::DSL.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Core::EntityLookup

#items, #method_missing, #things

Methods included from Terse

#changed, #channel, #channel_linked, #channel_unlinked, #cron, #every, #item_added, #item_removed, #item_updated, #on_start, #received_command, #thing_added, #thing_removed, #thing_updated, #updated

Constructor Details

#initialize(provider) ⇒ Builder

Returns a new instance of Builder.



33
34
35
# File 'lib/openhab/dsl/rules/builder.rb', line 33

def initialize(provider)
  @provider = Core::Rules::Provider.current(provider)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class OpenHAB::Core::EntityLookup

Instance Attribute Details

#providerorg.openhab.core.automation.RuleProvider (readonly)



31
32
33
# File 'lib/openhab/dsl/rules/builder.rb', line 31

def provider
  @provider
end

Instance Method Details

#rule(name = nil, id: nil, replace: nil, script: nil, binding: nil) {|rule| ... } ⇒ Core::Rules::Rule?

Create a new rule

The rule must have at least one trigger and one execution block. To create a "script" without any triggers, use script.

When explicit id is not provided, the rule's ID will be inferred from the block's source location, and a suffix will be added to avoid clashing against existing rules.

When an explicit id is provided and an existing rule with the same id already exists, the rule will not be created, and the method will return nil.

To ensure that a rule is created even when the same id already exists, use OpenHAB::DSL.rule! or call rules.remove to remove any existing rule prior to creating the new rule.

Examples:

rule "name" do
  <one or more triggers>
  <one or more execution blocks>
  <zero or more guards>
end

Create a rule with an explicit id, deleting any existing rule with the same id

rule! "name", id: "my_happy_day_reminder" do
  every :day
  run { logger.info "Happy new day!" }
end

Parameters:

  • name (String) (defaults to: nil)

    The rule name

  • id (String) (defaults to: nil)

    The rule's ID. This can also be defined in the block using uid.

Yields:

Yield Parameters:

  • rule (Rules::BuilderDSL)

    Optional parameter to access the rule configuration from within execution blocks and guards.

Returns:

Raises:

  • (ArgumentError)

See Also:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/openhab/dsl/rules/builder.rb', line 76

def rule(name = nil, id: nil, replace: nil, script: nil, binding: nil, &block)
  raise ArgumentError, "Block is required" unless block

  inferred_id = nil
  id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
  script ||= block.source rescue nil # rubocop:disable Style/RescueModifier

  builder = nil

  ThreadLocal.thread_local(openhab_rule_type: "rule", openhab_rule_uid: id) do
    builder = BuilderDSL.new(binding || block.binding)
    builder.uid(id)
    builder.instance_exec(builder, &block)

    if replace
      logger.debug { "Removing existing rule '#{builder.uid}'." } if DSL.rules.remove(builder.uid)
    elsif replace.nil?
      id_not_inferred = inferred_id.nil? || inferred_id != builder.uid
      if id_not_inferred && (existing_rule = $rules.get(builder.uid))
        logger.warn "Rule '#{builder.uid}' is not created because " \
                    "another rule/script/scene with the same id already exists: #{existing_rule.inspect}."
        return nil
      end
    end

    builder.guard = Guard.new(run_context: builder.caller,
                              only_if: builder.only_if,
                              not_if: builder.not_if)

    name ||= NameInference.infer_rule_name(builder)
    name ||= id

    builder.name(name)
    logger.trace { builder.inspect }
    builder.build(provider, script)
  end
end

#scene(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil) { ... } ⇒ Core::Rules::Rule?

Create a new scene

A scene is a rule with no triggers. It can be called by various other actions, such as the Run Rules action.

Parameters:

Yields:

  • [] Block executed when the script is executed.

Returns:

Raises:

  • (ArgumentError)

See Also:

  • DSL.rule
  • DSL.scene!


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/openhab/dsl/rules/builder.rb', line 206

def scene(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil, &block)
  raise ArgumentError, "Block is required" unless block

  inferred_id = nil # rubocop:disable Lint/UselessAssignment
  id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
  name ||= id
  script ||= block.source rescue nil # rubocop:disable Style/RescueModifier

  if replace
    logger.debug { "Removing existing rule '#{id}'." } if DSL.rules.remove(id)
  elsif inferred_id.nil? && (existing_rule = $rules.get(id))
    logger.warn "Scene '#{id}' is not created because " \
                "another script/scene/rule with the same id already exists: #{existing_rule.inspect}."
    return nil
  end

  builder = nil
  ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
    builder = BuilderDSL.new(block.binding)
    builder.uid(id)
    builder.tags("Scene", *Array.wrap(tag), *Array.wrap(tags))
    builder.name(name)
    builder.description(description)
    builder.script(&block)
    logger.trace { builder.inspect }
    builder.build(provider, script)
  end
end

#script(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil) { ... } ⇒ Core::Rules::Rule?

Create a new script

A script is a rule with no triggers. It can be called by various other actions, such as the Run Rules action, or by calling Core::Rules::Rule#trigger.

Scripts can be executed with some additional context, similar to method parameters (see Core::Rules::Rule#trigger). The context can be accessed from within the script's execution block as a "local" variable.

Examples:

A simple script

# return the script object into a variable
door_check = script "Check all doors", id: "door_check", tags: :security do
  open_doors = gDoors.members.select(&:open?).map(&:label).join(", ")
  Notification.send("The following doors are open: #{open_doors}") unless open_doors.empty?
end

# run is an alias of trigger
door_check.run

A script with context

# This script expects to be called with `message` as context/parameter
DESTINATION_EMAIL = "myemail@example.com"
script "Send Notifications", id: "send_alert" do
  Notification.send(message)
  things["mail:smtp:local"].send_mail(DESTINATION_EMAIL, "OpenHAB Alert", message)
end

rules.scripts["send_alert"].run(message: "The door is open!")

Parameters:

Yields:

  • [] Block executed when the script is executed.

Returns:

Raises:

  • (ArgumentError)

See Also:



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/openhab/dsl/rules/builder.rb', line 158

def script(name = nil, description: nil, id: nil, tag: nil, tags: nil, replace: false, script: nil, &block)
  raise ArgumentError, "Block is required" unless block

  inferred_id = nil # rubocop:disable Lint/UselessAssignment it is used below
  id ||= inferred_id = NameInference.infer_rule_id_from_block(block)
  name ||= id
  script ||= block.source rescue nil # rubocop:disable Style/RescueModifier

  if replace
    logger.debug { "Removing existing rule '#{id}'." } if DSL.rules.remove(id)
  elsif inferred_id.nil? && (existing_rule = $rules.get(id))
    logger.warn "Script '#{id}' is not created because " \
                "another script/scene/rule with the same id already exists: #{existing_rule.inspect}."
    return nil
  end

  builder = nil
  ThreadLocal.thread_local(openhab_rule_type: "script", openhab_rule_uid: id) do
    builder = BuilderDSL.new(block.binding)
    builder.uid(id)
    builder.tags("Script", *Array.wrap(tag), *Array.wrap(tags))
    builder.name(name)
    builder.description(description)
    builder.script(&block)
    logger.trace { builder.inspect }
    builder.build(provider, script)
  end
end