Documenting behavior of Ecobee, Home Assistant, and preset holding

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_modes:

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:

  1. In homeassistant/components/ecobee/climate.py, in the set_preset_mode() function, remove the if statement on line 571 that calls set_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.
  2. 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, the set_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!)

3 Likes

An issue was opened on this: Ecobee- Away preset not creating permanent hold · Issue #86094 · home-assistant/core · GitHub

For reference, this is the YAML I used to set the indefinite “away” hold (lowercase “a”):

service: climate.set_preset_mode
data:
  preset_mode: away
target:
  entity_id: climate.master_bedroom

Anyone else having issues with the lowercase infinite ‘away’? Not sure if there was an API or integration change, but when I try to set the infinite away now I have an error in my logs:

Error executing script. Error for call_service at pos 1: The preset_mode away is not a valid preset_mode: Away, Home, Sleep

EDIT: Looks like this is a known open issue:

1 Like

Yeah having the same issue. Figured they patched it.

@redwood Thank you so much for figuring this out. What frustration I’ve been having. I hope this behavior gets changed as per the issue below, but thank you.

This has been updated starting in 2024.4. You can now use away_indefinitely where you previously used the lowercase away preset for indefinite holds. Away (which comes directly from the ecobee API) continues to be a temporary hold. The new indefinite preset will show up in the UI as well.

3 Likes