Hi folks,
After setting up my Ecobee and setting the preset mode to hold at “Away” via home assistant I was surprised that this was overridden by my normal schedule.
I learned that in home assistant setting the preset mode to “Away” with a capital A – as is shown in the UI by default – your thermostat will use its “Hold Action” setting to choose when to resume its schedule. If you set the preset mode to “away” with a lowercase A – which requires you to edit the YAML – Home Assistant will tell the thermostat to use an indefinite hold regardless of the “Hold Action” setting.
Regardless of “Hold Action” setting or lower or upper case “away”, the ecobee thermostat will display “Away and Holding”. This is very confusing because “holding” could be indefinite or until the next schedule change depending on your settings, and there is no way to figure out which kind of hold has been set.
Below I get into the technicals of how we ended up in this place:
First off, when you use an automation and select the “Device” action with your ecobee, you then select the “Change preset on My ecobee” action with 3 default preset_mode
s:
Screen Shot 2022-12-15 at 12.46.00 PM|690x260
Note that these have a capitalized first letter. Now let’s look at the logic for the set_preset_mode function:
def set_preset_mode(self, preset_mode: str) -> None:
"""Activate a preset."""
if preset_mode == self.preset_mode:
return
self.update_without_throttle = True
# If we are currently in vacation mode, cancel it.
if self.preset_mode == PRESET_VACATION:
self.data.ecobee.delete_vacation(self.thermostat_index, self.vacation)
if preset_mode == PRESET_AWAY:
self.data.ecobee.set_climate_hold(
self.thermostat_index, "away", "indefinite", self.hold_hours()
)
// <snipped>
set_preset_mode()
will call set_climate_hold()
with the argument indefinite
if PRESET_AWAY
is passed. What is PRESET_AWAY
set to? We can see that this is imported from homeassistant.components.climate
, where it is defined as:
PRESET_AWAY = "away"
set_climate_hold()
if you were wondering, calls the pyecobee
library that home assistant uses to interface with ecobee. That function effectively calls the official Ecobee API endpoint setHold
. Where the docs say that passing the “indefinite” argument will:
The hold will not end and require to be cancelled explicitly.
So that explains the behavior for the lower case away – but what about the upper case Away?
Turns out when you use an upper case Away, as is presented in the UI by default, the set_preset_mode()
function matches this with the preset “Away” mode included by default on your device on line 590:
elif preset_mode in self.preset_modes:
climate_ref = None
for comfort in self.thermostat["program"]["climates"]:
if comfort["name"] == preset_mode:
climate_ref = comfort["climateRef"]
break
if climate_ref is not None:
self.data.ecobee.set_climate_hold(
self.thermostat_index,
climate_ref,
self.hold_preference(),
self.hold_hours(),
)
else:
_LOGGER.warning("Received unknown preset mode: %s", preset_mode)
This mode retrieves the hold_preference() that has been set by the device! This means if you have set your “Hold Action’’ setting to “indefinite” the lower case and upper case Away would function the same. This explains some of the mixed reports people have shared when debugging this issue.
At the root of this issue is the inconsistent use of hold states based on the logic in the set_preset_mode()
. To fix this, I might recommend the following:
- In homeassistant/components/ecobee/climate.py, in the
set_preset_mode()
function, remove theif
statement on line 571 that callsset_climate_hold()
with special arguments if the preset mode is lower case away. I looked through the code and am not sure why this preset requires special treatment. Perhaps someone here can share how this got here – I looked and it’s been this way in the codebase for years. Perhaps a hacky workaround to set an indefinite away preset, which is clearly a common use case. - Collect an additional boolean input from the UI called “indefinite hold” and pass this to the
set_preset_mode()
function. If this option is set to true, theset_climate_hold()
call on line 599 should be passed the “indefinite” argument and override the device setting.
With these two changes, it would ensure that the default behavior respects the settings on the device, but allows users the clear ability to override this from home assistant should they choose. This preserves and makes more clear the two use cases people have talked about: respecting the device setting and offering an explicit override as well.
Another change that would be great is if ecobee could show “Away and holding <indefinitely>” or “Away and holding <until next schedule change>” to make it clear to users what their thermostat is doing. But we probably won’t get that, so in the meantime the above solution would be the best.
(Fun side note, if you use the quick actions panel on your ecobee to toggle the home/away mode, that is an indefinite hold which does not respect your device settings!)