diff --git a/custom_components/mypyllant/fan.py b/custom_components/mypyllant/fan.py index 74c934f..1a99b6b 100644 --- a/custom_components/mypyllant/fan.py +++ b/custom_components/mypyllant/fan.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +import math from collections.abc import Mapping from typing import Any @@ -13,8 +14,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util.percentage import ( - ordered_list_item_to_percentage, - percentage_to_ordered_list_item, + percentage_to_ranged_value, + ranged_value_to_percentage, ) from myPyllant.models import ( System, @@ -69,7 +70,8 @@ class VentilationFan(CoordinatorEntity, FanEntity): coordinator: SystemCoordinator _attr_preset_modes = [str(k) for k in VentilationOperationMode] _attr_temperature_unit = UnitOfTemperature.CELSIUS - _attr_speed_count = len(FAN_SPEED_OPTIONS) + _attr_speed_count = 6 + _low_high_range = (1, _attr_speed_count) def __init__( self, @@ -90,6 +92,16 @@ def system(self) -> System: def ventilation(self) -> Ventilation: return self.system.ventilation[self.ventilation_index] + @property + def maximum_fan_stage(self): + if ( + self.ventilation.operation_mode_ventilation + == VentilationOperationMode.REDUCED + ): + return self.ventilation.maximum_night_fan_stage + else: + return self.ventilation.maximum_day_fan_stage + @property def device_info(self) -> DeviceInfo: return DeviceInfo( @@ -165,32 +177,20 @@ async def async_set_preset_mode(self, preset_mode): @property def percentage(self) -> int | None: - # See https://developers.home-assistant.io/docs/core/entity/fan#set-speed-percentage + return ranged_value_to_percentage(self._low_high_range, self.maximum_fan_stage) + + async def async_set_percentage(self, percentage: int) -> None: if ( self.ventilation.operation_mode_ventilation - == VentilationOperationMode.TIME_CONTROLLED + == VentilationOperationMode.REDUCED ): - return 100 - elif ( - self.ventilation.operation_mode_ventilation == VentilationOperationMode.OFF - ): - return 0 + fan_stage_type = VentilationFanStageType.NIGHT else: - return ordered_list_item_to_percentage( - FAN_SPEED_OPTIONS, - self.ventilation.operation_mode_ventilation, - ) + fan_stage_type = VentilationFanStageType.DAY - async def async_set_percentage(self, percentage: int) -> None: - if percentage == 0: - await self.coordinator.api.set_ventilation_operation_mode( - self.ventilation, - VentilationOperationMode.OFF, - ) - else: - mode = percentage_to_ordered_list_item(FAN_SPEED_OPTIONS, percentage) - await self.coordinator.api.set_ventilation_operation_mode( - self.ventilation, - mode, - ) + await self.coordinator.api.set_ventilation_fan_stage( + self.ventilation, + math.ceil(percentage_to_ranged_value(self._low_high_range, percentage)), + fan_stage_type, + ) await self.coordinator.async_request_refresh_delayed() diff --git a/tests/test_fan.py b/tests/test_fan.py index d90a499..2c3c925 100644 --- a/tests/test_fan.py +++ b/tests/test_fan.py @@ -30,7 +30,12 @@ async def test_ventilation_fan( assert isinstance(ventilation.device_info, dict) assert isinstance(ventilation.extra_state_attributes, dict) assert isinstance(ventilation.preset_mode, str) + assert isinstance(ventilation.percentage, int) await ventilation.async_set_preset_mode(str(VentilationOperationMode.REDUCED)) + await ventilation.async_set_percentage(0) + await ventilation.async_set_percentage(25) + await ventilation.async_set_percentage(50) + await ventilation.async_set_percentage(100) system_coordinator_mock._debounced_refresh.async_cancel() await mocked_api.aiohttp_session.close()