Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Support for Roku selects."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Awaitable, Callable
6 from dataclasses import dataclass
7 
8 from rokuecp import Roku
9 from rokuecp.models import Device as RokuDevice
10 
11 from homeassistant.components.select import SelectEntity, SelectEntityDescription
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.core import HomeAssistant
14 from homeassistant.helpers.entity_platform import AddEntitiesCallback
15 
16 from .const import DOMAIN
17 from .coordinator import RokuDataUpdateCoordinator
18 from .entity import RokuEntity
19 from .helpers import format_channel_name, roku_exception_handler
20 
21 
22 def _get_application_name(device: RokuDevice) -> str | None:
23  if device.app is None or device.app.name is None:
24  return None
25 
26  if device.app.name == "Roku":
27  return "Home"
28 
29  return device.app.name
30 
31 
32 def _get_applications(device: RokuDevice) -> list[str]:
33  return ["Home", *sorted(app.name for app in device.apps if app.name is not None)]
34 
35 
36 def _get_channel_name(device: RokuDevice) -> str | None:
37  if device.channel is None:
38  return None
39 
40  return format_channel_name(device.channel.number, device.channel.name)
41 
42 
43 def _get_channels(device: RokuDevice) -> list[str]:
44  return sorted(
45  format_channel_name(channel.number, channel.name) for channel in device.channels
46  )
47 
48 
49 async def _launch_application(device: RokuDevice, roku: Roku, value: str) -> None:
50  if value == "Home":
51  await roku.remote("home")
52 
53  appl = next(
54  (app for app in device.apps if value == app.name),
55  None,
56  )
57 
58  if appl is not None and appl.app_id is not None:
59  await roku.launch(appl.app_id)
60 
61 
62 async def _tune_channel(device: RokuDevice, roku: Roku, value: str) -> None:
63  _channel = next(
64  (
65  channel
66  for channel in device.channels
67  if (
68  channel.name is not None
69  and value == format_channel_name(channel.number, channel.name)
70  )
71  or value == channel.number
72  ),
73  None,
74  )
75 
76  if _channel is not None:
77  await roku.tune(_channel.number)
78 
79 
80 @dataclass(frozen=True, kw_only=True)
82  """Describes Roku select entity."""
83 
84  options_fn: Callable[[RokuDevice], list[str]]
85  value_fn: Callable[[RokuDevice], str | None]
86  set_fn: Callable[[RokuDevice, Roku, str], Awaitable[None]]
87 
88 
89 ENTITIES: tuple[RokuSelectEntityDescription, ...] = (
91  key="application",
92  translation_key="application",
93  set_fn=_launch_application,
94  value_fn=_get_application_name,
95  options_fn=_get_applications,
96  entity_registry_enabled_default=False,
97  ),
98 )
99 
101  key="channel",
102  translation_key="channel",
103  set_fn=_tune_channel,
104  value_fn=_get_channel_name,
105  options_fn=_get_channels,
106 )
107 
108 
110  hass: HomeAssistant,
111  entry: ConfigEntry,
112  async_add_entities: AddEntitiesCallback,
113 ) -> None:
114  """Set up Roku select based on a config entry."""
115  coordinator: RokuDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
116  device: RokuDevice = coordinator.data
117 
118  entities: list[RokuSelectEntity] = [
120  coordinator=coordinator,
121  description=description,
122  )
123  for description in ENTITIES
124  ]
125 
126  if len(device.channels) > 0:
127  entities.append(
129  coordinator=coordinator,
130  description=CHANNEL_ENTITY,
131  )
132  )
133 
134  async_add_entities(entities)
135 
136 
138  """Defines a Roku select entity."""
139 
140  entity_description: RokuSelectEntityDescription
141 
142  @property
143  def current_option(self) -> str | None:
144  """Return the current value."""
145  return self.entity_descriptionentity_description.value_fn(self.coordinator.data)
146 
147  @property
148  def options(self) -> list[str]:
149  """Return a set of selectable options."""
150  return self.entity_descriptionentity_description.options_fn(self.coordinator.data)
151 
152  @roku_exception_handler()
153  async def async_select_option(self, option: str) -> None:
154  """Set the option."""
155  await self.entity_descriptionentity_description.set_fn(
156  self.coordinator.data,
157  self.coordinator.roku,
158  option,
159  )
160  await self.coordinator.async_request_refresh()
str format_channel_name(str channel_number, str|None channel_name=None)
Definition: helpers.py:21
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: select.py:113
list[str] _get_applications(RokuDevice device)
Definition: select.py:32
None _launch_application(RokuDevice device, Roku roku, str value)
Definition: select.py:49
list[str] _get_channels(RokuDevice device)
Definition: select.py:43
str|None _get_application_name(RokuDevice device)
Definition: select.py:22
None _tune_channel(RokuDevice device, Roku roku, str value)
Definition: select.py:62
str|None _get_channel_name(RokuDevice device)
Definition: select.py:36