Reusable variable in automation

Hello,

I’m trying to make my security system smarter with Home-Assistant.
I’m trying to achieve the following: when the security system is armed in home mode (stay or night), the humidity in the bathroom is above a threshold, and the window is opened, do not trigger the alarm.

Some information on my system:

  • I have a group of binary sensors for outside contacts (all windows and doors that can be an entry/exit point)
  • I have a group of binary sensors for inside contacts (all windows and doors that do not represent interaction with the outside world; those are used when armed away)
  • I have motion, temperature, and humidity sensors in the bathrooms
  • I have a virtual sensor (input_number) where I set the threshold for humidity in the bathroom
  • I have a virtual sensor for the number of contacts that have been in an open state at the moment of arming
  • I have a virtual sensor for the names of contacts that have been in an open state at the moment of arming
  • I have a virtual sensor that stores the diff between the number of contacts that are now open vs the number of open contacts at the moment of arm
  • I have automation in place, so when I close contact while armed, I get alerts/notifications and reset virtual sensors as I am arming
  • I have automation that, if it determines that a new contact has opened, will trigger an alarm
  • I have a macro function that can tell me the friendly name of the contact that was opened or closed in such a case (this may be a hack, but in my limited knowledge of the platform, I do not know of another solution where things are dynamically configured) it is a string separated by “;” where at index 0 I get true/false if there was an error, at index 1 I get the error message, at index 2 I get the opened contact name and at index 3 I get the closed contact name

Now, my problem is that my automation looks like this:

alias: "security: trigger-alarm-stay"
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.alarm_new_door_opened
    to: "1"
condition:
  - condition: or
    conditions:
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_home
        enabled: true
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_night
        enabled: true
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_away
        enabled: true
