Fan template with 2 relays

I’ve got a fan who’s state/speed is controlled with esphome and two relays - exposed to homeassistant as switches:
High-resistance relay closed for low speed.
Low-resistance relay closed for high speed.
Both relays closed for medium speed.

The esp is handling the physical buttons on the fan nicely.

I’m struggling with the set_speed part of the template. I’ve pseudocoded it out below. Can anybody point me in the right direction?

Thanks

fan:
  - platform: template
    fans:
      office_fan:
        speed_template: >
          {% if is_state('switch.office_fan_low_speed', 'on') and is_state('switch.office_fan_medium_speed', 'on') %} 
            medium
          {% elif is_state('switch.office_fan_low_speed', 'on') %}
            low
          {% elif is_state('switch.office_fan_medium_speed', 'on') %}
            high 
          {% endif %}
        value_template: >
          {% if is_state('switch.office_fan_low_speed', 'on') or is_state('switch.office_fan_medium_speed', 'on') %} 
            on 
          {% else %} 
            off 
          {% endif %}"
        turn_on:
          service: switch.turn_on
          data_template: 
            entity_id: switch.office_fan_low_speed
        turn_off:
          - service: switch.turn_off
            data_template: 
              entity_id: switch.office_fan_low_speed
          - service: switch.turn_off
            data_template: 
              entity_id: switch.office_fan_medium_speed
        set_speed:
          {{if speed = low}}
              - service: switch.turn_ON
                 data_template: 
                 entity_id: switch.office_fan_LOW_speed
              - service: switch.turn_OFF
                 data_template: 
                 entity_id: switch.office_fan_MEDIUM_speed
          {{if speed = medium}}
              - service: switch.turn_ON
                 data_template: 
                 entity_id: switch.office_fan_LOW_speed
              - service: switch.turn_ON
                 data_template: 
                 entity_id: switch.office_fan_MEDIUM_speed
          {{if speed = high}}
              - service: switch.turn_OFF
                 data_template: 
                 entity_id: switch.office_fan_LOW_speed
              - service: switch.turn_ON
                 data_template: 
                 entity_id: switch.office_fan_MEDIUM_speed
1 Like

When only this switch is on it’s LOW speed:

switch.office_fan_low_speed

Yet for some reason the switch used to set HIGH speed is called:

switch.office_fan_medium_speed

and to set MEDIUM speed both the low and medium switches are turned on. :thinking:

May I suggest that you rename this:

switch.office_fan_medium_speed

to this:

switch.office_fan_high_speed

That will make it less confusing when composing the template.

1 Like

Here’s what I suggest you do.

Create an input_boolean and an input_text. They will be used to track the Office Fan’s power-state and speed, respectively.

input_boolean:
  office_fan:
    name: Office Fan Power

input_text:
  office_fan:
    name: Office Fan Speed

The following Template Fan assumes you have renamed
switch.office_fan_medium_speed
to
switch.office_fan_high_speed

I have tested it on my system and confirmed it works. Let me know if it works for you.

fan:
  - platform: template
    fans:
      office_fan:
        value_template: "{{states('input_boolean.office_fan')}}"
        speed_template: "{{states('input_text.office_fan')}}"
        turn_on:
          - service: input_text.set_value
            data:
              entity_id: input_text.office_fan
              value: 'low'
          - service: homeassistant.turn_on
            entity_id: switch.office_fan_low_speed, input_boolean.office_fan
        turn_off:
          - service: homeassistant.turn_off
            entity_id: switch.office_fan_low_speed, switch.office_fan_high_speed, input_boolean.office_fan
        set_speed:
          - service_template: "switch.turn_{{'on' if speed in ['low', 'medium'] else 'off'}}"
            entity_id: switch.office_fan_low_speed
          - service_template: "switch.turn_{{'on' if speed in ['high', 'medium'] else 'off'}}"
            entity_id: switch.office_fan_high_speed
          - service: input_text.set_value
            data_template:
              entity_id: input_text.office_fan
              value: '{{speed}}'
2 Likes

Stumbled across this post when looking for a solution to a similar setup. I have a two speed fan with two speed circuits, low and high speed. I have a relay for each, with the high speed common fed from the low NC relay. This prevents both circuits from being turned on at the same time.

In HA, I needed a fan where:
Off: relay1=off, relay2=off
Low: relay1=on, relay2=off
High: relay1=off, relay2=on.

After adding both relays as MQTT switches, here’s the config I used for the fan. Hope this helps anyone doing something similar!

  - platform: template
    fans:
      stove_fan:
        friendly_name: "Stove Fan"
        value_template: >
          {%- if states.switch.stove_fan_relay_low.state == 'on' or states.switch.stove_fan_relay_high.state == 'on' -%} on 
          {%- else -%} off
          {%- endif %}
          
        percentage_template: >
          {%- if states.switch.stove_fan_relay_low.state == 'on' -%} 50 
          {%- elif states.switch.stove_fan_relay_high.state == 'on' -%} 100
          {%- else -%} 0
          {%- endif %}

        turn_on:
          service: homeassistant.turn_on
          entity_id: switch.stove_fan_relay_low
        turn_off:
          service: homeassistant.turn_off
          entity_id: switch.stove_fan_relay_low, switch.stove_fan_relay_high
        set_percentage:
          - service_template: >-
                {%- if (percentage > 0) and (percentage <=50) -%} homeassistant.turn_on 
                {%- else -%} homeassistant.turn_off
                {%- endif %}
            entity_id: switch.stove_fan_relay_low
          - service_template: >
                {%- if (percentage > 50) and (percentage <=100) -%} homeassistant.turn_on 
                {%- else -%} homeassistant.turn_off
                {%- endif %}
            entity_id: switch.stove_fan_relay_high
        speed_count: 2

