Home Assistant Unofficial Reference 2024.12.1
entity.py
Go to the documentation of this file.
1 """Base entity for Sensibo integration."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from collections.abc import Callable, Coroutine
7 from typing import TYPE_CHECKING, Any, Concatenate
8 
9 from pysensibo.model import MotionSensor, SensiboDevice
10 
11 from homeassistant.exceptions import HomeAssistantError
12 from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
13 from homeassistant.helpers.update_coordinator import CoordinatorEntity
14 
15 from .const import DOMAIN, LOGGER, SENSIBO_ERRORS, TIMEOUT
16 from .coordinator import SensiboDataUpdateCoordinator
17 
18 
19 def async_handle_api_call[_T: SensiboDeviceBaseEntity, **_P](
20  function: Callable[Concatenate[_T, _P], Coroutine[Any, Any, Any]],
21 ) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, Any]]:
22  """Decorate api calls."""
23 
24  async def wrap_api_call(entity: _T, *args: _P.args, **kwargs: _P.kwargs) -> None:
25  """Wrap services for api calls."""
26  res: bool = False
27  if TYPE_CHECKING:
28  assert isinstance(entity.name, str)
29  try:
30  async with asyncio.timeout(TIMEOUT):
31  res = await function(entity, *args, **kwargs)
32  except SENSIBO_ERRORS as err:
33  raise HomeAssistantError(
34  translation_domain=DOMAIN,
35  translation_key="service_raised",
36  translation_placeholders={"error": str(err), "name": entity.name},
37  ) from err
38 
39  LOGGER.debug("Result %s for entity %s with arguments %s", res, entity, kwargs)
40  if res is not True:
41  raise HomeAssistantError(
42  translation_domain=DOMAIN,
43  translation_key="service_result_not_true",
44  translation_placeholders={"name": entity.name},
45  )
46  if (
47  isinstance(key := kwargs.get("key"), str)
48  and (value := kwargs.get("value")) is not None
49  ):
50  setattr(entity.device_data, key, value)
51  LOGGER.debug("Debug check key %s is now %s", key, value)
52  entity.async_write_ha_state()
53  await entity.coordinator.async_request_refresh()
54 
55  return wrap_api_call
56 
57 
58 class SensiboBaseEntity(CoordinatorEntity[SensiboDataUpdateCoordinator]):
59  """Representation of a Sensibo Base Entity."""
60 
61  _attr_has_entity_name = True
62 
63  def __init__(
64  self,
65  coordinator: SensiboDataUpdateCoordinator,
66  device_id: str,
67  ) -> None:
68  """Initiate Sensibo Number."""
69  super().__init__(coordinator)
70  self._device_id_device_id = device_id
71  self._client_client = coordinator.client
72 
73  @property
74  def device_data(self) -> SensiboDevice:
75  """Return data for device."""
76  return self.coordinator.data.parsed[self._device_id_device_id]
77 
78 
80  """Representation of a Sensibo Device."""
81 
82  def __init__(
83  self,
84  coordinator: SensiboDataUpdateCoordinator,
85  device_id: str,
86  ) -> None:
87  """Initiate Sensibo Device."""
88  super().__init__(coordinator, device_id)
89  self._attr_device_info_attr_device_info = DeviceInfo(
90  identifiers={(DOMAIN, self.device_datadevice_data.id)},
91  name=self.device_datadevice_data.name,
92  connections={(CONNECTION_NETWORK_MAC, self.device_datadevice_data.mac)},
93  manufacturer="Sensibo",
94  configuration_url="https://home.sensibo.com/",
95  model=self.device_datadevice_data.model,
96  sw_version=self.device_datadevice_data.fw_ver,
97  hw_version=self.device_datadevice_data.fw_type,
98  suggested_area=self.device_datadevice_data.name,
99  serial_number=self.device_datadevice_data.serial,
100  )
101 
102 
104  """Representation of a Sensibo Motion Entity."""
105 
106  def __init__(
107  self,
108  coordinator: SensiboDataUpdateCoordinator,
109  device_id: str,
110  sensor_id: str,
111  sensor_data: MotionSensor,
112  ) -> None:
113  """Initiate Sensibo Number."""
114  super().__init__(coordinator, device_id)
115  self._sensor_id_sensor_id = sensor_id
116  self._attr_device_info_attr_device_info = DeviceInfo(
117  identifiers={(DOMAIN, sensor_id)},
118  name=f"{self.device_data.name} Motion Sensor",
119  via_device=(DOMAIN, device_id),
120  manufacturer="Sensibo",
121  configuration_url="https://home.sensibo.com/",
122  model=sensor_data.model,
123  sw_version=sensor_data.fw_ver,
124  hw_version=sensor_data.fw_type,
125  )
126 
127  @property
128  def sensor_data(self) -> MotionSensor | None:
129  """Return data for Motion Sensor."""
130  if TYPE_CHECKING:
131  assert self.device_datadevice_data.motion_sensors
132  return self.device_datadevice_data.motion_sensors[self._sensor_id_sensor_id]
None __init__(self, SensiboDataUpdateCoordinator coordinator, str device_id)
Definition: entity.py:67
None __init__(self, SensiboDataUpdateCoordinator coordinator, str device_id)
Definition: entity.py:86
None __init__(self, SensiboDataUpdateCoordinator coordinator, str device_id, str sensor_id, MotionSensor sensor_data)
Definition: entity.py:112