From 82ac3e3fdf39fe0a4df4e76ffbd0994183e2e3d6 Mon Sep 17 00:00:00 2001 From: SLaks Date: Tue, 18 Feb 2025 14:11:37 -0500 Subject: [PATCH] Ecobee: Report Humidifier Action (#138756) Co-authored-by: Josef Zweck --- homeassistant/components/ecobee/humidifier.py | 36 ++++++++++++++----- .../ecobee/fixtures/ecobee-data.json | 2 +- tests/components/ecobee/test_humidifier.py | 3 ++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/ecobee/humidifier.py b/homeassistant/components/ecobee/humidifier.py index ab6831d8f26..a6f3c16f84a 100644 --- a/homeassistant/components/ecobee/humidifier.py +++ b/homeassistant/components/ecobee/humidifier.py @@ -3,11 +3,13 @@ from __future__ import annotations from datetime import timedelta +from typing import Any from homeassistant.components.humidifier import ( DEFAULT_MAX_HUMIDITY, DEFAULT_MIN_HUMIDITY, MODE_AUTO, + HumidifierAction, HumidifierDeviceClass, HumidifierEntity, HumidifierEntityFeature, @@ -41,6 +43,12 @@ async def async_setup_entry( async_add_entities(entities, True) +ECOBEE_HUMIDIFIER_ACTION_TO_HASS = { + "humidifier": HumidifierAction.HUMIDIFYING, + "dehumidifier": HumidifierAction.DRYING, +} + + class EcobeeHumidifier(HumidifierEntity): """A humidifier class for an ecobee thermostat with humidifier attached.""" @@ -52,7 +60,7 @@ class EcobeeHumidifier(HumidifierEntity): _attr_has_entity_name = True _attr_name = None - def __init__(self, data, thermostat_index): + def __init__(self, data, thermostat_index) -> None: """Initialize ecobee humidifier platform.""" self.data = data self.thermostat_index = thermostat_index @@ -80,11 +88,11 @@ class EcobeeHumidifier(HumidifierEntity): ) @property - def available(self): + def available(self) -> bool: """Return if device is available.""" return self.thermostat["runtime"]["connected"] - async def async_update(self): + async def async_update(self) -> None: """Get the latest state from the thermostat.""" if self.update_without_throttle: await self.data.update(no_throttle=True) @@ -96,12 +104,20 @@ class EcobeeHumidifier(HumidifierEntity): self._last_humidifier_on_mode = self.mode @property - def is_on(self): + def action(self) -> HumidifierAction: + """Return the current action.""" + for status in self.thermostat["equipmentStatus"].split(","): + if status in ECOBEE_HUMIDIFIER_ACTION_TO_HASS: + return ECOBEE_HUMIDIFIER_ACTION_TO_HASS[status] + return HumidifierAction.IDLE if self.is_on else HumidifierAction.OFF + + @property + def is_on(self) -> bool: """Return True if the humidifier is on.""" return self.mode != MODE_OFF @property - def mode(self): + def mode(self) -> str: """Return the current mode, e.g., off, auto, manual.""" return self.thermostat["settings"]["humidifierMode"] @@ -118,9 +134,11 @@ class EcobeeHumidifier(HumidifierEntity): except KeyError: return None - def set_mode(self, mode): + def set_mode(self, mode: str) -> None: """Set humidifier mode (auto, off, manual).""" - if mode.lower() not in (self.available_modes): + if self.available_modes is None: + raise NotImplementedError("Humidifier does not support modes.") + if mode.lower() not in self.available_modes: raise ValueError( f"Invalid mode value: {mode} Valid values are" f" {', '.join(self.available_modes)}." @@ -134,10 +152,10 @@ class EcobeeHumidifier(HumidifierEntity): self.data.ecobee.set_humidity(self.thermostat_index, humidity) self.update_without_throttle = True - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Set humidifier to off mode.""" self.set_mode(MODE_OFF) - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Set humidifier to on mode.""" self.set_mode(self._last_humidifier_on_mode) diff --git a/tests/components/ecobee/fixtures/ecobee-data.json b/tests/components/ecobee/fixtures/ecobee-data.json index e0e82d68863..87d85250780 100644 --- a/tests/components/ecobee/fixtures/ecobee-data.json +++ b/tests/components/ecobee/fixtures/ecobee-data.json @@ -67,7 +67,7 @@ "hasHeatPump": false, "humidity": "30" }, - "equipmentStatus": "fan", + "equipmentStatus": "fan,humidifier", "events": [ { "name": "Event1", diff --git a/tests/components/ecobee/test_humidifier.py b/tests/components/ecobee/test_humidifier.py index 696ca3d6c0d..6f20d38deaa 100644 --- a/tests/components/ecobee/test_humidifier.py +++ b/tests/components/ecobee/test_humidifier.py @@ -6,6 +6,7 @@ import pytest from homeassistant.components.ecobee.humidifier import MODE_MANUAL, MODE_OFF from homeassistant.components.humidifier import ( + ATTR_ACTION, ATTR_AVAILABLE_MODES, ATTR_CURRENT_HUMIDITY, ATTR_HUMIDITY, @@ -17,6 +18,7 @@ from homeassistant.components.humidifier import ( MODE_AUTO, SERVICE_SET_HUMIDITY, SERVICE_SET_MODE, + HumidifierAction, HumidifierDeviceClass, HumidifierEntityFeature, ) @@ -44,6 +46,7 @@ async def test_attributes(hass: HomeAssistant) -> None: state = hass.states.get(DEVICE_ID) assert state.state == STATE_ON + assert state.attributes[ATTR_ACTION] == HumidifierAction.HUMIDIFYING assert state.attributes[ATTR_CURRENT_HUMIDITY] == 15 assert state.attributes[ATTR_MIN_HUMIDITY] == DEFAULT_MIN_HUMIDITY assert state.attributes[ATTR_MAX_HUMIDITY] == DEFAULT_MAX_HUMIDITY