Skip to content

Commit

Permalink
Setting fan stage with percentage controls
Browse files Browse the repository at this point in the history
  • Loading branch information
signalkraft committed Nov 4, 2023
1 parent c0d5875 commit 050097c
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
52 changes: 26 additions & 26 deletions custom_components/mypyllant/fan.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
import math
from collections.abc import Mapping
from typing import Any

Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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(
Expand Down Expand Up @@ -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()
5 changes: 5 additions & 0 deletions tests/test_fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 050097c

Please sign in to comment.