Home Assistant Unofficial Reference 2024.12.1
switch.py
Go to the documentation of this file.
1 """Switch platform for Hyperion."""
2 
3 from __future__ import annotations
4 
5 import functools
6 from typing import Any
7 
8 from hyperion import client
9 from hyperion.const import (
10  KEY_COMPONENT,
11  KEY_COMPONENTID_ALL,
12  KEY_COMPONENTID_BLACKBORDER,
13  KEY_COMPONENTID_BOBLIGHTSERVER,
14  KEY_COMPONENTID_FORWARDER,
15  KEY_COMPONENTID_GRABBER,
16  KEY_COMPONENTID_LEDDEVICE,
17  KEY_COMPONENTID_SMOOTHING,
18  KEY_COMPONENTID_TO_NAME,
19  KEY_COMPONENTID_V4L,
20  KEY_COMPONENTS,
21  KEY_COMPONENTSTATE,
22  KEY_ENABLED,
23  KEY_NAME,
24  KEY_STATE,
25  KEY_UPDATE,
26 )
27 
28 from homeassistant.components.switch import SwitchEntity
29 from homeassistant.config_entries import ConfigEntry
30 from homeassistant.const import EntityCategory
31 from homeassistant.core import HomeAssistant, callback
32 from homeassistant.helpers.device_registry import DeviceInfo
34  async_dispatcher_connect,
35  async_dispatcher_send,
36 )
37 from homeassistant.helpers.entity_platform import AddEntitiesCallback
38 from homeassistant.util import slugify
39 
40 from . import (
41  get_hyperion_device_id,
42  get_hyperion_unique_id,
43  listen_for_instance_updates,
44 )
45 from .const import (
46  CONF_INSTANCE_CLIENTS,
47  DOMAIN,
48  HYPERION_MANUFACTURER_NAME,
49  HYPERION_MODEL_NAME,
50  SIGNAL_ENTITY_REMOVE,
51  TYPE_HYPERION_COMPONENT_SWITCH_BASE,
52 )
53 
54 COMPONENT_SWITCHES = [
55  KEY_COMPONENTID_ALL,
56  KEY_COMPONENTID_SMOOTHING,
57  KEY_COMPONENTID_BLACKBORDER,
58  KEY_COMPONENTID_FORWARDER,
59  KEY_COMPONENTID_BOBLIGHTSERVER,
60  KEY_COMPONENTID_GRABBER,
61  KEY_COMPONENTID_LEDDEVICE,
62  KEY_COMPONENTID_V4L,
63 ]
64 
65 
66 def _component_to_unique_id(server_id: str, component: str, instance_num: int) -> str:
67  """Convert a component to a unique_id."""
69  server_id,
70  instance_num,
71  slugify(
72  f"{TYPE_HYPERION_COMPONENT_SWITCH_BASE} {KEY_COMPONENTID_TO_NAME[component]}"
73  ),
74  )
75 
76 
77 def _component_to_translation_key(component: str) -> str:
78  return {
79  KEY_COMPONENTID_ALL: "all",
80  KEY_COMPONENTID_SMOOTHING: "smoothing",
81  KEY_COMPONENTID_BLACKBORDER: "blackbar_detection",
82  KEY_COMPONENTID_FORWARDER: "forwarder",
83  KEY_COMPONENTID_BOBLIGHTSERVER: "boblight_server",
84  KEY_COMPONENTID_GRABBER: "platform_capture",
85  KEY_COMPONENTID_LEDDEVICE: "led_device",
86  KEY_COMPONENTID_V4L: "usb_capture",
87  }[component]
88 
89 
91  hass: HomeAssistant,
92  config_entry: ConfigEntry,
93  async_add_entities: AddEntitiesCallback,
94 ) -> None:
95  """Set up a Hyperion platform from config entry."""
96  entry_data = hass.data[DOMAIN][config_entry.entry_id]
97  server_id = config_entry.unique_id
98 
99  @callback
100  def instance_add(instance_num: int, instance_name: str) -> None:
101  """Add entities for a new Hyperion instance."""
102  assert server_id
105  server_id,
106  instance_num,
107  instance_name,
108  component,
109  entry_data[CONF_INSTANCE_CLIENTS][instance_num],
110  )
111  for component in COMPONENT_SWITCHES
112  )
113 
114  @callback
115  def instance_remove(instance_num: int) -> None:
116  """Remove entities for an old Hyperion instance."""
117  assert server_id
118  for component in COMPONENT_SWITCHES:
120  hass,
121  SIGNAL_ENTITY_REMOVE.format(
122  _component_to_unique_id(server_id, component, instance_num),
123  ),
124  )
125 
126  listen_for_instance_updates(hass, config_entry, instance_add, instance_remove)
127 
128 
130  """ComponentBinarySwitch switch class."""
131 
132  _attr_entity_category = EntityCategory.CONFIG
133  _attr_should_poll = False
134  _attr_has_entity_name = True
135  # These component controls are for advanced users and are disabled by default.
136  _attr_entity_registry_enabled_default = False
137 
138  def __init__(
139  self,
140  server_id: str,
141  instance_num: int,
142  instance_name: str,
143  component_name: str,
144  hyperion_client: client.HyperionClient,
145  ) -> None:
146  """Initialize the switch."""
148  server_id, component_name, instance_num
149  )
150  self._device_id_device_id = get_hyperion_device_id(server_id, instance_num)
151  self._attr_translation_key_attr_translation_key = _component_to_translation_key(component_name)
152  self._instance_name_instance_name = instance_name
153  self._component_name_component_name = component_name
154  self._client_client = hyperion_client
155  self._client_callbacks_client_callbacks = {
156  f"{KEY_COMPONENTS}-{KEY_UPDATE}": self._update_components_update_components
157  }
158  self._attr_device_info_attr_device_info = DeviceInfo(
159  identifiers={(DOMAIN, self._device_id_device_id)},
160  manufacturer=HYPERION_MANUFACTURER_NAME,
161  model=HYPERION_MODEL_NAME,
162  name=self._instance_name_instance_name,
163  configuration_url=self._client_client.remote_url,
164  )
165 
166  @property
167  def is_on(self) -> bool:
168  """Return true if the switch is on."""
169  for component in self._client_client.components or []:
170  if component[KEY_NAME] == self._component_name_component_name:
171  return bool(component.setdefault(KEY_ENABLED, False))
172  return False
173 
174  @property
175  def available(self) -> bool:
176  """Return server availability."""
177  return bool(self._client_client.has_loaded_state)
178 
179  async def _async_send_set_component(self, value: bool) -> None:
180  """Send a component control request."""
181  await self._client_client.async_send_set_component(
182  **{
183  KEY_COMPONENTSTATE: {
184  KEY_COMPONENT: self._component_name_component_name,
185  KEY_STATE: value,
186  }
187  }
188  )
189 
190  async def async_turn_on(self, **kwargs: Any) -> None:
191  """Turn on the switch."""
192  await self._async_send_set_component_async_send_set_component(True)
193 
194  async def async_turn_off(self, **kwargs: Any) -> None:
195  """Turn off the switch."""
196  await self._async_send_set_component_async_send_set_component(False)
197 
198  @callback
199  def _update_components(self, _: dict[str, Any] | None = None) -> None:
200  """Update Hyperion components."""
201  self.async_write_ha_stateasync_write_ha_state()
202 
203  async def async_added_to_hass(self) -> None:
204  """Register callbacks when entity added to hass."""
205  self.async_on_removeasync_on_remove(
207  self.hasshass,
208  SIGNAL_ENTITY_REMOVE.format(self._attr_unique_id_attr_unique_id),
209  functools.partial(self.async_removeasync_remove, force_remove=True),
210  )
211  )
212 
213  self._client_client.add_callbacks(self._client_callbacks_client_callbacks)
214 
215  async def async_will_remove_from_hass(self) -> None:
216  """Cleanup prior to hass removal."""
217  self._client_client.remove_callbacks(self._client_callbacks_client_callbacks)
None __init__(self, str server_id, int instance_num, str instance_name, str component_name, client.HyperionClient hyperion_client)
Definition: switch.py:145
None _update_components(self, dict[str, Any]|None _=None)
Definition: switch.py:199
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
None async_remove(self, *bool force_remove=False)
Definition: entity.py:1387
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: switch.py:94
str _component_to_translation_key(str component)
Definition: switch.py:77
str _component_to_unique_id(str server_id, str component, int instance_num)
Definition: switch.py:66
str get_hyperion_device_id(str server_id, int instance)
Definition: __init__.py:71
str get_hyperion_unique_id(str server_id, int instance, str name)
Definition: __init__.py:66
None listen_for_instance_updates(HomeAssistant hass, ConfigEntry config_entry, Callable add_func, Callable remove_func)
Definition: __init__.py:113
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
Definition: dispatcher.py:193