Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Sensor 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_COMPONENTID,
11  KEY_ORIGIN,
12  KEY_OWNER,
13  KEY_PRIORITIES,
14  KEY_PRIORITY,
15  KEY_RGB,
16  KEY_UPDATE,
17  KEY_VALUE,
18  KEY_VISIBLE,
19 )
20 
21 from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
22 from homeassistant.config_entries import ConfigEntry
23 from homeassistant.core import HomeAssistant, callback
24 from homeassistant.helpers.device_registry import DeviceInfo
26  async_dispatcher_connect,
27  async_dispatcher_send,
28 )
29 from homeassistant.helpers.entity_platform import AddEntitiesCallback
30 
31 from . import (
32  get_hyperion_device_id,
33  get_hyperion_unique_id,
34  listen_for_instance_updates,
35 )
36 from .const import (
37  CONF_INSTANCE_CLIENTS,
38  DOMAIN,
39  HYPERION_MANUFACTURER_NAME,
40  HYPERION_MODEL_NAME,
41  SIGNAL_ENTITY_REMOVE,
42  TYPE_HYPERION_SENSOR_BASE,
43  TYPE_HYPERION_SENSOR_VISIBLE_PRIORITY,
44 )
45 
46 SENSORS = [TYPE_HYPERION_SENSOR_VISIBLE_PRIORITY]
47 PRIORITY_SENSOR_DESCRIPTION = SensorEntityDescription(
48  key="visible_priority",
49  translation_key="visible_priority",
50  icon="mdi:lava-lamp",
51 )
52 
53 
54 def _sensor_unique_id(server_id: str, instance_num: int, suffix: str) -> str:
55  """Calculate a sensor's unique_id."""
57  server_id,
58  instance_num,
59  f"{TYPE_HYPERION_SENSOR_BASE}_{suffix}",
60  )
61 
62 
64  hass: HomeAssistant,
65  config_entry: ConfigEntry,
66  async_add_entities: AddEntitiesCallback,
67 ) -> None:
68  """Set up a Hyperion platform from config entry."""
69  entry_data = hass.data[DOMAIN][config_entry.entry_id]
70  server_id = config_entry.unique_id
71 
72  @callback
73  def instance_add(instance_num: int, instance_name: str) -> None:
74  """Add entities for a new Hyperion instance."""
75  assert server_id
76  sensors = [
78  server_id,
79  instance_num,
80  instance_name,
81  entry_data[CONF_INSTANCE_CLIENTS][instance_num],
82  PRIORITY_SENSOR_DESCRIPTION,
83  )
84  ]
85 
86  async_add_entities(sensors)
87 
88  @callback
89  def instance_remove(instance_num: int) -> None:
90  """Remove entities for an old Hyperion instance."""
91  assert server_id
92 
93  for sensor in SENSORS:
95  hass,
96  SIGNAL_ENTITY_REMOVE.format(
97  _sensor_unique_id(server_id, instance_num, sensor),
98  ),
99  )
100 
101  listen_for_instance_updates(hass, config_entry, instance_add, instance_remove)
102 
103 
105  """Sensor class."""
106 
107  _attr_has_entity_name = True
108  _attr_should_poll = False
109 
110  def __init__(
111  self,
112  server_id: str,
113  instance_num: int,
114  instance_name: str,
115  hyperion_client: client.HyperionClient,
116  entity_description: SensorEntityDescription,
117  ) -> None:
118  """Initialize the sensor."""
119  self.entity_descriptionentity_description = entity_description
120  self._client_client = hyperion_client
121  self._attr_native_value_attr_native_value = None
122  self._client_callbacks: dict[str, Any] = {}
123 
124  device_id = get_hyperion_device_id(server_id, instance_num)
125 
126  self._attr_device_info_attr_device_info = DeviceInfo(
127  identifiers={(DOMAIN, device_id)},
128  manufacturer=HYPERION_MANUFACTURER_NAME,
129  model=HYPERION_MODEL_NAME,
130  name=instance_name,
131  configuration_url=self._client_client.remote_url,
132  )
133 
134  @property
135  def available(self) -> bool:
136  """Return server availability."""
137  return bool(self._client_client.has_loaded_state)
138 
139  async def async_added_to_hass(self) -> None:
140  """Register callbacks when entity added to hass."""
141  self.async_on_removeasync_on_remove(
143  self.hasshass,
144  SIGNAL_ENTITY_REMOVE.format(self._attr_unique_id),
145  functools.partial(self.async_removeasync_remove, force_remove=True),
146  )
147  )
148 
149  self._client_client.add_callbacks(self._client_callbacks)
150 
151  async def async_will_remove_from_hass(self) -> None:
152  """Cleanup prior to hass removal."""
153  self._client_client.remove_callbacks(self._client_callbacks)
154 
155 
157  """Class that displays the visible priority of a Hyperion instance."""
158 
159  def __init__(
160  self,
161  server_id: str,
162  instance_num: int,
163  instance_name: str,
164  hyperion_client: client.HyperionClient,
165  entity_description: SensorEntityDescription,
166  ) -> None:
167  """Initialize the sensor."""
168 
169  super().__init__(
170  server_id, instance_num, instance_name, hyperion_client, entity_description
171  )
172 
173  self._attr_unique_id_attr_unique_id = _sensor_unique_id(
174  server_id, instance_num, TYPE_HYPERION_SENSOR_VISIBLE_PRIORITY
175  )
176 
177  self._client_callbacks_client_callbacks = {
178  f"{KEY_PRIORITIES}-{KEY_UPDATE}": self._update_priorities_update_priorities
179  }
180 
181  @callback
182  def _update_priorities(self, _: dict[str, Any] | None = None) -> None:
183  """Update Hyperion priorities."""
184  state_value = None
185  attrs = {}
186 
187  for priority in self._client_client.priorities or []:
188  if not (KEY_VISIBLE in priority and priority[KEY_VISIBLE] is True):
189  continue
190 
191  if priority[KEY_COMPONENTID] == "COLOR":
192  state_value = priority[KEY_VALUE][KEY_RGB]
193  else:
194  state_value = priority.get(KEY_OWNER)
195 
196  attrs = {
197  "component_id": priority[KEY_COMPONENTID],
198  "origin": priority[KEY_ORIGIN],
199  "priority": priority[KEY_PRIORITY],
200  "owner": priority.get(KEY_OWNER),
201  }
202 
203  if priority[KEY_COMPONENTID] == "COLOR":
204  attrs["color"] = priority[KEY_VALUE]
205  else:
206  attrs["color"] = None
207 
208  self._attr_native_value_attr_native_value_attr_native_value = state_value
209  self._attr_extra_state_attributes_attr_extra_state_attributes = attrs
210 
211  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, str server_id, int instance_num, str instance_name, client.HyperionClient hyperion_client, SensorEntityDescription entity_description)
Definition: sensor.py:117
None _update_priorities(self, dict[str, Any]|None _=None)
Definition: sensor.py:182
None __init__(self, str server_id, int instance_num, str instance_name, client.HyperionClient hyperion_client, SensorEntityDescription entity_description)
Definition: sensor.py:166
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: sensor.py:67
str _sensor_unique_id(str server_id, int instance_num, str suffix)
Definition: sensor.py:54
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