Home Assistant Unofficial Reference 2024.12.1
fan.py
Go to the documentation of this file.
1 """Support for fan entities."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from thinqconnect import DeviceType
9 from thinqconnect.integration import ExtendedProperty
10 
11 from homeassistant.components.fan import (
12  FanEntity,
13  FanEntityDescription,
14  FanEntityFeature,
15 )
16 from homeassistant.core import HomeAssistant
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19  ordered_list_item_to_percentage,
20  percentage_to_ordered_list_item,
21 )
22 
23 from . import ThinqConfigEntry
24 from .coordinator import DeviceDataUpdateCoordinator
25 from .entity import ThinQEntity
26 
27 DEVICE_TYPE_FAN_MAP: dict[DeviceType, tuple[FanEntityDescription, ...]] = {
28  DeviceType.CEILING_FAN: (
30  key=ExtendedProperty.FAN,
31  name=None,
32  ),
33  ),
34 }
35 
36 FOUR_STEP_SPEEDS = ["low", "mid", "high", "turbo"]
37 
38 _LOGGER = logging.getLogger(__name__)
39 
40 
42  hass: HomeAssistant,
43  entry: ThinqConfigEntry,
44  async_add_entities: AddEntitiesCallback,
45 ) -> None:
46  """Set up an entry for fan platform."""
47  entities: list[ThinQFanEntity] = []
48  for coordinator in entry.runtime_data.coordinators.values():
49  if (
50  descriptions := DEVICE_TYPE_FAN_MAP.get(coordinator.api.device.device_type)
51  ) is not None:
52  for description in descriptions:
53  entities.extend(
54  ThinQFanEntity(coordinator, description, property_id)
55  for property_id in coordinator.api.get_active_idx(description.key)
56  )
57 
58  if entities:
59  async_add_entities(entities)
60 
61 
63  """Represent a thinq fan platform."""
64 
65  def __init__(
66  self,
67  coordinator: DeviceDataUpdateCoordinator,
68  entity_description: FanEntityDescription,
69  property_id: str,
70  ) -> None:
71  """Initialize fan platform."""
72  super().__init__(coordinator, entity_description, property_id)
73 
74  self._ordered_named_fan_speeds_ordered_named_fan_speeds = []
75  self._attr_supported_features_attr_supported_features = (
76  FanEntityFeature.SET_SPEED
77  | FanEntityFeature.TURN_ON
78  | FanEntityFeature.TURN_OFF
79  )
80  if (fan_modes := self.datadatadatadata.fan_modes) is not None:
81  self._attr_speed_count_attr_speed_count = len(fan_modes)
82  if self.speed_countspeed_countspeed_count == 4:
83  self._ordered_named_fan_speeds_ordered_named_fan_speeds = FOUR_STEP_SPEEDS
84 
85  def _update_status(self) -> None:
86  """Update status itself."""
87  super()._update_status()
88 
89  # Update power on state.
90  self._attr_is_on_attr_is_on = self.datadatadatadata.is_on
91 
92  # Update fan speed.
93  if (
94  self.datadatadatadata.is_on
95  and (mode := self.datadatadatadata.fan_mode) in self._ordered_named_fan_speeds_ordered_named_fan_speeds
96  ):
97  self._attr_percentage_attr_percentage = ordered_list_item_to_percentage(
98  self._ordered_named_fan_speeds_ordered_named_fan_speeds, mode
99  )
100  else:
101  self._attr_percentage_attr_percentage = 0
102 
103  _LOGGER.debug(
104  "[%s:%s] update status: %s -> %s (percentage=%s)",
105  self.coordinator.device_name,
106  self.property_idproperty_id,
107  self.datadatadatadata.is_on,
108  self.is_onis_onis_on,
109  self.percentagepercentage,
110  )
111 
112  async def async_set_percentage(self, percentage: int) -> None:
113  """Set the speed percentage of the fan."""
114  if percentage == 0:
115  await self.async_turn_offasync_turn_offasync_turn_off()
116  return
117  try:
118  value = percentage_to_ordered_list_item(
119  self._ordered_named_fan_speeds_ordered_named_fan_speeds, percentage
120  )
121  except ValueError:
122  _LOGGER.exception("Failed to async_set_percentage")
123  return
124 
125  _LOGGER.debug(
126  "[%s:%s] async_set_percentage. percentage=%s, value=%s",
127  self.coordinator.device_name,
128  self.property_idproperty_id,
129  percentage,
130  value,
131  )
132  await self.async_call_apiasync_call_api(
133  self.coordinator.api.async_set_fan_mode(self.property_idproperty_id, value)
134  )
135 
136  async def async_turn_on(
137  self,
138  percentage: int | None = None,
139  preset_mode: str | None = None,
140  **kwargs: Any,
141  ) -> None:
142  """Turn on the fan."""
143  _LOGGER.debug(
144  "[%s:%s] async_turn_on", self.coordinator.device_name, self.property_idproperty_id
145  )
146  await self.async_call_apiasync_call_api(self.coordinator.api.async_turn_on(self.property_idproperty_id))
147 
148  async def async_turn_off(self, **kwargs: Any) -> None:
149  """Turn the fan off."""
150  _LOGGER.debug(
151  "[%s:%s] async_turn_off", self.coordinator.device_name, self.property_idproperty_id
152  )
153  await self.async_call_apiasync_call_api(self.coordinator.api.async_turn_off(self.property_idproperty_id))
None async_call_api(self, Coroutine[Any, Any, Any] target, Callable[[], None]|None on_fail_method=None)
Definition: entity.py:101
None async_set_percentage(self, int percentage)
Definition: fan.py:112
None __init__(self, DeviceDataUpdateCoordinator coordinator, FanEntityDescription entity_description, str property_id)
Definition: fan.py:70
None async_turn_on(self, int|None percentage=None, str|None preset_mode=None, **Any kwargs)
Definition: fan.py:141
None async_turn_off(self, **Any kwargs)
Definition: entity.py:1709
None async_setup_entry(HomeAssistant hass, ThinqConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: fan.py:45