Home Assistant Unofficial Reference 2024.12.1
entity.py
Go to the documentation of this file.
1 """Base class for Netatmo entities."""
2 
3 from __future__ import annotations
4 
5 from abc import abstractmethod
6 from typing import Any, cast
7 
8 from pyatmo import DeviceType, Home, Module, Room
9 from pyatmo.modules.base_class import NetatmoBase, Place
10 from pyatmo.modules.device_types import DEVICE_DESCRIPTION_MAP
11 
12 from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE
13 from homeassistant.core import callback
14 from homeassistant.helpers import device_registry as dr
15 from homeassistant.helpers.device_registry import DeviceInfo
16 from homeassistant.helpers.entity import Entity
17 
18 from .const import (
19  CONF_URL_ENERGY,
20  CONF_URL_WEATHER,
21  DATA_DEVICE_IDS,
22  DEFAULT_ATTRIBUTION,
23  DOMAIN,
24  SIGNAL_NAME,
25 )
26 from .data_handler import PUBLIC, NetatmoDataHandler, NetatmoDevice, NetatmoRoom
27 
28 
30  """Netatmo entity base class."""
31 
32  _attr_attribution = DEFAULT_ATTRIBUTION
33  _attr_has_entity_name = True
34 
35  def __init__(self, data_handler: NetatmoDataHandler) -> None:
36  """Set up Netatmo entity base."""
37  self.data_handlerdata_handler = data_handler
38  self._publishers: list[dict[str, Any]] = []
39  self._attr_extra_state_attributes_attr_extra_state_attributes = {}
40 
41  async def async_added_to_hass(self) -> None:
42  """Entity created."""
43  for publisher in self._publishers:
44  signal_name = publisher[SIGNAL_NAME]
45 
46  if "home_id" in publisher:
47  await self.data_handlerdata_handler.subscribe(
48  publisher["name"],
49  signal_name,
50  self.async_update_callbackasync_update_callback,
51  home_id=publisher["home_id"],
52  )
53 
54  elif publisher["name"] == PUBLIC:
55  await self.data_handlerdata_handler.subscribe(
56  publisher["name"],
57  signal_name,
58  self.async_update_callbackasync_update_callback,
59  lat_ne=publisher["lat_ne"],
60  lon_ne=publisher["lon_ne"],
61  lat_sw=publisher["lat_sw"],
62  lon_sw=publisher["lon_sw"],
63  )
64 
65  else:
66  await self.data_handlerdata_handler.subscribe(
67  publisher["name"], signal_name, self.async_update_callbackasync_update_callback
68  )
69 
70  if any(
71  sub is None
72  for sub in self.data_handlerdata_handler.publisher[signal_name].subscriptions
73  ):
74  await self.data_handlerdata_handler.unsubscribe(signal_name, None)
75 
76  self.async_update_callbackasync_update_callback()
77 
78  async def async_will_remove_from_hass(self) -> None:
79  """Run when entity will be removed from hass."""
80  await super().async_will_remove_from_hass()
81 
82  for publisher in self._publishers:
83  await self.data_handlerdata_handler.unsubscribe(
84  publisher[SIGNAL_NAME], self.async_update_callbackasync_update_callback
85  )
86 
87  @callback
88  def async_update_callback(self) -> None:
89  """Update the entity's state."""
90  raise NotImplementedError
91 
92 
94  """Netatmo entity base class."""
95 
96  def __init__(self, data_handler: NetatmoDataHandler, device: NetatmoBase) -> None:
97  """Set up Netatmo entity base."""
98  super().__init__(data_handler)
99  self.devicedevice = device
100 
101  @property
102  @abstractmethod
103  def device_type(self) -> DeviceType:
104  """Return the device type."""
105 
106  @property
107  def device_description(self) -> tuple[str, str]:
108  """Return the model of this device."""
109  return DEVICE_DESCRIPTION_MAP[self.device_typedevice_type]
110 
111  @property
112  def home(self) -> Home:
113  """Return the home this room belongs to."""
114  return self.devicedevice.home
115 
116 
118  """Netatmo room entity base class."""
119 
120  device: Room
121 
122  def __init__(self, room: NetatmoRoom) -> None:
123  """Set up a Netatmo room entity."""
124  super().__init__(room.data_handler, room.room)
125  self._attr_device_info_attr_device_info = DeviceInfo(
126  identifiers={(DOMAIN, room.room.entity_id)},
127  name=room.room.name,
128  manufacturer=self.device_descriptiondevice_description[0],
129  model=self.device_descriptiondevice_description[1],
130  configuration_url=CONF_URL_ENERGY,
131  suggested_area=room.room.name,
132  )
133 
134  async def async_added_to_hass(self) -> None:
135  """Entity created."""
136  await super().async_added_to_hass()
137  registry = dr.async_get(self.hasshass)
138  if device := registry.async_get_device(
139  identifiers={(DOMAIN, self.devicedevice.entity_id)}
140  ):
141  self.hasshass.data[DOMAIN][DATA_DEVICE_IDS][self.devicedevice.entity_id] = device.id
142 
143  @property
144  def device_type(self) -> DeviceType:
145  """Return the device type."""
146  assert self.devicedevice.climate_type
147  return self.devicedevice.climate_type
148 
149 
151  """Netatmo module entity base class."""
152 
153  device: Module
154  _attr_configuration_url: str
155 
156  def __init__(self, device: NetatmoDevice) -> None:
157  """Set up a Netatmo module entity."""
158  super().__init__(device.data_handler, device.device)
159  self._attr_device_info_attr_device_info = DeviceInfo(
160  identifiers={(DOMAIN, device.device.entity_id)},
161  name=device.device.name,
162  manufacturer=self.device_descriptiondevice_description[0],
163  model=self.device_descriptiondevice_description[1],
164  configuration_url=self._attr_configuration_url,
165  )
166 
167  @property
168  def device_type(self) -> DeviceType:
169  """Return the device type."""
170  return self.devicedevice.device_type
171 
172 
174  """Netatmo weather module entity base class."""
175 
176  _attr_configuration_url = CONF_URL_WEATHER
177 
178  def __init__(self, device: NetatmoDevice) -> None:
179  """Set up a Netatmo weather module entity."""
180  super().__init__(device)
181  category = getattr(self.devicedevice.device_category, "name")
182  self._publishers.extend(
183  [
184  {
185  "name": category,
186  SIGNAL_NAME: category,
187  },
188  ]
189  )
190 
191  if hasattr(self.devicedevice, "place"):
192  place = cast(Place, getattr(self.devicedevice, "place"))
193  if hasattr(place, "location") and place.location is not None:
194  self._attr_extra_state_attributes_attr_extra_state_attributes.update(
195  {
196  ATTR_LATITUDE: place.location.latitude,
197  ATTR_LONGITUDE: place.location.longitude,
198  }
199  )
200 
201  @property
202  def device_type(self) -> DeviceType:
203  """Return the Netatmo device type."""
204  if "." not in self.devicedevice.device_type:
205  return super().device_type
206  return DeviceType(self.devicedevice.device_type.partition(".")[2])
None __init__(self, NetatmoDataHandler data_handler)
Definition: entity.py:35
None __init__(self, NetatmoDataHandler data_handler, NetatmoBase device)
Definition: entity.py:96
Callable[[], None] subscribe(HomeAssistant hass, str topic, MessageCallbackType msg_callback, int qos=DEFAULT_QOS, str encoding="utf-8")
Definition: client.py:247