[Guide]Template Fan and Broadlink

If anyone is still struggling with the fan speed script - I found when I did the trace, the choose didn’t function because the number passed is ‘33.0’ not ‘33’. So add decimals to your script and voila!

Thanks for this! New to HA and was pulling my hair trying to get a simple fan added.

I recently got a Bestcon RM4C Mini Universal IR Blaster to control my Dyson floor fan. Realized it might also ease control to see the power level so I got a Shelly Plus Plug. With those two devices and the below fan template I was able to get it completely automated as a fan. I also bridged the fan template over to homekit along with a separate template switch for the oscillation since calls to toggle the oscillation with siri do not work as expected, seems to be a known issue if you search the web for that.

Edit: added in an input_boolean to assist with tracking the oscillation state of the fan. The script just toggles it whenever the oscillation call happens and then the fan is set to track the state of the input_boolean.

fan:

- platform: template
  fans:
    bedroom_fan:
      unique_id: bedroom_fan
      friendly_name: "Bedroom fan"
      value_template: "{{ states('sensor.bedroom_fan_power') | float > 0 }}"
      percentage_template: >
        {% if state_attr('fan.bedroom_fan', 'oscillating') %}
          {%   if states('sensor.bedroom_fan_power') | float >= 55.0 %}
            100
          {% elif states('sensor.bedroom_fan_power') | float >= 41.3 %}
            90
          {% elif states('sensor.bedroom_fan_power') | float >= 29.8 %}
            80
          {% elif states('sensor.bedroom_fan_power') | float >= 20.1 %}
            70
          {% elif states('sensor.bedroom_fan_power') | float >= 16.3 %}
            60
          {% elif states('sensor.bedroom_fan_power') | float >= 10.1 %}
            50
          {% elif states('sensor.bedroom_fan_power') | float >= 7.7 %}
            40
          {% elif states('sensor.bedroom_fan_power') | float >= 5.9 %}
            30
          {% elif states('sensor.bedroom_fan_power') | float >= 4.8 %}
            20
          {% elif states('sensor.bedroom_fan_power') | float >= 3.3 %}
            10
          {% else %}
            0
          {% endif %}
        {% else %}
          {%   if states('sensor.bedroom_fan_power') | float >= 52.0 %}
            100
          {% elif states('sensor.bedroom_fan_power') | float >= 39.0 %}
            90
          {% elif states('sensor.bedroom_fan_power') | float >= 28.0 %}
            80
          {% elif states('sensor.bedroom_fan_power') | float >= 18.0 %}
            70
          {% elif states('sensor.bedroom_fan_power') | float >= 14.0 %}
            60
          {% elif states('sensor.bedroom_fan_power') | float >= 7.5 %}
            50
          {% elif states('sensor.bedroom_fan_power') | float >= 5.0 %}
            40
          {% elif states('sensor.bedroom_fan_power') | float >= 3.2 %}
            30
          {% elif states('sensor.bedroom_fan_power') | float >= 2.2 %}
            20
          {% elif states('sensor.bedroom_fan_power') | float >= 1.0 %}
            10
          {% else %}
            0
          {% endif %}
        {% endif %}
      oscillating_template: "{{ states('input_boolean.bedroom_fan_oscillation_state') == 'on' }}"
      turn_on:
        service: script.bedroom_fan_power
      turn_off:
        service: script.bedroom_fan_power
      set_percentage:
        service: >
          {% if percentage | float > state_attr('fan.bedroom_fan', 'percentage') | float %}
            script.bedroom_fan_increase
          {% elif percentage | float < state_attr('fan.bedroom_fan', 'percentage') | float %}
            script.bedroom_fan_decrease
          {% else %}
            script.do_nothing
          {% endif %}
      set_oscillating:
        service: script.bedroom_fan_oscillate
      speed_count: 10

script:

bedroom_fan_power:
  alias: Bedroom Fan Power On
  sequence:
  - service: remote.send_command
    target:
      entity_id: remote.bedroom_fan
    data:
      command: b64:JgBIAEcbGTEZMhoYGRoZGRkZGRgZGxoZGRoZGRkZGRkZGBoZGQAM2EgaGDMYMxcbFxsYGxcaGBsWHRYdFxsXHBYbFxwXGhccFgANBQ==
  - delay: 1
  - service: fan.oscillate
    target:
      entity_id: fan.bedroom_fan
    data:
      oscillating: "{{ states('fan.bedroom_fan') == 'on' }}"