3 Likes

Did I miss something here? It is not templating for me.

'speed' is undefined

I tried with this instead, it templates but the the new fan entity isn’t created.

value: "{{state_attr('fan.vmc_fan','speed')}}"

Post the configuration of your Template Fan.

When the fan is off, the speed attribute doesn’t exist.

I tried adding the following in the turn-off section but still no luck. The template isn’t created in my entites, meaning the input_text/boolean aren’t updated as a result (FYI).

              - service: input_text.set_value
                data:
                  entity_id: input_text.vmc_fan
                  value: 'off'

Is that syntaxe still correct with the new templating syntaxe ?

    fan:
      - platform: template
        fans:
          vmc_fan:
            friendly_name: "VMC Fan"
            value_template: "{{states('input_boolean.vmc_fan')}}"
            speed_template: "{{states('input_text.vmc_fan')}}"
            turn_on:
              - service: input_text.set_value
                data:
                  entity_id: input_text.vmc_fan
                  value: 'low'
              - service: homeassistant.turn_on
                entity_id: switch.vmc_l1, input_boolean.vmc_fan
            turn_off:
              - service: homeassistant.turn_off
                entity_id: switch.vmc_l1, switch.vmc_l2, input_boolean.vmc_fan
              - service: input_text.set_value
                data:
                  entity_id: input_text.vmc_fan
                  value: 'off'
            set_speed:
              - service_template: "switch.turn_{{'on' if speed in ['low'] else 'off'}}"
                entity_id: switch.vmc_l1
              - service_template: "switch.turn_{{'on' if speed in ['high'] else 'off'}}"
                entity_id: switch.vmc_l2
              - service: input_text.set_value
                data_template:
                  entity_id: input_text.vmc_fan
                  value: '{{ speed }}'

EDIT (HA logs - investigating)

2024-01-14 13:16:15.702 ERROR (MainThread) [homeassistant.config] Invalid config for 'fan.template' at configuration.yaml, line 122: 'speed_template' is an invalid option for 'fan.template', check: fans->vmc_fan->speed_template, please check the docs at https://www.home-assistant.io/integrations/template
Invalid config for 'fan.template' at configuration.yaml, line 137: 'set_speed' is an invalid option for 'fan.template', check: fans->vmc_fan->set_speed, please check the docs at https://www.home-assistant.io/integrations/template

No. The set_speed option no longer exists. A fan’s ‘speed’ is now called ‘speed percentage’ which is a number between 0 and 100 and configured by the set_percentage option.

Do what the error message suggests and read the documentation. It includes three examples showing the new syntax.

Yep, that configuration works fine for me :point_down: (edit: fixed turn off)

    input_boolean:
      vmc_fan:
        name: VMC Fan Power

    input_number:
      fan_percentage:
        name: VMC Percentage
        initial: 0
        min: 0
        max: 100
        step: 50

    fan:
      - platform: template
        fans:
          vmc_fan:
            friendly_name: "VMC Fan"
            value_template: "{{ states('input_boolean.vmc_fan') }}"
            turn_on:
              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.vmc_fan
            turn_off:
              - service: input_boolean.turn_off
                target:
                  entity_id: input_boolean.vmc_fan
              - service: switch.turn_off
                entity_id: switch.vmc_l1
              - service: switch.turn_off
                entity_id: switch.vmc_l2
            percentage_template: >
              {{ states('input_number.fan_percentage') if is_state('input_boolean.state', 'on') else 0 }}
            speed_count: 2
            set_percentage:
              - service: input_boolean.turn_{{ 'on' if percentage > 0 else 'off' }}
                target:
                  entity_id: input_boolean.vmc_fan
              - service: input_number.set_value
                target:
                  entity_id: input_number.fan_percentage
                data:
                  value: "{{ percentage }}"
              - service_template: "switch.turn_{{'on' if percentage == 50 else 'off'}}"
                entity_id: switch.vmc_l1
              - service_template: "switch.turn_{{'on' if percentage == 100 else 'off'}}"
                entity_id: switch.vmc_l2

For future reference, many versions ago, service_template was deprecated in favor of simply service and configured like this:

              - service: "switch.turn_{{'on' if percentage == 50 else 'off'}}"
                target:
                  entity_id: switch.vmc_l1
              - service: "switch.turn_{{'on' if percentage == 100 else 'off'}}"
                target:
                  entity_id: switch.vmc_l2

There’s also a new form of if statement available called an Immediate If. It’s useful for situations where the ‘then’ and ‘else’ contain constants.

              - service: "switch.turn_{{ iif(percentage == 50, 'on' , 'off') }}"
                target:
                  entity_id: switch.vmc_l1
              - service: "switch.turn_{{ iif(percentage == 100, 'on', 'off') }}"
                target:
                  entity_id: switch.vmc_l2
1 Like