Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for OpenTherm Gateway select entities."""
2 
3 from collections.abc import Awaitable, Callable
4 from dataclasses import dataclass
5 from enum import IntEnum, StrEnum
6 from functools import partial
7 
8 from pyotgw.vars import (
9  OTGW_GPIO_A,
10  OTGW_GPIO_B,
11  OTGW_LED_A,
12  OTGW_LED_B,
13  OTGW_LED_C,
14  OTGW_LED_D,
15  OTGW_LED_E,
16  OTGW_LED_F,
17 )
18 
19 from homeassistant.components.select import SelectEntity, SelectEntityDescription
20 from homeassistant.config_entries import ConfigEntry
21 from homeassistant.const import CONF_ID, EntityCategory
22 from homeassistant.core import HomeAssistant, callback
23 from homeassistant.helpers.entity_platform import AddEntitiesCallback
24 
25 from . import OpenThermGatewayHub
26 from .const import (
27  DATA_GATEWAYS,
28  DATA_OPENTHERM_GW,
29  GATEWAY_DEVICE_DESCRIPTION,
30  OpenThermDataSource,
31 )
32 from .entity import OpenThermEntityDescription, OpenThermStatusEntity
33 
34 
35 class OpenThermSelectGPIOMode(StrEnum):
36  """OpenTherm Gateway GPIO modes."""
37 
38  INPUT = "input"
39  GROUND = "ground"
40  VCC = "vcc"
41  LED_E = "led_e"
42  LED_F = "led_f"
43  HOME = "home"
44  AWAY = "away"
45  DS1820 = "ds1820"
46  DHW_BLOCK = "dhw_block"
47 
48 
49 class OpenThermSelectLEDMode(StrEnum):
50  """OpenThermGateway LED modes."""
51 
52  RX_ANY = "receive_any"
53  TX_ANY = "transmit_any"
54  THERMOSTAT_TRAFFIC = "thermostat_traffic"
55  BOILER_TRAFFIC = "boiler_traffic"
56  SETPOINT_OVERRIDE_ACTIVE = "setpoint_override_active"
57  FLAME_ON = "flame_on"
58  CENTRAL_HEATING_ON = "central_heating_on"
59  HOT_WATER_ON = "hot_water_on"
60  COMFORT_MODE_ON = "comfort_mode_on"
61  TX_ERROR_DETECTED = "transmit_error_detected"
62  BOILER_MAINTENANCE_REQUIRED = "boiler_maintenance_required"
63  RAISED_POWER_MODE_ACTIVE = "raised_power_mode_active"
64 
65 
66 class PyotgwGPIOMode(IntEnum):
67  """pyotgw GPIO modes."""
68 
69  INPUT = 0
70  GROUND = 1
71  VCC = 2
72  LED_E = 3
73  LED_F = 4
74  HOME = 5
75  AWAY = 6
76  DS1820 = 7
77  DHW_BLOCK = 8
78 
79 
80 class PyotgwLEDMode(StrEnum):
81  """pyotgw LED modes."""
82 
83  RX_ANY = "R"
84  TX_ANY = "X"
85  THERMOSTAT_TRAFFIC = "T"
86  BOILER_TRAFFIC = "B"
87  SETPOINT_OVERRIDE_ACTIVE = "O"
88  FLAME_ON = "F"
89  CENTRAL_HEATING_ON = "H"
90  HOT_WATER_ON = "W"
91  COMFORT_MODE_ON = "C"
92  TX_ERROR_DETECTED = "E"
93  BOILER_MAINTENANCE_REQUIRED = "M"
94  RAISED_POWER_MODE_ACTIVE = "P"
95 
96 
98  pyotgw_led_mode: PyotgwLEDMode,
99 ) -> OpenThermSelectLEDMode | None:
100  """Convert pyotgw LED mode to Home Assistant LED mode."""
101  return (
102  OpenThermSelectLEDMode[PyotgwLEDMode(pyotgw_led_mode).name]
103  if pyotgw_led_mode in PyotgwLEDMode
104  else None
105  )
106 
107 
108 async def set_gpio_mode(
109  gpio_id: str, gw_hub: OpenThermGatewayHub, mode: str
110 ) -> OpenThermSelectGPIOMode | None:
111  """Set gpio mode, return selected option or None."""
112  value = await gw_hub.gateway.set_gpio_mode(
113  gpio_id, PyotgwGPIOMode[OpenThermSelectGPIOMode(mode).name]
114  )
115  return (
116  OpenThermSelectGPIOMode[PyotgwGPIOMode(value).name]
117  if value in PyotgwGPIOMode
118  else None
119  )
120 
121 
122 async def set_led_mode(
123  led_id: str, gw_hub: OpenThermGatewayHub, mode: str
124 ) -> OpenThermSelectLEDMode | None:
125  """Set gpio mode, return selected option or None."""
126  value = await gw_hub.gateway.set_led_mode(
127  led_id, PyotgwLEDMode[OpenThermSelectLEDMode(mode).name]
128  )
129  return (
130  OpenThermSelectLEDMode[PyotgwLEDMode(value).name]
131  if value in PyotgwLEDMode
132  else None
133  )
134 
135 
136 @dataclass(frozen=True, kw_only=True)
138  OpenThermEntityDescription, SelectEntityDescription
139 ):
140  """Describes an opentherm_gw select entity."""
141 
142  select_action: Callable[[OpenThermGatewayHub, str], Awaitable]
143  convert_pyotgw_state_to_ha_state: Callable
144 
145 
146 SELECT_DESCRIPTIONS: tuple[OpenThermSelectEntityDescription, ...] = (
148  key=OTGW_GPIO_A,
149  translation_key="gpio_mode_n",
150  translation_placeholders={"gpio_id": "A"},
151  device_description=GATEWAY_DEVICE_DESCRIPTION,
152  options=[
153  mode
154  for mode in OpenThermSelectGPIOMode
155  if mode != OpenThermSelectGPIOMode.DS1820
156  ],
157  select_action=partial(set_gpio_mode, "A"),
158  convert_pyotgw_state_to_ha_state=(
159  lambda state: OpenThermSelectGPIOMode[PyotgwGPIOMode(state).name]
160  if state in PyotgwGPIOMode
161  else None
162  ),
163  ),
165  key=OTGW_GPIO_B,
166  translation_key="gpio_mode_n",
167  translation_placeholders={"gpio_id": "B"},
168  device_description=GATEWAY_DEVICE_DESCRIPTION,
169  options=list(OpenThermSelectGPIOMode),
170  select_action=partial(set_gpio_mode, "B"),
171  convert_pyotgw_state_to_ha_state=(
172  lambda state: OpenThermSelectGPIOMode[PyotgwGPIOMode(state).name]
173  if state in PyotgwGPIOMode
174  else None
175  ),
176  ),
178  key=OTGW_LED_A,
179  translation_key="led_mode_n",
180  translation_placeholders={"led_id": "A"},
181  device_description=GATEWAY_DEVICE_DESCRIPTION,
182  options=list(OpenThermSelectLEDMode),
183  select_action=partial(set_led_mode, "A"),
184  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
185  ),
187  key=OTGW_LED_B,
188  translation_key="led_mode_n",
189  translation_placeholders={"led_id": "B"},
190  device_description=GATEWAY_DEVICE_DESCRIPTION,
191  options=list(OpenThermSelectLEDMode),
192  select_action=partial(set_led_mode, "B"),
193  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
194  ),
196  key=OTGW_LED_C,
197  translation_key="led_mode_n",
198  translation_placeholders={"led_id": "C"},
199  device_description=GATEWAY_DEVICE_DESCRIPTION,
200  options=list(OpenThermSelectLEDMode),
201  select_action=partial(set_led_mode, "C"),
202  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
203  ),
205  key=OTGW_LED_D,
206  translation_key="led_mode_n",
207  translation_placeholders={"led_id": "D"},
208  device_description=GATEWAY_DEVICE_DESCRIPTION,
209  options=list(OpenThermSelectLEDMode),
210  select_action=partial(set_led_mode, "D"),
211  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
212  ),
214  key=OTGW_LED_E,
215  translation_key="led_mode_n",
216  translation_placeholders={"led_id": "E"},
217  device_description=GATEWAY_DEVICE_DESCRIPTION,
218  options=list(OpenThermSelectLEDMode),
219  select_action=partial(set_led_mode, "E"),
220  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
221  ),
223  key=OTGW_LED_F,
224  translation_key="led_mode_n",
225  translation_placeholders={"led_id": "F"},
226  device_description=GATEWAY_DEVICE_DESCRIPTION,
227  options=list(OpenThermSelectLEDMode),
228  select_action=partial(set_led_mode, "F"),
229  convert_pyotgw_state_to_ha_state=pyotgw_led_mode_to_ha_led_mode,
230  ),
231 )
232 
233 
235  hass: HomeAssistant,
236  config_entry: ConfigEntry,
237  async_add_entities: AddEntitiesCallback,
238 ) -> None:
239  """Set up the OpenTherm Gateway select entities."""
240  gw_hub = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][config_entry.data[CONF_ID]]
241 
243  OpenThermSelect(gw_hub, description) for description in SELECT_DESCRIPTIONS
244  )
245 
246 
248  """Represent an OpenTherm Gateway select."""
249 
250  _attr_current_option = None
251  _attr_entity_category = EntityCategory.CONFIG
252  entity_description: OpenThermSelectEntityDescription
253 
254  async def async_select_option(self, option: str) -> None:
255  """Change the selected option."""
256  new_option = await self.entity_descriptionentity_description.select_action(self._gateway_gateway, option)
257  if new_option is not None:
258  self._attr_current_option_attr_current_option = new_option
259  self.async_write_ha_stateasync_write_ha_state()
260 
261  @callback
262  def receive_report(self, status: dict[OpenThermDataSource, dict]) -> None:
263  """Handle status updates from the component."""
264  state = status[self.entity_descriptionentity_description.device_description.data_source].get(
265  self.entity_descriptionentity_description.key
266  )
267  self._attr_current_option_attr_current_option = (
268  self.entity_descriptionentity_description.convert_pyotgw_state_to_ha_state(state)
269  )
270  self.async_write_ha_stateasync_write_ha_state()
None receive_report(self, dict[OpenThermDataSource, dict] status)
Definition: select.py:262
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: select.py:238
OpenThermSelectLEDMode|None pyotgw_led_mode_to_ha_led_mode(PyotgwLEDMode pyotgw_led_mode)
Definition: select.py:99
OpenThermSelectLEDMode|None set_led_mode(str led_id, OpenThermGatewayHub gw_hub, str mode)
Definition: select.py:124
OpenThermSelectGPIOMode|None set_gpio_mode(str gpio_id, OpenThermGatewayHub gw_hub, str mode)
Definition: select.py:110