bedroom_fan_increase:
  alias: Bedroom Fan Increase
  sequence:
  - repeat:
      count: 2
      sequence:
        service: remote.send_command
        target:
          entity_id: remote.bedroom_fan
        data:
          command: b64:JgBIAEYcFjQYMxgaGRoYGhgaGBkYHBg0FxsYMxgaFzQXGhgaGAAMikcbFzQYMxgbFxoYGxcaGBsXHBc0GBoZMhgbGDIYGhgaFwANBQ==
bedroom_fan_decrease:
  alias: Bedroom Fan Decrease
  sequence:
  - repeat:
      count: 2
      sequence:
        service: remote.send_command
        target:
          entity_id: remote.bedroom_fan
        data:
          command: b64:JgBIAEcbFzQYMxccFxoYGxcaGBsXNBc0GDQXMxkyGDMXMxgaFwAMsEYbGTIYNBcbFxsYGhgaGBoXNRg0FzMYMxgzGDIYMxcaGQANBQ==
bedroom_fan_oscillate:
  alias: Bedroom Fan Oscillate
  sequence:
  - service: input_boolean.toggle
    target:
      entity_id: input_boolean.bedroom_fan_oscillation_state
    data: {}
  - service: remote.send_command
    target:
      entity_id: remote.bedroom_fan
    data:
      command: b64:JgBIAEcbGDQXMxkaFxsYGhgaGBoXNRgaGDQXGxY1FxsYGhY0GAAMeEYcFzMZMxccFxoYGxgZGBsXNBkaGDMYGhgzGBoYGhgyGQANBQ==

do_nothing:
  alias: "Placeholder service that does absolutely nothing (pass)"
  sequence:
    delay:
      milliseconds: 1

switch:

bedroom_fan_oscillation:
  friendly_name: "Bedroom Fan Oscillation"
  unique_id: bedroom_fan_oscillation
  value_template: "{{ state_attr('fan.bedroom_fan', 'oscillating') }}"
  availability_template: "{{ states('fan.bedroom_fan') }}"
  turn_on:
    service: fan.oscillate
    target:
      entity_id: fan.bedroom_fan
    data:
      oscillating: true
  turn_off:
    service: fan.oscillate
    target:
      entity_id: fan.bedroom_fan
    data:
      oscillating: false

input_boolean:

bedroom_fan_oscillation_state:
  name: "Bedroom Fan Oscillation State"

With this and bridging it all to homekit I can say any of the following:

Hey Siri, Turn on the Bedroom Fan

Hey Siri, Turn off the Bedroom Fan

Hey Siri, Turn on Bedroom Fan Oscillation

Hey Siri, Turn off Bedroom Fan Oscillation

Hey Siri, Increase the Bedroom Fan

Hey Siri, Decrease the Bedroom Fan

It also shows up in Homekit as a proper fan entity.

Just figured I would share here in case it helps anyone else.

I added in an input_boolean helper to track fan oscillation state. Updated my prior code to reflect all of that, every part of fan control for this previously dumb-fan works beautifully now.

Dears, I tried to follow the guide but when I switch on de the fan say me fan.set_percentage not found.
Some one can help me?

Here you have my files

alias: ventilador_habitacion_3_on
sequence:

  • service: remote.send_command
    data:
    device: ventilador habitación 3
    command: speed1
    target:
    entity_id: remote.habitacion_3_2
  • service: input_boolean.turn_on
    target:
    entity_id: input_boolean.ventilador_techo_habitacion_3_state
    data: {}
  • service: input_number.set_value
    target:
    entity_id: input_number.ventilador_habitacion_3
    data:
    value: 20
    mode: single

alias: ventilador_habitacion_3_off
sequence:

  • service: remote.send_command
    data:
    device: ventilador habitación 3
    command: “off”
    target:
    entity_id: remote.habitacion_3_2
  • service: input_boolean.turn_off
    target:
    entity_id: input_boolean.ventilador_techo_habitacion_3_state
    data: {}
  • service: input_number.set_value
    target:
    entity_id: input_number.ventilador_habitacion_3
    data:
    value: 0
    mode: single

