Condense multiple automations

I have a bunch of radiator valves which show up as climate devices in HA.
They however do not set the HVAC mode (They aren’t true control devices as they do not control the actual heating, just that valve).

I have setup a couple of automations that look like

alias: Set Kitchen TRV HVAC
description: ""
trigger:
  - platform: template
    value_template: >-
      {{ state_attr('climate.kitchen_trv', 'temperature') >
      state_attr('climate.kitchen_trv', 'local_temperature')}}
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: heat
    target:
      entity_id:
        - climate.kitchen_trv
mode: single

and

alias: Set Kitchen TRV HVAC Off
description: ""
trigger:
  - platform: template
    value_template: >-
      {{ state_attr('climate.kitchen_trv', 'temperature') <=
      state_attr('climate.kitchen_trv', 'local_temperature')}}
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: "off"
    target:
      entity_id:
        - climate.kitchen_trv
mode: single

which works OK but if seems a bit OTT to have to create two automations for each device (not to mention that if I ever want to tweak them to do something else I would need to go in and amend lots of individual automations).

Is there a way I could condense this down? Can I use a template within the set_hvac_mode action and combine both automations into one?
Is there a way I can make this better for multiple devices? A blueprint I guess would allow we me create the automations easily enough but if I wanted to change them I would still be needing to amend or recreate several automations…

Would be nice if I could make this a bit more modular / reusable. How do I do that?

There are tons of ways to approach this depending how condensed you are trying to get it. One option would be something like…

alias: Set Kitchen TRV HVAC
description: ""
trigger_variables:
  trv: climate.kitchen_trv
trigger:
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') > state_attr(trv, 'local_temperature')}}"
    id: heat
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') <= state_attr(trv, 'local_temperature')}}"
    id: 'off'
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: "{{trigger.id}}"
    target:
      entity_id: "{{trv}}"
mode: single

You could actually take that a step further and put all the trvs into a single automation since the templates only reference a single entity:

alias: Combined Set TRV HVAC
description: ""
trigger_variables:
  kitchen: climate.kitchen_trv
  lr: climate.living_room_trv
trigger:
  - platform: template
    value_template: "{{ state_attr(kitchen, 'temperature') > state_attr(kitchen, 'local_temperature')}}"
    id: heat
  - platform: template
    value_template: "{{ state_attr(kitchen, 'temperature') <= state_attr(kitchen, 'local_temperature')}}"
    id: 'off'
  - platform: template
    value_template: "{{ state_attr(lr, 'temperature') > state_attr(lr, 'local_temperature')}}"
    id: heat
  - platform: template
    value_template: "{{ state_attr(lr, 'temperature') <= state_attr(lr, 'local_temperature')}}"
    id: 'off'
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: "{{trigger.id}}"
    target:
      entity_id: "{{ trigger.entity_id }}"
mode: queued
2 Likes

Ahh trigger variables. That makes sense.

I translated slightly to a blueprint which works OK but obviously won’t work when run manually so I need to wait for the state to change for the automation to trigger.

blueprint:
  name: Set TRV HVAC Status
  description: Set TRV to Heat / Off depending on temperature
  domain: automation
  input:
    input_trv:
      name: TRV
      description: The TRV to set
      selector:
        entity:
          domain: climate
trigger_variables:
  trv: !input input_trv
trigger:
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') > state_attr(trv, 'local_temperature')}}"
    id: "heat"
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') <= state_attr(trv, 'local_temperature')}}"
    id: "off"
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: "{{trigger.id}}"
    target:
      entity_id: "{{trv}}"
mode: single

I did try to template the actual value with something like

action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: >
      {% if (state_attr(trv, 'temperature') > state_attr(trv, 'local_temperature')) %}
      "heat"
      {% else %}
      "off"
      {% end if %}

but it complained about expecting a string from a dictionary so I guess I can’t put a template here…
Is there a way to do this so that the state will be set if you run the automation and when HA is restarted

blueprint:
  name: Set TRV HVAC Status
  description: Set TRV to Heat / Off depending on temperature
  domain: automation
  input:
    input_trv:
      name: TRV
      description: The TRV to set
      selector:
        entity:
          domain: climate
trigger_variables:
  trv: !input input_trv
trigger:
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') > state_attr(trv, 'local_temperature')}}"
  - platform: template
    value_template: "{{ state_attr(trv, 'temperature') <= state_attr(trv, 'local_temperature')}}"
  - platform: homeassistant
    event: start
condition: []
action:
  - service: climate.set_hvac_mode
    data:
      hvac_mode: |
        {{ iif(not state_attr(trv, 'temperature') <= state_attr(trv, 'local_temperature'), 'heat', 'off', 'off') }}
    target:
      entity_id: !input input_trv
mode: single
1 Like

needed a slight tweak to state_attr rather than states and had to throw in some float conversions but kind of works. When HA starts the states aren’t there from MQTT and it doesn’t seem to update when they do come through but I will look at that (I think it might just be a missing float conversion)

It does sit uneasy that I have to keep repeating code. I am guessing I can’t nest variables so I couldn’t do

trigger_variables:
  trv: !input input_trv
  trv_set_temp: state_attr(trv, 'temperature')

but I guess I could do

trigger_variables:
  trv_set_temp: state_attr(!input trv, 'temperature')

?

I am still not quite sure why my initial template didn’t work but the single line if statementt does

I thought I had answered that in my post, but I must have erased it… Your’s should work, but it wasn’t properly indented.

I don’t think that would work. IIRC, the variable would save the string value with the !inputsubstitution i.e. "state_attr('climate.kitchen_trv', 'temperature')". Then the template {{trv_set_temp}} would just return the string value, not the rendered value of the state_attr() function.

1 Like