Home Assistant Unofficial Reference 2024.12.1
fan.py
Go to the documentation of this file.
1 """Represent an air purifier."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from typing import Any, cast
7 
8 from pytradfri.command import Command
9 
10 from homeassistant.components.fan import FanEntity, FanEntityFeature
11 from homeassistant.config_entries import ConfigEntry
12 from homeassistant.core import HomeAssistant
13 from homeassistant.helpers.entity_platform import AddEntitiesCallback
14 
15 from .const import CONF_GATEWAY_ID, COORDINATOR, COORDINATOR_LIST, DOMAIN, KEY_API
16 from .coordinator import TradfriDeviceDataUpdateCoordinator
17 from .entity import TradfriBaseEntity
18 
19 ATTR_AUTO = "Auto"
20 ATTR_MAX_FAN_STEPS = 49
21 
22 
23 def _from_fan_percentage(percentage: int) -> int:
24  """Convert percent to a value that the Tradfri API understands."""
25  return round(max(2, (percentage / 100 * ATTR_MAX_FAN_STEPS) + 1))
26 
27 
28 def _from_fan_speed(fan_speed: int) -> int:
29  """Convert the Tradfri API fan speed to a percentage value."""
30  return max(round((fan_speed - 1) / ATTR_MAX_FAN_STEPS * 100), 0)
31 
32 
34  hass: HomeAssistant,
35  config_entry: ConfigEntry,
36  async_add_entities: AddEntitiesCallback,
37 ) -> None:
38  """Load Tradfri switches based on a config entry."""
39  gateway_id = config_entry.data[CONF_GATEWAY_ID]
40  coordinator_data = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR]
41  api = coordinator_data[KEY_API]
42 
45  device_coordinator,
46  api,
47  gateway_id,
48  )
49  for device_coordinator in coordinator_data[COORDINATOR_LIST]
50  if device_coordinator.device.has_air_purifier_control
51  )
52 
53 
55  """The platform class required by Home Assistant."""
56 
57  _attr_name = None
58  _attr_supported_features = (
59  FanEntityFeature.PRESET_MODE
60  | FanEntityFeature.SET_SPEED
61  | FanEntityFeature.TURN_ON
62  | FanEntityFeature.TURN_OFF
63  )
64  _attr_preset_modes = [ATTR_AUTO]
65  # These are the steps:
66  # 0 = Off
67  # 1 = Preset: Auto mode
68  # 2 = Min
69  # ... with step size 1
70  # 50 = Max
71  _attr_speed_count = ATTR_MAX_FAN_STEPS
72  _enable_turn_on_off_backwards_compatibility = False
73 
74  def __init__(
75  self,
76  device_coordinator: TradfriDeviceDataUpdateCoordinator,
77  api: Callable[[Command | list[Command]], Any],
78  gateway_id: str,
79  ) -> None:
80  """Initialize a switch."""
81  super().__init__(
82  device_coordinator=device_coordinator,
83  api=api,
84  gateway_id=gateway_id,
85  )
86 
87  self._device_control_device_control = self._device.air_purifier_control
88  self._device_data_device_data = self._device_control_device_control.air_purifiers[0]
89 
90  def _refresh(self) -> None:
91  """Refresh the device."""
92  self._device_data_device_data = self.coordinator.data.air_purifier_control.air_purifiers[0]
93 
94  @property
95  def is_on(self) -> bool:
96  """Return true if switch is on."""
97  if not self._device_data_device_data:
98  return False
99  return cast(bool, self._device_data_device_data.state)
100 
101  @property
102  def percentage(self) -> int | None:
103  """Return the current speed percentage."""
104  if not self._device_data_device_data:
105  return None
106 
107  if self._device_data_device_data.fan_speed:
108  return _from_fan_speed(self._device_data_device_data.fan_speed)
109 
110  return None
111 
112  @property
113  def preset_mode(self) -> str | None:
114  """Return the current preset mode."""
115  if not self._device_data_device_data:
116  return None
117 
118  if self._device_data_device_data.is_auto_mode:
119  return ATTR_AUTO
120 
121  return None
122 
123  async def async_set_preset_mode(self, preset_mode: str) -> None:
124  """Set the preset mode of the fan."""
125  if not self._device_control_device_control:
126  return
127 
128  # Preset must be 'Auto'
129 
130  await self._api_api(self._device_control_device_control.turn_on_auto_mode())
131 
132  async def async_turn_on(
133  self,
134  percentage: int | None = None,
135  preset_mode: str | None = None,
136  **kwargs: Any,
137  ) -> None:
138  """Turn on the fan. Auto-mode if no argument is given."""
139  if not self._device_control_device_control:
140  return
141 
142  if percentage is not None:
143  await self.async_set_percentageasync_set_percentageasync_set_percentage(percentage)
144  return
145 
146  preset_mode = preset_mode or ATTR_AUTO
147  await self.async_set_preset_modeasync_set_preset_modeasync_set_preset_mode(preset_mode)
148 
149  async def async_set_percentage(self, percentage: int) -> None:
150  """Set the speed percentage of the fan."""
151  if not self._device_control_device_control:
152  return
153 
154  if percentage == 0:
155  await self.async_turn_offasync_turn_offasync_turn_off()
156  return
157 
158  await self._api_api(
159  self._device_control_device_control.set_fan_speed(_from_fan_percentage(percentage))
160  )
161 
162  async def async_turn_off(self, **kwargs: Any) -> None:
163  """Turn off the fan."""
164  if not self._device_control_device_control:
165  return
166  await self._api_api(self._device_control_device_control.turn_off())
None async_set_percentage(self, int percentage)
Definition: __init__.py:340
None async_set_preset_mode(self, str preset_mode)
Definition: __init__.py:385
None __init__(self, TradfriDeviceDataUpdateCoordinator device_coordinator, Callable[[Command|list[Command]], Any] api, str gateway_id)
Definition: fan.py:79
None async_set_preset_mode(self, str preset_mode)
Definition: fan.py:123
None async_turn_on(self, int|None percentage=None, str|None preset_mode=None, **Any kwargs)
Definition: fan.py:137
None async_turn_off(self, **Any kwargs)
Definition: entity.py:1709
None turn_off(self, **Any kwargs)
Definition: entity.py:1705
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: fan.py:37
int _from_fan_speed(int fan_speed)
Definition: fan.py:28
int _from_fan_percentage(int percentage)
Definition: fan.py:23