sequence:

  • service: remote.send_command
    data:
    device: ventilador_habitacion_3
    command: speed1
    target:
    entity_id: remote.habitacion_3_2
  • delay:
    hours: 0
    minutes: 0
    seconds: 0
    milliseconds: 500
  • service: remote.send_command
    data:
    device: ventilador_habitacion_3
    command: speed2
    target:
    entity_id: remote.habitacion_3_2
  • delay:
    hours: 0
    minutes: 0
    seconds: 0
    milliseconds: 500
  • service: remote.send_command
    data:
    device: ventilador_habitacion_3
    command: speed3
    target:
    entity_id: remote.habitacion_3_2
  • delay:
    hours: 0
    minutes: 0
    seconds: 0
    milliseconds: 500
  • service: remote.send_command
    data:
    device: ventilador_habitacion_3
    command: speed4
    target:
    entity_id: remote.habitacion_3_2
  • delay:
    hours: 0
    minutes: 0
    seconds: 0
    milliseconds: 500
  • service: remote.send_command
    data:
    device: ventilador_habitacion_3
    command: speed5
    target:
    entity_id: remote.habitacion_3_2
    mode: single
    alias: ventilador_habitacion_3_inc

alias: ventilador_habitacion_3_set_speed
sequence:

  • service: input_number.set_value
    target:
    entity_id: input_number.ventilador_habitacion_3
    data:
    value: “{{ percentage }}”

  • delay:
    hours: 0
    minutes: 0
    seconds: 0
    milliseconds: 500

  • choose:

    • conditions:
      • condition: state
        entity_id: input_number.ventilador_habitacion_3
        state: “20.0”
        sequence:
      • service: script.ventilador_habitacion_3_inc
    • conditions:
      • condition: state
        entity_id: input_number.ventilador_habitacion_3
        state: “40.0”
        sequence:
      • service: script.ventilador_habitacion_3_inc
    • conditions:
      • condition: state
        entity_id: input_number.ventilador_habitacion_3
        state: “60.0”
        sequence:
      • service: script.ventilador_habitacion_3_inc
    • conditions:
      • condition: state
        entity_id: input_number.ventilador_habitacion_3
        state: “80.0”
        sequence:
      • service: script.ventilador_habitacion_3_inc
    • conditions:
      • condition: state
        entity_id: input_number.ventilador_habitacion_3
        state: “100.0”
        sequence:
      • service:
  • platform: template
    fans:
    ventilador_habitacion_3:
    friendly_name: “ventilador habitación 3”
    unique_id: ventilador_habitacion_3
    value_template: “{{ states(‘input_boolean.ventilador_habitacion_3_state’) }}”
    percentage_template: “{{ states(‘input_number.ventilador_habitacion_3’) }}”
    turn_on:
    service: script.ventilador_habitacion_3_power_on
    turn_off:
    service: script.ventilador_habitacion_3_power_off
    set_percentage:
    service: script.ventilador_habitacion_3_set_speed
    data:
    percentage: ‘{{ percentage }}’
    speed_count: 5

This is so Cool~ Everything works perfect , Thanks for sharing

When I was using Scene to turn off all my living room’s devices, I found that when the fan was off, it would be turn on again by Automations or Scenes. but after add ‘‘Conditions’’, everything became normal. I would suggest to add ‘‘Conditions’’ in turn_on and turn_off

turn_on:
- condition: state
entity_id: fan.bedroom_fan
state: ‘off’
- service: script.bedroom_fan_power
turn_off:
- condition: state
entity_id: fan.bedroom_fan
state: ‘on’
- service: script.bedroom_fan_power

Hi, did you find any solution for that?

I ended up buying a fan that had wifi

Hi! Thanks a lot for this guide. I have my fan working on HA but when using it on HomeKit the slider doesn’t work properly. When I move the percentage on HomeKit it doesn’t change on HA until the next change of percentage. Can you help me?

I got On and Off working but the others do not.
This is my FAN config:

- platform: template
  fans:
    work_room_fan:
      friendly_name: "Work Room Fan"
      unique_id: e244c3b5-0db9-4737-8656-4bffg5404287
      value_template: "{{ states('input_boolean.work_room_fan_state') }}"
      turn_on:
        - action: script.work_room_fan_1
          target:
            entity_id: input_number.work_room_fan_percentage
          data:
            value: 20
      turn_off:
        - action: script.work_room_fan_off
          target:
            entity_id: input_number.work_room_fan_percentage
          data:
            value: 0
      percentage_template: >
        {{ states('input_number.work_room_fan_percentage') if is_state('input_boolean.work_room_fan_state', 'on') else 0 }}
      speed_count: 5
      set_percentage:
        - action: input_boolean.turn_{{ 'on' if percentage > 0 else 'off' }}
          target:
            entity_id: input_boolean.work_room_fan_state
        - action: input_number.set_value
          target:
            entity_id: input_number.work_room_fan_percentage
          data:
            value: "{{ percentage }}"
        - action: script.work_room_fan_set_speed

