From f1b1cac91a9d11209276576b8ccb694b5742783a Mon Sep 17 00:00:00 2001 From: Edward Brown Date: Fri, 1 May 2026 09:43:46 +0100 Subject: [PATCH] Migrate Fan control from v0 --- haco/fan.py | 101 ++++++++++++++++++++++++++++++++++++++++++++ haco/v0/haco/fan.py | 57 ------------------------- 2 files changed, 101 insertions(+), 57 deletions(-) create mode 100644 haco/fan.py delete mode 100644 haco/v0/haco/fan.py diff --git a/haco/fan.py b/haco/fan.py new file mode 100644 index 0000000..5c729c2 --- /dev/null +++ b/haco/fan.py @@ -0,0 +1,101 @@ +from dataclasses import dataclass + +from haco.capabilities import Capability +from haco.control import Control +from haco.utils import ON, OFF, ConvertersNumeric, ConvertersString + + +@dataclass(kw_only=True) +class Fan(Control): + """ + + A fan control with support for speed percentage, preset modes, and oscillation. + + """ + DATA = dict( + platform="fan" + ) + + speed_range_min: int | None = None + speed_range_max: int | None = None + preset_modes: list[str] | None = None + payload_oscillation_on: str = ON + payload_oscillation_off: str = OFF + + def command(self, value: bool) -> bool: + """ + + Handle on/off commands for the fan. + + """ + raise NotImplementedError() + + def state(self, value: bool | None) -> bool: + """ + + Return the current on/off state of the fan. + + """ + raise NotImplementedError() + + def preset_mode_command(self, value: str) -> str: + """ + + Handle preset mode commands. + + """ + raise NotImplementedError() + + def preset_mode_state(self, value: str | None) -> str: + """ + + Return the current preset mode. + + """ + raise NotImplementedError() + + def percentage_command(self, value: int) -> int: + """ + + Handle percentage (speed) commands. + + """ + raise NotImplementedError() + + def percentage_state(self, value: int | None) -> int: + """ + + Return the current speed percentage. + + """ + raise NotImplementedError() + + def oscillation_command(self, value: bool) -> bool: + """ + + Handle oscillation toggle commands. + + """ + raise NotImplementedError() + + def oscillation_state(self, value: bool | None) -> bool: + """ + + Return the current oscillation state. + + """ + raise NotImplementedError() + + @classmethod + def get_capabilities(cls) -> list[Capability]: + """ + + Get the capabilities for the fan control. + + """ + return [ + Capability(name=None), + Capability(name="preset_mode", converters=ConvertersString), + Capability(name="percentage", converters=ConvertersNumeric), + Capability(name="oscillation"), + ] diff --git a/haco/v0/haco/fan.py b/haco/v0/haco/fan.py deleted file mode 100644 index c6472d7..0000000 --- a/haco/v0/haco/fan.py +++ /dev/null @@ -1,57 +0,0 @@ -from haco.control import Control -from haco.schema import Schema, Capability, AnnounceTopic, Tasmota, ControlType, HomeAssistant -from haco.tools import get_range_pair, invert_bool - -from haco import constants - - -class Fan(Control): - NAME = 'fan' - - @classmethod - def get_schema(cls): - schema = Schema( - capabilities=[ - Capability( - ha=HomeAssistant(announce_data=AnnounceTopic(key='{io_ha}_topic')), - tasmota=Tasmota(announce_data=AnnounceTopic(key='{io_ha}_topic')) - ), - Capability( - name='preset_mode', - type=str - ), - Capability( - name='percentage', - type=int - ), - Capability( - name='oscillation', - type=ControlType - ) - - ] - ) - return schema - - def __init__(self, name=None, preset_modes=None, icon=None, speed_range=None): - self.temperature_unit = speed_range - self.speed_min, self.speed_max = get_range_pair(speed_range) - self.preset_modes = preset_modes - - super().__init__(name, icon=icon) - - def get_config_ha_ex(self): - data = { - 'speed_range_min': self.speed_min, - 'speed_range_max': self.speed_max, - 'preset_modes': self.preset_modes, - 'payload_oscillation_on': constants.ON, - 'payload_oscillation_off': constants.OFF, - - } - - return data - - @property - def control_type(self): - return invert_bool