Did you get this working? I suspect the problem is simply that ecobee doesn’t listen to the service climate.set_fan_mode
and instead you have to use climate.ecobee_set_fan_min_on_time
and send it 0 for off and 60 for on, or 30 or whatever if you want it to only run some of the time.
I have my version of this working using an automation and a template sensor.
I also have a custom switch so I can see if the fan is on or off and easily turn it on by hand if I want.
There are a few subtleties in the config that I’ll explain at the bottom.
configuration.yaml:
# Sensors
sensor:
# Custom Sensors
- platform: template
sensors:
# Difference between max and minimum temperature in the house
ecobee_spread:
friendly_name: 'Temperature Spread'
unit_of_measurement: 'Δ°F'
device_class: temperature
value_template: >-
{% set t = [
states('sensor.lilbee_temperature'),
states('sensor.office_temperature'),
states('sensor.thermostat_temperature')
] | map('regex_replace', '(^[-+]?[0-9]*\.?[0-9]+$)|.*', '\\1')
| reject('eq', '')
| map('float')
| list %}
{% set spread = t|max - t|min if t else 0 %}
{{ spread | round(2) }}
# Switches
switch:
- platform: template
switches:
thermostat_fan_mode:
friendly_name: "Thermostat Fan Mode"
value_template: "{{ state_attr('climate.thermostat', 'fan_min_on_time')|int > 5 }}"
icon_template: >-
{% if state_attr('climate.thermostat', 'fan_min_on_time')|int > 5 -%}
mdi:fan
{%- else -%}
mdi:fan-off
{%- endif %}
turn_on:
- service: climate.ecobee_set_fan_min_on_time
data:
entity_id: climate.thermostat
fan_min_on_time: 60
turn_off:
- service: climate.ecobee_set_fan_min_on_time
data:
entity_id: climate.thermostat
fan_min_on_time: 0
automations.yaml:
- alias: "Normalize Temperature"
initial_state: off
trigger:
- entity_id: sensor.ecobee_spread
platform: state
condition:
- condition: numeric_state
entity_id: sensor.ecobee_spread
above: 2.8
action:
- service: climate.ecobee_set_fan_min_on_time
entity_id: climate.thermostat
data_template:
fan_min_on_time: >-
{{- 30 if states('sensor.ecobee_spread')|float >= 3.0
and states('sensor.thermostat_temperature')|float >= 65.0 else 0 -}}
The reason I use such a strange expression for creating sensor.ecobee_spread
is that I want to filter out any unknown (non numeric) values because if the ecobee misses a sensor for whatever reason then it ends up causing a naive conversion to float to become 0.0 and that makes the spread rating spike up to something like 60 or 70. I could probably get away with a simple reject('eq', 'unknown')
but I got anal and decided to reject anything that isn’t a valid float.
In the automation, I have a kluge that runs the condition any time the spread is > 2.8 degrees, but I actually only set the fan runtime if the spread is >= 3.0 degrees. This is so that there is a chance for the automation to set the fan runtime to zero. Otherwise I’d need 2 automations, one to turn the fan on and one to turn it off. I also restrict the normalize temperature to when the house is above 65 degrees since I find it uncomfortable to blow cold air around at night when we’re sleeping and the house has cooled. I shoudl probably limit it on the high end too to prevent the fan from running when we are gone and/or if nothing is occupied.
Note that I still have a bit of trouble with this automation when the spread is close to 3.0 there is a tendency for this approach to cause the fan to cycle on and off more than it should. Really I should put in a duration constraint somewhere so that the runtime is not changed too frequently.