shelly (eg_luefter_01 & eg_luefter_02)
→ hardware & cabeling works, control/imitate both hw switches by webinterface or HA work as expected.

eg_luefter_01 eg_luefter_02 fan
OFF OFF OFF
ON OFF LOW
OFF ON MEDIUM
ON ON HIGH

configuration.yaml:

  - platform: template
    fans:
      eg_luefter:
        friendly_name: "EG Lüfter"
        unique_id: "eg_luefter"
        preset_modes:
          - "off"
          - "low"
          - "medium"
          - "high"
        preset_mode_template: >-
          {% set s1 = is_state('switch.eg_luefter_01', 'on') %}
          {% set s2 = is_state('switch.eg_luefter_02', 'on') %}
          {% if not s1 and not s2 %}
            off
          {% elif s1 and not s2 %}
            low
          {% elif not s1 and s2 %}
            medium
          {% elif s1 and s2 %}
            high
          {% else %}
            off
          {% endif %}
        turn_on:
          service: script.set_luefter_mode
          data:
            mode: low
        turn_off:
          service: script.set_luefter_mode
          data:
            mode: off
        set_preset_mode:
          service: script.set_luefter_mode
          data_template:
            mode: "{{ mode }}"

script:

set_luefter_mode:
    alias: "Lüfter Mode"
    fields:
      mode:
        description: "fan mode"
        example: "off"
    sequence:
      - choose:
          - conditions:
              - condition: template
                value_template: "{{ mode == 'off' }}"
            sequence:
              - service: switch.turn_off
                target:
                  entity_id:
                    - switch.eg_luefter_01
                    - switch.eg_luefter_02
          - conditions:
              - condition: template
                value_template: "{{ mode == 'low' }}"
            sequence:
              - service: switch.turn_on
                target:
                  entity_id: switch.eg_luefter_01
              - service: switch.turn_off
                target:
                  entity_id: switch.eg_luefter_02
          - conditions:
              - condition: template
                value_template: "{{ mode == 'medium' }}"
            sequence:
              - service: switch.turn_off
                target:
                  entity_id: switch.eg_luefter_01
              - service: switch.turn_on
                target:
                  entity_id: switch.eg_luefter_02
          - conditions:
              - condition: template
                value_template: "{{ mode == 'high' }}"
            sequence:
              - service: switch.turn_on
                target:
                  entity_id:
                    - switch.eg_luefter_01
                    - switch.eg_luefter_02

what am I doing wrong here?

thanks for help

Thank you so much Chris for sharing your guide as it was very helpful when I was doing the same exact thing to control my ceiling fan via broadlink rm4 pro ir/rf controller.

I made some updates using your guide as a baseline to share with everyone if you guys want to do something similar. My goal was to emulate the fan template just like an actual fan template entity so I added the added ability to turn on the fan to the last speed it was set to instead of a default speed of 1.

# Keep track of the fan state
input_boolean:
  bedroom_fan_state:

# Keep track of fan speed
input_number:
  bedroom_fan_speed:
    name: Bedroom Fan Percentage
    min: 0
    max: 100

# Keep track of the fan last speed
iinput_number:
  bedroom_fan_last_speed:
    name: Bedroom Fan Percentage
    min: 0
    max: 100

Fan ON/OFF Script

bedroom_fan_on_off:
  sequence:
  - alias: Fan ON/OFF
    choose:
    - conditions:
      - condition: state
        entity_id: input_boolean.bedroom_fan_state
        state:
        - 'off'
      sequence:
      - alias: Copy value from Fan Speed Helper to Last Fan Speed Helper
        action: input_number.set_value
        metadata: {}
        data:
          value: '{{ states(''input_number.bedroom_fan_speed'') }}'
        target:
          entity_id:
          - input_number.bedroom_fan_last_speed
      - alias: Set Fan Speed Helper to 0
        action: input_number.set_value
        metadata: {}
        target:
          entity_id:
          - input_number.bedroom_fan_speed
        data:
          value: 0
      - action: script.bedroom_fan_send_command
        metadata: {}
        data: {}
      alias: Fan OFF
    - conditions:
      - condition: state
        entity_id: input_boolean.bedroom_fan_state
        state:
        - 'on'
      sequence:
      - alias: Copy value from Last Speed Helper to Fan Speed Helper
        action: input_number.set_value
        metadata: {}
        target:
          entity_id:
          - input_number.bedroom_fan_speed
        data:
          value: '{{ states(''input_number.bedroom_fan_last_speed'') }}'
      - action: script.bedroom_fan_send_command
        metadata: {}
        data: {}
      alias: Fan ON
  alias: Bedroom_Fan_ON/OFF
  description: ''