action:
  - if:
      - condition: template
        value_template: >-
          {# check that the opened contact is 1.BS window #}

          {% from 'contact_sensor_changes.jinja' import contact_sensor_changes
          %}

          {% set result = contact_sensor_changes(true, true)|trim %}

          {% set result = result.split(';') %} 

          {{ result[2] == state_attr('binary_sensor.1_bs_window_contact',
          'friendly_name') }}
      - condition: numeric_state
        entity_id: sensor.1_bs_aerq_relative_humidity_measurement
        above: input_number.humidity_bathroom_threshold
      - condition: state
        entity_id: binary_sensor.1_bs_window_contact
        state: "on"
    then:
      - parallel:
          - service: notify.mobile_phones
            data:
              title: "security-system: opened contact"
              message: >-
                {% from 'contact_sensor_changes.jinja' import
                contact_sensor_changes %} {% set result =
                contact_sensor_changes(true, true)|trim %} {% set result =
                result.split(';') %} {% if result[2] %}
                  Opened contact is {{ result[2] }}, skipped alarm trigger as the humidity is above thredshold.
                {% elif result[0]=='True' %}
                  There was an error trying to determine opened contact -> {{ result[1] }}
                {% endif %}
          - service: script.alarm_reset_helpers
            data: {}
    else:
      - if:
          - condition: template
            value_template: >-
              {# check that the opened contact is 0.BJ window #}

              {% from 'contact_sensor_changes.jinja' import
              contact_sensor_changes %}

              {% set result = contact_sensor_changes(true, true)|trim %}

              {% set result = result.split(';') %} 

              {{ result[2] == state_attr('binary_sensor.0_bj_window_contact',
              'friendly_name') }}
          - condition: numeric_state
            entity_id: sensor.0_bj_aerq_relative_humidity_measurement
            above: input_number.humidity_bathroom_threshold
          - condition: state
            entity_id: binary_sensor.0_bj_window_contact
            state: "on"
        then:
          - parallel:
              - service: notify.mobile_phones
                data:
                  title: "security-system: opened contact"
                  message: >-
                    {% from 'contact_sensor_changes.jinja' import
                    contact_sensor_changes %} {% set result =
                    contact_sensor_changes(true, true)|trim %} {% set result =
                    result.split(';') %} {% if result[2] %}
                      Opened contact is {{ result[2] }}, skipped alarm trigger as the humidity is above thredshold.
                    {% elif result[0]=='True' %}
                      There was an error trying to determine opened contact -> {{ result[1] }}
                    {% endif %}
              - service: script.alarm_reset_helpers
                data: {}
        else:
          - parallel:
              - service: notify.mobile_phones
                data:
                  title: "security-system: alarm trigger"
                  message: >-
                    {% from 'contact_sensor_changes.jinja' import
                    contact_sensor_changes %} {% set result =
                    contact_sensor_changes(true, true)|trim %} {% set result =
                    result.split(';') %} A door/window has been opened, open
                    contacts are {{ states('sensor.info_open_doors') }}. {% if
                    result[2] %}
                      Opened contact is {{ result[2] }}
                    {% elif result[0]=='True' %}
                      There was an error trying to determine closed contact -> {{ result[1] }}
                    {% endif %}
              - service: alarm_control_panel.alarm_trigger
                data: {}
                target:
                  entity_id: alarm_control_panel.home_alarm
                enabled: true
mode: single

Notice how many times I have the same part of the template…
Is there any way to put the result of the macro in a variable (multiple variables) and use them in my automation?

After exposing what I tried to do, I was thinking about blueprints … and then tried to follow the same concept, and it worked.

Final code looks like this:

alias: "security: trigger-alarm-stay"
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.alarm_new_door_opened
    to: "1"
condition:
  - condition: or
    conditions:
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_home
        enabled: true
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_night
        enabled: true
      - condition: state
        entity_id: alarm_control_panel.home_alarm
        state: armed_away
        enabled: true
variables:
  contact_sensor_opened: >-
    {% from 'contact_sensor_changes.jinja' import contact_sensor_changes %} {%
    set result = contact_sensor_changes(true, true)|trim %} {{ result }}
  open_contact: >-
    {% set result = contact_sensor_opened|trim %} {% set result =
    result.split(';') %} {{ result[2] }}
  notification_message_skip: >-
    {% set result = contact_sensor_opened|trim %} {% set result =
    result.split(';') %} {% if result[2] %}
      Opened contact is {{ result[2] }}, skipped alarm trigger as the humidity is above the threshold.
    {% elif result[0]=='True' %}
      There was an error trying to determine opened contact -> {{ result[1] }}
    {% endif %}
  notification_message_triger: >-
    {% set result = contact_sensor_opened|trim %} {% set result =
    result.split(';') %} A door/window has been opened, open contacts are {{
    states('sensor.info_open_doors') }}. {% if result[2] %}
      Opened contact is {{ result[2] }}.
    {% elif result[0]=='True' %}
      There was an error trying to determine opened contact -> {{ result[1] }}
    {% endif %}
action:
  - if:
      - condition: template
        value_template: >-
          {# check that the opened contact is 1.BS window #} {% set result =
          open_contact|trim %} {{ result ==
          state_attr('binary_sensor.1_bs_window_contact', 'friendly_name') }}
      - condition: numeric_state
        entity_id: sensor.1_bs_aerq_relative_humidity_measurement
        above: input_number.humidity_bathroom_threshold
        enabled: true
      - condition: state
        entity_id: binary_sensor.1_bs_window_contact
        state: "on"
    then:
      - parallel:
          - service: notify.mobile_phones
            data:
              title: "security-system: opened contact"
              message: "{% set result = notification_message_skip|trim %} {{ result }}"
          - service: script.alarm_reset_helpers
            data: {}
    else:
      - if:
          - condition: template
            value_template: >-
              {# check that the opened contact is 0.BJ window #} {% set result =
              open_contact|trim %} {{ result ==
              state_attr('binary_sensor.0_bj_window_contact', 'friendly_name')
              }}
          - condition: numeric_state
            entity_id: sensor.0_bj_aerq_relative_humidity_measurement
            above: input_number.humidity_bathroom_threshold
            enabled: true
          - condition: state
            entity_id: binary_sensor.0_bj_window_contact
            state: "on"
        then:
          - parallel:
              - service: notify.mobile_phones
                data:
                  title: "security-system: opened contact"
                  message: >-
                    {% set result = notification_message_skip|trim %} {{ result
                    }}
              - service: script.alarm_reset_helpers
                data: {}
        else:
          - parallel:
              - service: notify.mobile_phones
                data:
                  title: "security-system: alarm trigger"
                  message: >-
                    {% set result = notification_message_triger|trim %} {{
                    result }}
              - service: alarm_control_panel.alarm_trigger
                data: {}
                target:
                  entity_id: alarm_control_panel.home_alarm
                enabled: true
    enabled: true
mode: single

Maybe it can be improved, but now I’m happier with how it looks and significantly reduced duplication.