Home Assistant Unofficial Reference 2024.12.1
entity.py
Go to the documentation of this file.
1 """Support for RFXtrx devices."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from typing import cast
7 
8 import RFXtrx as rfxtrxmod
9 
10 from homeassistant.core import callback
11 from homeassistant.helpers.device_registry import DeviceInfo
12 from homeassistant.helpers.dispatcher import async_dispatcher_connect
13 from homeassistant.helpers.restore_state import RestoreEntity
14 
15 from . import DeviceTuple
16 from .const import ATTR_EVENT, COMMAND_GROUP_LIST, DATA_RFXOBJECT, DOMAIN, SIGNAL_EVENT
17 
18 
20  device_tuple: DeviceTuple,
21 ) -> set[tuple[str, str]]:
22  """Calculate the device identifier from a device tuple."""
23  # work around legacy identifier, being a multi tuple value
24  return {(DOMAIN, *device_tuple)} # type: ignore[arg-type]
25 
26 
28  """Represents a Rfxtrx device.
29 
30  Contains the common logic for Rfxtrx lights and switches.
31  """
32 
33  _attr_assumed_state = True
34  _attr_has_entity_name = True
35  _attr_should_poll = False
36  _device: rfxtrxmod.RFXtrxDevice
37  _event: rfxtrxmod.RFXtrxEvent | None
38 
39  def __init__(
40  self,
41  device: rfxtrxmod.RFXtrxDevice,
42  device_id: DeviceTuple,
43  event: rfxtrxmod.RFXtrxEvent | None = None,
44  ) -> None:
45  """Initialize the device."""
46  self._attr_device_info_attr_device_info = DeviceInfo(
47  identifiers=_get_identifiers_from_device_tuple(device_id),
48  model=device.type_string,
49  name=f"{device.type_string} {device.id_string}",
50  )
51  self._attr_unique_id_attr_unique_id = "_".join(x for x in device_id)
52  self._device_device = device
53  self._event_event = event
54  self._device_id_device_id = device_id
55  # If id_string is 213c7f2:1, the group_id is 213c7f2, and the device will respond to
56  # group events regardless of their group indices.
57  (self._group_id, _, _) = cast(str, device.id_string).partition(":")
58 
59  async def async_added_to_hass(self) -> None:
60  """Restore RFXtrx device state (ON/OFF)."""
61  if self._event_event:
62  self._apply_event_apply_event(self._event_event)
63 
64  self.async_on_removeasync_on_remove(
65  async_dispatcher_connect(self.hasshass, SIGNAL_EVENT, self._handle_event_handle_event)
66  )
67 
68  @property
69  def extra_state_attributes(self) -> dict[str, str] | None:
70  """Return the device state attributes."""
71  if not self._event_event:
72  return None
73  return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event_event.data)}
74 
76  self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
77  ) -> bool:
78  """Check if event applies to me."""
79  if isinstance(event, rfxtrxmod.ControlEvent):
80  if (
81  "Command" in event.values
82  and event.values["Command"] in COMMAND_GROUP_LIST
83  ):
84  device: rfxtrxmod.RFXtrxDevice = event.device
85  (group_id, _, _) = cast(str, device.id_string).partition(":")
86  return group_id == self._group_id
87 
88  # Otherwise, the event only applies to the matching device.
89  return device_id == self._device_id_device_id
90 
91  def _apply_event(self, event: rfxtrxmod.RFXtrxEvent) -> None:
92  """Apply a received event."""
93  self._event_event = event
94 
95  @callback
97  self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
98  ) -> None:
99  """Handle a reception of data, overridden by other classes."""
100 
101 
103  """Represents a Rfxtrx device.
104 
105  Contains the common logic for Rfxtrx lights and switches.
106  """
107 
108  _attr_name = None
109 
110  def __init__(
111  self,
112  device: rfxtrxmod.RFXtrxDevice,
113  device_id: DeviceTuple,
114  event: rfxtrxmod.RFXtrxEvent | None = None,
115  ) -> None:
116  """Initialzie a switch or light device."""
117  super().__init__(device, device_id, event=event)
118 
119  async def _async_send[*_Ts](
120  self, fun: Callable[[rfxtrxmod.PySerialTransport, *_Ts], None], *args: *_Ts
121  ) -> None:
122  rfx_object: rfxtrxmod.Connect = self.hasshass.data[DOMAIN][DATA_RFXOBJECT]
123  await self.hasshass.async_add_executor_job(fun, rfx_object.transport, *args)
None __init__(self, rfxtrxmod.RFXtrxDevice device, DeviceTuple device_id, rfxtrxmod.RFXtrxEvent|None event=None)
Definition: entity.py:115
dict[str, str]|None extra_state_attributes(self)
Definition: entity.py:69
None __init__(self, rfxtrxmod.RFXtrxDevice device, DeviceTuple device_id, rfxtrxmod.RFXtrxEvent|None event=None)
Definition: entity.py:44
None _apply_event(self, rfxtrxmod.RFXtrxEvent event)
Definition: entity.py:91
None _handle_event(self, rfxtrxmod.RFXtrxEvent event, DeviceTuple device_id)
Definition: entity.py:98
bool _event_applies(self, rfxtrxmod.RFXtrxEvent event, DeviceTuple device_id)
Definition: entity.py:77
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
set[tuple[str, str]] _get_identifiers_from_device_tuple(DeviceTuple device_tuple)
Definition: entity.py:21
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103