Exactly! I’m thinking like you set the desired temperature on your AC unit with your remote. Sometimes you want a bit warmer and sometimes a bit cooler.
The min/max value would be set via the offset. Those you’d just have to set once as the “temperature curve” would then move up and down based on the set temperature.
Sir_Goodenough has a working input number in his BP if that would help
Would you be able to add to the blueprint an option to invert the blocking entity so that it would work with an entity that is off. My use case is a whole house fan that I want to run, but only when the window is open, which in this case it goes from an off state to on state.
Also it would be nice to have a separate enabling entity you can chose. Idea being I could install a remote switch that starts of the automation, otherwise the automation is disabled.
Hi @adamalli7, sorry for my late reply and thanks for your interest and ideas. Regarding your request to add an option to invert the blocking entity, I think the cost for implementing this in terms of the logic needed and the added complexity, proabably means I won’t add this feature. A much easier way would be to create your own template sensor that inverts the state of your entity. Here’s an example of how to to that:
Open your Home Assistant configuration file: This is usually located at /config/configuration.yaml.
Add the template sensor configuration: In your configuration.yaml file, add the following lines to define your template sensor. Replace sensor.your_entity with the actual entity ID you want to invert.
template:
- sensor:
- name: "Inverted Entity State"
state: >
{% if is_state('sensor.your_entity', 'on') %}
off
{% else %}
on
{% endif %}
availability: >
{{ states('sensor.your_entity') not in ['unknown', 'unavailable'] }}
Hey,
I really like your blueprint the only thing that is missing is a maximum percentage change. I got some wild jumps on my air conditioning fan.
Could you implant this value as well?
Thanks!
Haha interesting! Was that caused by a large jump in temperature though? What’s your thoughts on what should happen in this case? Eg: should the blueprint set the fan to the maximum allowed step change in fan speed and then continue to step it up until it eventually reached the required fan speed for the current temperature?
@Creepe95 ok I’ve added a maximum percentage change slider. Give it a go and let me know how it goes
Update the blueprint by re-importing it. It is backwards compatible, so your old settings will be preseved if you have any automations that are already using this blueprint.
Notes on this change:
To ensure the set_fan_speed value never increases or decreases by more than a desired threshold, you can set a max_change which is a threshold value set for the difference betwen the current fan_speed and the calculated set_fan_speed. If the difference exceeds max_change, the set_fan_speed will be adjusted to fan_speed + max_change (for the positive direction) or fan_speed - max_change (for the negative direction) as necessary.
IMPORTANT!
Because the automation is triggered only when the temperature sensor changes or when the fan is turned on, if you have set a small max_change and the time between temperature changes is large, the time it takes for the fan to get the set_fan_speed could be large.
Awesome blueprint!
I’ve tried to add the option to select another temperature sensor for the off_temp variable, which also influences the min_temp with an additional selector. But the fan speed doesn’t seem to change. Do you have any tips/remarks? Cheers.
blueprint:
name: Auto fan speed sensor
description: "Temperature based Auto fan control.\n\n Fan Speed will be set when
initially turned on by relating the ambient temperature to an equivalent speed
setting. \nA time delay and a minimum percentage change is used to eliminate frequent
speed changes.\n At the minimum temperature setting the fan will turn off. \n
When the temperature rises above this minimum temperature setting, the fan will
automatically turn back on."
domain: automation
input:
temp_sensor:
name: "\U0001F321 Temperature Sensor"
description: Enter your temperature sensor. Make sure the temperature sensor
is in the units (°C or °F) you want to use for the settings below. If your
temp sensor is in °C but you want to use the °F settings, you will need to
create a template sensor to convert the sensor into the correct units.
default: []
selector:
entity:
domain:
- sensor
device_class:
- temperature
multiple: false
off_temp_sensor:
name: "\U0001F321 Off Temperature Sensor"
description: "Enter a different temperature sensor to determine when the fan should turn off. This sensor will also be used to determine the minimum temperature setting."
default: []
selector:
entity:
domain:
- sensor
device_class:
- temperature
multiple: false
temp_adjustment:
name: "\U0001F321 Temperature Adjustment"
description: "Adjust the temperature added to the off temperature for setting the minimum fan speed temperature."
default: 2
selector:
number:
min: 0.0
max: 10.0
step: 0.5
mode: slider
unit_of_measurement: '°C'
fan_switch:
name: "\U0001F4A8 Fan"
description: The fan you wish to speed control.
selector:
entity:
domain:
- fan
multiple: false
min_fan_speed:
name: "\U0001F4A8 Minimum Fan Speed"
description: Set the minimum percentage speed when your fan is still on.
default: 16
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_fan_speed:
name: "\U0001F4A8 Maximum Fan Speed"
description: Set the maximum percentage speed for your fan.
default: 100
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_temp:
name: "\U0001F4C8 Maximum Temperature"
description: What temperature would you like the fan to run at max fan speed.
default: 40
selector:
number:
min: 10.0
max: 120.0
step: 1.0
mode: slider
auto_turn_on_enabled:
name: ✅ Enable auto fan on
description: "Let the fan automatically turn back on if the temperature returns to a value above the temperature that the fan switches off."
default: true
selector:
boolean: {}
change_time:
name: ⏱️ Change frequency delay
description: How long to delay between potential speed adjustments.
default: 30
selector:
number:
min: 1.0
max: 120.0
unit_of_measurement: minutes
step: 1.0
mode: slider
change_threshold:
name: Minimum percentage change
description: The minimum percentage change (between current fan speed and set
fan speed)
default: 1
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_change:
name: Maximum percentage change
description: The maximum percentage change (between current fan speed and set
fan speed)
default: 50
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
blocker_entity:
name: (OPTIONAL) Blocking entity
description: If this entity's state is on, it will prevent the automation from
running. E.g. sleep mode or away mode.
default:
selector:
entity:
multiple: false
source_url: https://community.home-assistant.io/t/adaptive-fan-speed-control-based-on-temperature-and-speed-range/678152
variables:
temp_sensor: !input temp_sensor
off_temp_sensor: !input off_temp_sensor
temp_adjustment: !input temp_adjustment
fan_switch: !input fan_switch
auto_turn_on_enabled: !input auto_turn_on_enabled
min_fan_speed: !input min_fan_speed
max_fan_speed: !input max_fan_speed
max_temp: !input max_temp
current_temp: '{{ states(temp_sensor) | float(0)}}'
off_temp: '{{ states(off_temp_sensor) | float(0)}}'
min_temp: '{{ off_temp + temp_adjustment }}'
change_time: !input change_time
max_change: !input max_change
change_threshold: !input change_threshold
blocker_entity: !input blocker_entity
fan_speed: '{{ state_attr(fan_switch,''percentage'') | float(0)}}'
temp_range: '{{ max_temp | float(0) - min_temp | float(0)}}'
fan_range: '{{ max_fan_speed | float(0) - min_fan_speed | float(0)}}'
slope: '{{ fan_range | float(0)/temp_range | float(0)}}'
initial_set_fan_speed: '{{ [[slope|float(0) * (current_temp|float(0) - min_temp|float(0))
+ min_fan_speed|float(0), min_fan_speed] | max, max_fan_speed] | min}}'
adjusted_set_fan_speed: "{% set diff = initial_set_fan_speed - fan_speed %} {% if
diff > max_change|float(0) %}\n {{ fan_speed + max_change|float(0) }}\n{% elif
diff < -max_change|float(0) %}\n {{ fan_speed - max_change|float(0) }}\n{% else
%}\n {{ initial_set_fan_speed }}\n{% endif %}\n"
set_fan_speed: '{{ adjusted_set_fan_speed }}'
speed_diff: '{{(fan_speed - set_fan_speed)|abs}}'
trigger:
- platform: state
entity_id:
- !input fan_switch
id: fanon
from: 'off'
to: 'on'
- platform: state
id: temp_state_change
entity_id:
- !input temp_sensor
condition:
- condition: template
alias: Check for blocker entity
value_template: '{{ (blocker_entity == none) or (states(blocker_entity) == ''off'')}}'
action:
- choose:
- conditions:
- condition: trigger
alias: Only run if fan was switched on
id: fanon
- condition: template
alias: Is the percentage change great enough?
value_template: '{{ speed_diff | float(0) > change_threshold | float(0) }}'
sequence:
- service: homeassistant.turn_on
data:
percentage: '{{set_fan_speed}}'
target:
entity_id: '{{fan_switch}}'
- delay:
minutes: !input change_time
- conditions:
- condition: template
value_template: '{{states(fan_switch) == ''on''}}'
alias: Make sure the fan is already on (ignore if it's been switched off)
- condition: template
alias: Is the percentage change great enough?
value_template: '{{ speed_diff | float(0) > change_threshold | float(0) }}'
- condition: template
alias: Is the temperature above the off temp?
value_template: '{{ current_temp | float(0) > off_temp | float(0) }}'
sequence:
- service: homeassistant.turn_on
target:
entity_id: '{{fan_switch}}'
data:
percentage: '{{set_fan_speed}}'
- delay:
minutes: !input change_time
- conditions:
- condition: not
alias: Make sure the fan hasn't just been turned on
conditions:
- condition: trigger
id: fanon
- condition: template
alias: Check if the temperature is below off_temp
value_template: '{{ states(off_temp_sensor) | float(0) < (off_temp | float(0)) }}'
sequence:
- service: homeassistant.turn_off
target:
entity_id: '{{fan_switch}}'
- conditions:
- '{{ auto_turn_on_enabled }}'
- condition: template
value_template: '{{states(fan_switch) == ''off''}}'
alias: Is the fan currently off?
- condition: template
alias: Is the temperature above the off temp?
value_template: '{{ current_temp | float(0) > off_temp | float(0) }}'
sequence:
- service: homeassistant.turn_on
data:
percentage: '{{set_fan_speed}}'
target:
entity_id: '{{fan_switch}}'
- delay:
minutes: !input change_time
mode: single
i added humidity control.
it works the same way. it calculates fan speed for temp and humidity and chooses the higher fan speed.
blueprint:
name: Auto fan speed based on Temperature and Humidity
description: "Auto fan control based on both temperature and humidity.\n\n The fan speed will be set according to the higher of the two calculated speeds: one based on ambient temperature and the other based on humidity. \nA time delay and a minimum percentage change is used to eliminate frequent speed changes.\n At the minimum settings for either, the fan will turn off."
domain: automation
input:
temp_sensor:
name: 🌡 Temperature Sensor
description: Enter your temperature sensor.
default: []
selector:
entity:
domain:
- sensor
device_class:
- temperature
multiple: false
humidity_sensor:
name: 💧 Humidity Sensor
description: Enter your humidity sensor.
default: []
selector:
entity:
domain:
- sensor
device_class:
- humidity
multiple: false
fan_switch:
name: 💨 Fan
description: The fan you wish to speed control.
selector:
entity:
domain:
- fan
multiple: false
min_fan_speed:
name: 💨 Minimum Fan Speed
description: Set the minimum percentage speed when your fan is still on.
default: 16
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_fan_speed:
name: 💨 Maximum Fan Speed
description: Set the maximum percentage speed for your fan.
default: 100
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_temp:
name: 📈 Maximum Temperature
description: The temperature at which the fan will run at max speed.
default: 40
selector:
number:
min: 10.0
max: 120.0
step: 1.0
mode: slider
min_temp:
name: 📉 Minimum Temperature
description: The temperature at which the fan will run at minimum speed.
default: 23
selector:
number:
min: 10.0
max: 120.0
step: 1.0
mode: slider
max_humidity:
name: 📈 Maximum Humidity
description: The humidity level at which the fan will run at max speed.
default: 80
selector:
number:
min: 10.0
max: 100.0
step: 1.0
mode: slider
min_humidity:
name: 📉 Minimum Humidity
description: The humidity level at which the fan will run at minimum speed.
default: 40
selector:
number:
min: 10.0
max: 100.0
step: 1.0
mode: slider
off_temp:
name: 🛑 The temperature at which the fan switches off
description: The temperature below which the fan turns off.
default: 22
selector:
number:
min: 10.0
max: 120.0
step: 1.0
mode: slider
off_humidity:
name: 🛑 The humidity level at which the fan switches off
description: The humidity level below which the fan turns off.
default: 35
selector:
number:
min: 10.0
max: 100.0
step: 1.0
mode: slider
auto_turn_on_enabled:
name: ✅ Enable auto fan on
description: Let the fan automatically turn back on if the temperature or humidity returns to a value above the off thresholds.
default: true
selector:
boolean: {}
change_time:
name: ⏱️ Change frequency delay
description: How long to delay between potential speed adjustments.
default: 30
selector:
number:
min: 1.0
max: 120.0
unit_of_measurement: minutes
step: 1.0
mode: slider
change_threshold:
name: Minimum percentage change
description: The minimum percentage change (between current fan speed and set fan speed).
default: 1
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
max_change:
name: Maximum percentage change
description: The maximum percentage change (between current fan speed and set fan speed).
default: 50
selector:
number:
min: 1.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: '%'
blocker_entity:
name: (OPTIONAL) Blocking entity
description: If this entity's state is on, it will prevent the automation from running. E.g., sleep mode or away mode.
default: []
selector:
entity:
multiple: false
source_url: https://community.home-assistant.io/t/adaptive-fan-speed-control-based-on-temperature-and-speed-range/678152
variables:
temp_sensor: !input temp_sensor
humidity_sensor: !input humidity_sensor
fan_switch: !input fan_switch
auto_turn_on_enabled: !input 'auto_turn_on_enabled'
min_fan_speed: !input min_fan_speed
max_fan_speed: !input max_fan_speed
max_temp: !input max_temp
min_temp: !input min_temp
off_temp: !input off_temp
max_humidity: !input max_humidity
min_humidity: !input min_humidity
off_humidity: !input off_humidity
change_time: !input change_time
max_change: !input max_change
change_threshold: !input change_threshold
blocker_entity: !input blocker_entity
current_temp: "{{ states(temp_sensor) | float(0)}}"
current_humidity: "{{ states(humidity_sensor) | float(0)}}"
fan_speed: '{{ state_attr(fan_switch,''percentage'') | float(0)}}'
# Temperature-based fan speed calculation
temp_range: '{{ max_temp | float(0) - min_temp | float(0) }}'
temp_slope: '{{ (max_fan_speed | float(0) - min_fan_speed | float(0)) / temp_range }}'
temp_fan_speed: '{{ [[temp_slope * (current_temp - min_temp) + min_fan_speed, min_fan_speed] | max, max_fan_speed] | min }}'
# Humidity-based fan speed calculation
humidity_range: '{{ max_humidity | float(0) - min_humidity | float(0) }}'
humidity_slope: '{{ (max_fan_speed | float(0) - min_fan_speed | float(0)) / humidity_range }}'
humidity_fan_speed: '{{ [[humidity_slope * (current_humidity - min_humidity) + min_fan_speed, min_fan_speed] | max, max_fan_speed] | min }}'
# Select the higher fan speed between temperature and humidity
set_fan_speed: '{{ [temp_fan_speed, humidity_fan_speed] | max }}'
speed_diff: '{{ (fan_speed - set_fan_speed) | abs }}'
trigger:
- platform: state
entity_id:
- !input fan_switch
id: fanon
from: 'off'
to: 'on'
- platform: state
id: temp_state_change
entity_id:
- !input temp_sensor
- platform: state
id: humidity_state_change
entity_id:
- !input humidity_sensor
condition:
- condition: template
alias: Check for blocker entity
value_template: '{{ (blocker_entity == none) or (states(blocker_entity) == ''off'')}}'
action:
- choose:
- conditions:
- condition: trigger
alias: Only run if fan was switched on
id: fanon
- condition: template
alias: Is the percentage change great enough?
value_template: '{{ speed_diff | float(0) > change_threshold | float(0) }}'
sequence:
- service: homeassistant.turn_on
data:
percentage: '{{ set_fan_speed }}'
target:
entity_id: '{{ fan_switch }}'
- delay:
minutes: !input change_time
- conditions:
- condition: template
value_template: '{{ states(fan_switch) == ''on'' }}'
alias: Make sure the fan is already on (ignore if it's been switched off)
- condition: template
alias: Is the percentage change great enough?
value_template: '{{ speed_diff | float(0) > change_threshold | float(0) }}'
- condition: template
alias: Is the temperature or humidity above the off thresholds?
value_template: >
{{ current_temp > off_temp or current_humidity > off_humidity }}
sequence:
- service: homeassistant.turn_on
target:
entity_id: '{{ fan_switch }}'
data:
percentage: '{{ set_fan_speed }}'
- delay:
minutes: !input change_time
- conditions:
- condition: not
alias: Make sure the fan hasn't just been turned on
conditions:
- condition: trigger
id: fanon
- condition: template
alias: Should the fan turn off based on both temperature and humidity?
value_template: '{{ current_temp <= off_temp and current_humidity <= off_humidity }}'
sequence:
- service: homeassistant.turn_off
target:
entity_id: '{{ fan_switch }}'
- conditions:
- '{{ auto_turn_on_enabled }}'
- condition: template
value_template: '{{ states(fan_switch) == ''off'' }}'
alias: Is the fan currently off?
- condition: template
alias: Is either the temperature or humidity above the off thresholds?
value_template: '{{ current_temp > off_temp or current_humidity > off_humidity }}'
sequence:
- service: homeassistant.turn_on
data:
percentage: '{{ set_fan_speed }}'
target:
entity_id: '{{ fan_switch }}'
oh wow that’s a great idea and a simple/tidy implementation! Nice work! My only suggestion would have been make the temp and humidity variables optional then during the set_fan_speed calculation, check if one or the other (or both) is undefined/null and perform the calculation accordingly. That way, you get to decide if you only want temperature control, or only humidity control, or both!
The check could be done like:
# Select the higher fan speed between temperature and humidity, ignoring None values
set_fan_speed: '{{ [temp_fan_speed | default(0), humidity_fan_speed | default(0)] | max }}'
Explanation:
| default(0) ensures that if temp_fan_speed or humidity_fan_speed is None, it is replaced with 0 (or any other fallback value you want).
The max function then compares the two values after replacing None with 0.
Yeah i’m not sure of the best way to do this other than creating a seperate fan entity as you have done. I don’t have enought experience with how to handle the service calls for a climate enitity and neatly that could be done while still keeping the fan entity functionality
Thumps up works. Thx.
Can you please add optional time / timer ?
Example I want to turn on the fan at 4pm (which is 1 hour before coming home) with the already set min/max settings .
I might also want to use a timer, turn off in 3 hours, or turn off at 2pm. (Fan noise drives me nuts when trying to sleep).
Thanks @Junglist79! Glad you like the blueprint. Regarding your idea for an optional time/timer: This is probably better suited as a seperate automation that turns the fan on and off during those times. Manually turning the fan (via switch or other automation) will automatically trigger this blueprint and the fan will be set to the speed accordingly. Does that make sense?
Love this blueprint but I seem to have issues trying to use local Tuya integration. The normal cloud Tuya integration works fine but for the life of me i can’t get it to work over local Tuya for fan control. Manual controls from HA are fine on both. Is it because the fan values on local are looking for an integer maybe? I’m also not smart enough apparently to make the output come out as an integer with any confidence to test it.