Alright I got this dramatically simpler, and now device-agnostic so can be re-used across fans. Was also able to simplify some logic by calling the “turn off” script briefly before setting speed. Basically acts as a common function to return fan state to a known baseline, and then number of button presses needed for desired speed is automatically known. No extra calculations needed.
Here are the final files:
Note: The delay
lines are to account for a separate automation that makes the fan switches into momentary buttons. Anytime the switch.turn_on
is called, the automation will automatically turn it off again. The delay in the scripts gives a little padding time for that to happen to avoid race condition bugs.
configuration.yaml
define fan(s) and which scripts to use to control them
fan:
- platform: template
fans:
starboard_saloon_fan:
friendly_name: "Starboard Saloon Fan"
value_template: "{{ states('binary_sensor.stb_saloon_fan_state') }}"
percentage_template: >
{% if states('sensor.starboard_saloon_fan_adc') | int > 10 %} 100
{% elif states('sensor.starboard_saloon_fan_adc') | int > 7 %} 66
{% elif states('sensor.starboard_saloon_fan_adc') | int > 5 %} 33
{% else %} 0
{% endif %}
turn_on:
service: script.fan_on
data:
sensor: "sensor.starboard_saloon_fan_adc"
button: "switch.starboard_saloon_fan_speed"
turn_off:
service: script.fan_off
data:
sensor: "sensor.starboard_saloon_fan_adc"
button: "switch.starboard_saloon_fan_speed"
set_percentage:
service: script.fan_speed
data:
percentage: "{{ percentage }}"
sensor: "sensor.starboard_saloon_fan_adc"
button: "switch.starboard_saloon_fan_speed"
speed_count: 3
script.fan_off:
Read current ADC value to figure out how many button presses to get it back to “off”
alias: Fan off
sequence:
- choose:
- conditions:
- condition: template
value_template: '{{ states(sensor) | float > 10 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- conditions:
- condition: template
value_template: '{{ states(sensor) | float > 7 and states(sensor) | float < 10 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- conditions:
- condition: template
value_template: '{{ states(sensor) | float > 5 and states(sensor) | float < 7 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
default: []
- delay: '00:00:00.1'
mode: queued
icon: mdi:fan-off
max: 10
script.fan_speed
To set speed, first call previous script to turn fan off. Then press button the correct number of times to set the speed requested by the UI.
alias: Fan speed
sequence:
- service: script.fan_off
data:
sensor: '{{ sensor }}'
button: '{{ button }}'
- choose:
- conditions:
- condition: template
value_template: '{{ percentage == 33 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- conditions:
- condition: template
value_template: '{{ percentage == 66 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- conditions:
- condition: template
value_template: '{{ percentage == 100 }}'
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
default: []
- delay: '00:00:00.5'
mode: queued
icon: mdi:fan-auto
max: 10
script.fan_on
Last, the utility script for default “fan on” behaviour - which just sets the fan to the “medium” speed.
alias: Fan on
sequence:
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.1'
- service: switch.turn_on
target:
entity_id: '{{ button }}'
- delay: '00:00:00.2'
mode: queued
icon: mdi:fan
max: 10
Thanks for the help everyone! I’ve done a full write-up of the project here, in case anyone else is interested in making Shelly UNI work with pushbutton fans: