Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for the Airzone sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from typing import Any, Final
8 
9 from aioairzone.common import GrilleAngle, OperationMode, SleepTimeout
10 from aioairzone.const import (
11  API_COLD_ANGLE,
12  API_HEAT_ANGLE,
13  API_MODE,
14  API_SLEEP,
15  AZD_COLD_ANGLE,
16  AZD_HEAT_ANGLE,
17  AZD_MASTER,
18  AZD_MODE,
19  AZD_MODES,
20  AZD_SLEEP,
21  AZD_ZONES,
22 )
23 
24 from homeassistant.components.select import SelectEntity, SelectEntityDescription
25 from homeassistant.config_entries import ConfigEntry
26 from homeassistant.const import EntityCategory
27 from homeassistant.core import HomeAssistant, callback
28 from homeassistant.helpers.entity_platform import AddEntitiesCallback
29 
30 from . import AirzoneConfigEntry
31 from .coordinator import AirzoneUpdateCoordinator
32 from .entity import AirzoneEntity, AirzoneZoneEntity
33 
34 
35 @dataclass(frozen=True, kw_only=True)
37  """Class to describe an Airzone select entity."""
38 
39  api_param: str
40  options_dict: dict[str, int]
41  options_fn: Callable[[dict[str, Any], dict[str, int]], list[str]] = (
42  lambda zone_data, value: list(value)
43  )
44 
45 
46 GRILLE_ANGLE_DICT: Final[dict[str, int]] = {
47  "90deg": GrilleAngle.DEG_90,
48  "50deg": GrilleAngle.DEG_50,
49  "45deg": GrilleAngle.DEG_45,
50  "40deg": GrilleAngle.DEG_40,
51 }
52 
53 MODE_DICT: Final[dict[str, int]] = {
54  "cool": OperationMode.COOLING,
55  "dry": OperationMode.DRY,
56  "fan": OperationMode.FAN,
57  "heat": OperationMode.HEATING,
58  "heat_cool": OperationMode.AUTO,
59  "stop": OperationMode.STOP,
60 }
61 
62 SLEEP_DICT: Final[dict[str, int]] = {
63  "off": SleepTimeout.SLEEP_OFF,
64  "30m": SleepTimeout.SLEEP_30,
65  "60m": SleepTimeout.SLEEP_60,
66  "90m": SleepTimeout.SLEEP_90,
67 }
68 
69 
71  zone_data: dict[str, Any],
72  options: dict[str, int],
73 ) -> list[str]:
74  """Filter available modes."""
75  modes = zone_data.get(AZD_MODES, [])
76  return [k for k, v in options.items() if v in modes]
77 
78 
79 MAIN_ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
81  api_param=API_MODE,
82  key=AZD_MODE,
83  options_dict=MODE_DICT,
84  options_fn=main_zone_options,
85  translation_key="modes",
86  ),
87 )
88 
89 
90 ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
92  api_param=API_COLD_ANGLE,
93  entity_category=EntityCategory.CONFIG,
94  key=AZD_COLD_ANGLE,
95  options=list(GRILLE_ANGLE_DICT),
96  options_dict=GRILLE_ANGLE_DICT,
97  translation_key="grille_angles",
98  ),
100  api_param=API_HEAT_ANGLE,
101  entity_category=EntityCategory.CONFIG,
102  key=AZD_HEAT_ANGLE,
103  options=list(GRILLE_ANGLE_DICT),
104  options_dict=GRILLE_ANGLE_DICT,
105  translation_key="heat_angles",
106  ),
108  api_param=API_SLEEP,
109  entity_category=EntityCategory.CONFIG,
110  key=AZD_SLEEP,
111  options=list(SLEEP_DICT),
112  options_dict=SLEEP_DICT,
113  translation_key="sleep_times",
114  ),
115 )
116 
117 
119  hass: HomeAssistant,
120  entry: AirzoneConfigEntry,
121  async_add_entities: AddEntitiesCallback,
122 ) -> None:
123  """Add Airzone select from a config_entry."""
124  coordinator = entry.runtime_data
125 
126  added_zones: set[str] = set()
127 
128  def _async_entity_listener() -> None:
129  """Handle additions of select."""
130 
131  zones_data = coordinator.data.get(AZD_ZONES, {})
132  received_zones = set(zones_data)
133  new_zones = received_zones - added_zones
134  if new_zones:
135  entities: list[AirzoneZoneSelect] = [
137  coordinator,
138  description,
139  entry,
140  system_zone_id,
141  zones_data.get(system_zone_id),
142  )
143  for system_zone_id in new_zones
144  for description in MAIN_ZONE_SELECT_TYPES
145  if description.key in zones_data.get(system_zone_id)
146  and zones_data.get(system_zone_id).get(AZD_MASTER) is True
147  ]
148  entities += [
150  coordinator,
151  description,
152  entry,
153  system_zone_id,
154  zones_data.get(system_zone_id),
155  )
156  for system_zone_id in new_zones
157  for description in ZONE_SELECT_TYPES
158  if description.key in zones_data.get(system_zone_id)
159  ]
160  async_add_entities(entities)
161  added_zones.update(new_zones)
162 
163  entry.async_on_unload(coordinator.async_add_listener(_async_entity_listener))
164  _async_entity_listener()
165 
166 
168  """Define an Airzone select."""
169 
170  entity_description: AirzoneSelectDescription
171  values_dict: dict[int, str]
172 
173  @callback
174  def _handle_coordinator_update(self) -> None:
175  """Update attributes when the coordinator updates."""
176  self._async_update_attrs_async_update_attrs()
178 
179  def _get_current_option(self) -> str | None:
180  value = self.get_airzone_valueget_airzone_value(self.entity_description.key)
181  return self.values_dict.get(value)
182 
183  @callback
184  def _async_update_attrs(self) -> None:
185  """Update select attributes."""
186  self._attr_current_option_attr_current_option = self._get_current_option_get_current_option()
187 
188 
190  """Define an Airzone Zone select."""
191 
192  def __init__(
193  self,
194  coordinator: AirzoneUpdateCoordinator,
195  description: AirzoneSelectDescription,
196  entry: ConfigEntry,
197  system_zone_id: str,
198  zone_data: dict[str, Any],
199  ) -> None:
200  """Initialize."""
201  super().__init__(coordinator, entry, system_zone_id, zone_data)
202 
203  self._attr_unique_id_attr_unique_id_attr_unique_id = (
204  f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
205  )
206  self.entity_descriptionentity_description = description
207 
208  self._attr_options_attr_options = self.entity_descriptionentity_description.options_fn(
209  zone_data, description.options_dict
210  )
211 
212  self.values_dictvalues_dict = {v: k for k, v in description.options_dict.items()}
213 
214  self._async_update_attrs_async_update_attrs()
215 
216  async def async_select_option(self, option: str) -> None:
217  """Change the selected option."""
218  param = self.entity_descriptionentity_description.api_param
219  value = self.entity_descriptionentity_description.options_dict[option]
220  await self._async_update_hvac_params_async_update_hvac_params({param: value})
None _async_update_hvac_params(self, dict[str, Any] params)
Definition: entity.py:196
None __init__(self, AirzoneUpdateCoordinator coordinator, AirzoneSelectDescription description, ConfigEntry entry, str system_zone_id, dict[str, Any] zone_data)
Definition: select.py:199
None async_setup_entry(HomeAssistant hass, AirzoneConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: select.py:122
list[str] main_zone_options(dict[str, Any] zone_data, dict[str, int] options)
Definition: select.py:73
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88