Set Fan Speed Script

bedroom_fan_set_speed:
  sequence:
    - if:
        - condition: template
          value_template: "{{ percentage == 0 }}"
          alias: If returned percentage == 0 from Fan Template
      then:
        - if:
            - condition: state
              entity_id: input_number.bedroom_fan_speed
              state:
                - "0.0"
          then: []
          else:
            - action: input_boolean.turn_off
              metadata: {}
              target:
                entity_id: input_boolean.bedroom_fan_state
              data: {}
              enabled: true
            - action: script.bedroom_fan_on_off
              metadata: {}
              data: {}
              enabled: true
      else:
        - alias: >-
            Copy returned Percentage from Fan Template to Bedroom_Fan_Speed Input
            Number
          action: input_number.set_value
          metadata: {}
          target:
            entity_id:
              - input_number.bedroom_fan_speed
          data:
            value: "{{ percentage }}"
        - action: input_boolean.turn_on
          metadata: {}
          target:
            entity_id: input_boolean.bedroom_fan_state
          data: {}
        - action: script.bedroom_fan_send_command
          metadata: {}
          data: {}
  alias: Bedroom_Fan_Set_Speed
  description: ""

Bedroom Fan Send Command Script

bedroom_fan_send_command:
  sequence:
    - choose:
        - conditions:
            - condition: state
              entity_id: input_number.bedroom_fan_speed
              state:
                - "0.0"
          sequence:
            - alias: Send Fan OFF Command to Bedroom Fan
              action: remote.send_command
              target:
                entity_id: remote.broadlink_rm4_pro
              data:
                device: Bedroom fan
                command: fan off
              enabled: false
        - conditions:
            - condition: state
              entity_id: input_number.bedroom_fan_speed
              state:
                - "33.0"
          sequence:
            - action: remote.send_command
              target:
                entity_id: remote.broadlink_rm4_pro
              data:
                device: Bedroom fan
                command: low speed
              enabled: false
              alias: Send Low Speed Command to Bedroom Fan
          alias: >-
            If Bedroom_Fan_Speed is 33, send Low Speed Command to Bedroom
            Fan
        - conditions:
            - condition: state
              entity_id: input_number.bedroom_fan_speed
              state:
                - "66.0"
          sequence:
            - action: remote.send_command
              target:
                entity_id: remote.broadlink_rm4_pro
              data:
                device: Bedroom fan
                command: medium speed
              enabled: false
              alias: Send Medium Speed Command to Bedroom Fan
          alias: >-
            If Bedroom_Fan_Speed is 66, send Medium Speed Command to
            Bedroom Fan
        - conditions:
            - condition: state
              entity_id: input_number.bedroom_fan_speed
              state:
                - "100.0"
          sequence:
            - action: remote.send_command
              target:
                entity_id: remote.broadlink_rm4_pro
              data:
                device: Bedroom room fan
                command: high speed
              enabled: false
              alias: Send High Speed Command to Bedroom Fan
          alias: >-
            If Bedroom_Fan_Speed is 100, send High Speed Command to Bedroom
            Fan
  alias: Bedroom_Fan_Send_Command
  description: >-
    Sends RF Commands to Fan to set Fan speed based on bedroom_fan_speed helper

Fan Template Created through GUI

Create new helper → template → fan

State Field:

{{ states('input_boolean.bedroom_fan_state') }}

Actions to Turn on:

action: input_boolean.turn_on
data: {}
metadata: {}
target:
 entity_id: input_boolean.bedroom_fan_state

action: script.bedroom_fan_on_off
data: {}
metadata: {}
response_variable: bedroom_fan_template_state

Actions to Turn off:

action: input_boolean.turn_off
data: {}
metadata: {}
target:
  entity_id: input_boolean.bedroom_fan_state

action: script.bedroom_fan_on_off
data: {}
metadata: {}
response_variable: bedroom_fan_template_state

Percentage Field:

{{ states('input_number.bedroom_fan_speed') }}

Actions to set percentage:

action: script.bedroom_fan_set_speed
data:
  percentage: "{{ percentage }}"
metadata: {}

Speed Count: 3