diff --git a/homeassistant/components/tradfri/const.py b/homeassistant/components/tradfri/const.py index b0c3955453c..487eb0dae13 100644 --- a/homeassistant/components/tradfri/const.py +++ b/homeassistant/components/tradfri/const.py @@ -36,3 +36,4 @@ PLATFORMS = [ Platform.SWITCH, ] TIMEOUT_API = 30 +ATTR_MAX_FAN_STEPS = 49 diff --git a/homeassistant/components/tradfri/fan.py b/homeassistant/components/tradfri/fan.py index dab39f598f2..e01d4d3b574 100644 --- a/homeassistant/components/tradfri/fan.py +++ b/homeassistant/components/tradfri/fan.py @@ -17,7 +17,24 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .base_class import TradfriBaseDevice -from .const import ATTR_AUTO, CONF_GATEWAY_ID, DEVICES, DOMAIN, KEY_API +from .const import ( + ATTR_AUTO, + ATTR_MAX_FAN_STEPS, + CONF_GATEWAY_ID, + DEVICES, + DOMAIN, + KEY_API, +) + + +def _from_fan_percentage(percentage: int) -> int: + """Convert percent to a value that the Tradfri API understands.""" + return round(max(2, (percentage / 100 * ATTR_MAX_FAN_STEPS) + 1)) + + +def _from_fan_speed(fan_speed: int) -> int: + """Convert the Tradfri API fan speed to a percentage value.""" + return max(round((fan_speed - 1) / ATTR_MAX_FAN_STEPS * 100), 0) async def async_setup_entry( @@ -38,23 +55,6 @@ async def async_setup_entry( ) -def _from_percentage(percentage: int) -> int: - """Convert percent to a value that the Tradfri API understands.""" - if percentage < 20: - # The device cannot be set to speed 5 (10%), so we should turn off the device - # for any value below 20 - return 0 - - nearest_10: int = round(percentage / 10) * 10 # Round to nearest multiple of 10 - return round(nearest_10 / 100 * 50) - - -def _from_fan_speed(fan_speed: int) -> int: - """Convert the Tradfri API fan speed to a percentage value.""" - nearest_10: int = round(fan_speed / 10) * 10 # Round to nearest multiple of 10 - return round(nearest_10 / 50 * 100) - - class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): """The platform class required by Home Assistant.""" @@ -80,24 +80,19 @@ class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): These are the steps: 0 = Off - 10 = Min - 15 - 20 - 25 - 30 - 35 - 40 - 45 + 1 = Preset: Auto mode + 2 = Min + ... with step size 1 50 = Max """ - return 10 + return ATTR_MAX_FAN_STEPS @property def is_on(self) -> bool: """Return true if switch is on.""" if not self._device_data: return False - return cast(bool, self._device_data.mode) + return cast(bool, self._device_data.state) @property def preset_modes(self) -> list[str] | None: @@ -121,7 +116,7 @@ class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): if not self._device_data: return None - if self._device_data.mode == ATTR_AUTO: + if self._device_data.is_auto_mode: return ATTR_AUTO return None @@ -133,7 +128,8 @@ class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): if not preset_mode == ATTR_AUTO: raise ValueError("Preset must be 'Auto'.") - await self._api(self._device_control.set_mode(1)) + + await self._api(self._device_control.turn_on_auto_mode()) async def async_turn_on( self, @@ -147,7 +143,7 @@ class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): return if percentage is not None: - await self._api(self._device_control.set_mode(_from_percentage(percentage))) + await self.async_set_percentage(percentage) return preset_mode = preset_mode or ATTR_AUTO @@ -158,13 +154,19 @@ class TradfriAirPurifierFan(TradfriBaseDevice, FanEntity): if not self._device_control: return - await self._api(self._device_control.set_mode(_from_percentage(percentage))) + if percentage == 0: + await self.async_turn_off() + return + + await self._api( + self._device_control.set_fan_speed(_from_fan_percentage(percentage)) + ) async def async_turn_off(self, **kwargs: Any) -> None: """Turn off the fan.""" if not self._device_control: return - await self._api(self._device_control.set_mode(0)) + await self._api(self._device_control.turn_off()) def _refresh(self, device: Command, write_ha: bool = True) -> None: """Refresh the purifier data.""" diff --git a/homeassistant/components/tradfri/manifest.json b/homeassistant/components/tradfri/manifest.json index b13abda25b0..1ac82d0b84c 100644 --- a/homeassistant/components/tradfri/manifest.json +++ b/homeassistant/components/tradfri/manifest.json @@ -3,7 +3,7 @@ "name": "IKEA TR\u00c5DFRI", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/tradfri", - "requirements": ["pytradfri[async]==7.2.1"], + "requirements": ["pytradfri[async]==8.0.1"], "homekit": { "models": ["TRADFRI"] }, diff --git a/requirements_all.txt b/requirements_all.txt index ea3f14c1f8c..954ac7802ee 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2005,7 +2005,7 @@ pytouchline==0.7 pytraccar==0.10.0 # homeassistant.components.tradfri -pytradfri[async]==7.2.1 +pytradfri[async]==8.0.1 # homeassistant.components.trafikverket_train # homeassistant.components.trafikverket_weatherstation diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fdc85428338..b7adbb40e20 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1230,7 +1230,7 @@ pytile==2021.12.0 pytraccar==0.10.0 # homeassistant.components.tradfri -pytradfri[async]==7.2.1 +pytradfri[async]==8.0.1 # homeassistant.components.trafikverket_train # homeassistant.components.trafikverket_weatherstation diff --git a/tests/components/tradfri/test_util.py b/tests/components/tradfri/test_util.py index 3dbdf801f89..67d5b95f5d8 100644 --- a/tests/components/tradfri/test_util.py +++ b/tests/components/tradfri/test_util.py @@ -1,22 +1,31 @@ """Tradfri utility function tests.""" +import pytest -from homeassistant.components.tradfri.fan import _from_fan_speed, _from_percentage +from homeassistant.components.tradfri.fan import _from_fan_percentage, _from_fan_speed -def test_from_fan_speed(): +@pytest.mark.parametrize( + "fan_speed, expected_result", + [ + (0, 0), + (2, 2), + (25, 49), + (50, 100), + ], +) +def test_from_fan_speed(fan_speed, expected_result): """Test that we can convert fan speed to percentage value.""" - assert _from_fan_speed(41) == 80 + assert _from_fan_speed(fan_speed) == expected_result -def test_from_percentage(): +@pytest.mark.parametrize( + "percentage, expected_result", + [ + (1, 2), + (100, 50), + (50, 26), + ], +) +def test_from_percentage(percentage, expected_result): """Test that we can convert percentage value to fan speed.""" - assert _from_percentage(84) == 40 - - -def test_from_percentage_limit(): - """ - Test that we can convert percentage value to fan speed. - - Handle special case of percent value being below 20. - """ - assert _from_percentage(10) == 0 + assert _from_fan_percentage(percentage) == expected_result