diff --git a/homeassistant/components/fan/__init__.py b/homeassistant/components/fan/__init__.py index 3a5b9bcda67..9289c899b57 100644 --- a/homeassistant/components/fan/__init__.py +++ b/homeassistant/components/fan/__init__.py @@ -235,6 +235,13 @@ class FanEntity(ToggleEntity): """Base class for fan entities.""" entity_description: FanEntityDescription + _attr_current_direction: str | None = None + _attr_oscillating: bool | None = None + _attr_percentage: int | None + _attr_preset_mode: str | None + _attr_preset_modes: list[str] | None + _attr_speed_count: int + _attr_supported_features: int = 0 @_fan_native def set_speed(self, speed: str) -> None: @@ -469,6 +476,9 @@ class FanEntity(ToggleEntity): @property def percentage(self) -> int | None: """Return the current speed as a percentage.""" + if hasattr(self, "_attr_percentage"): + return self._attr_percentage + if ( not self._implemented_preset_mode and self.preset_modes @@ -482,6 +492,9 @@ class FanEntity(ToggleEntity): @property def speed_count(self) -> int: """Return the number of speeds the fan supports.""" + if hasattr(self, "_attr_speed_count"): + return self._attr_speed_count + speed_list = speed_list_without_preset_modes(self.speed_list) if speed_list: return len(speed_list) @@ -505,12 +518,12 @@ class FanEntity(ToggleEntity): @property def current_direction(self) -> str | None: """Return the current direction of the fan.""" - return None + return self._attr_current_direction @property - def oscillating(self): + def oscillating(self) -> bool | None: """Return whether or not the fan is currently oscillating.""" - return None + return self._attr_oscillating @property def capability_attributes(self): @@ -629,7 +642,7 @@ class FanEntity(ToggleEntity): @property def supported_features(self) -> int: """Flag supported features.""" - return 0 + return self._attr_supported_features @property def preset_mode(self) -> str | None: @@ -637,6 +650,9 @@ class FanEntity(ToggleEntity): Requires SUPPORT_SET_SPEED. """ + if hasattr(self, "_attr_preset_mode"): + return self._attr_preset_mode + speed = self.speed if self.preset_modes and speed in self.preset_modes: return speed @@ -648,6 +664,9 @@ class FanEntity(ToggleEntity): Requires SUPPORT_SET_SPEED. """ + if hasattr(self, "_attr_preset_modes"): + return self._attr_preset_modes + return preset_modes_from_speed_list(self.speed_list) diff --git a/tests/components/fan/test_init.py b/tests/components/fan/test_init.py index 05ced3b8be7..3167cb16e67 100644 --- a/tests/components/fan/test_init.py +++ b/tests/components/fan/test_init.py @@ -65,3 +65,22 @@ async def test_async_fanentity(hass): await fan.async_increase_speed() with pytest.raises(NotImplementedError): await fan.async_decrease_speed() + + +@pytest.mark.parametrize( + "attribute_name, attribute_value", + [ + ("current_direction", "forward"), + ("oscillating", True), + ("percentage", 50), + ("preset_mode", "medium"), + ("preset_modes", ["low", "medium", "high"]), + ("speed_count", 50), + ("supported_features", 1), + ], +) +def test_fanentity_attributes(attribute_name, attribute_value): + """Test fan entity attribute shorthand.""" + fan = BaseFan() + setattr(fan, f"_attr_{attribute_name}", attribute_value) + assert getattr(fan, attribute_name) == attribute_value