mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Move rfxtrx base entity to separate module (#126521)
This commit is contained in:
parent
b7ba789370
commit
f11cdb4ab4
@ -25,21 +25,16 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import Event, HomeAssistant, ServiceCall, callback
|
from homeassistant.core import Event, HomeAssistant, ServiceCall, callback
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||||
from homeassistant.helpers.device_registry import (
|
from homeassistant.helpers.device_registry import EventDeviceRegistryUpdatedData
|
||||||
DeviceInfo,
|
|
||||||
EventDeviceRegistryUpdatedData,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers.dispatcher import (
|
from homeassistant.helpers.dispatcher import (
|
||||||
async_dispatcher_connect,
|
async_dispatcher_connect,
|
||||||
async_dispatcher_send,
|
async_dispatcher_send,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_EVENT,
|
ATTR_EVENT,
|
||||||
COMMAND_GROUP_LIST,
|
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DATA_BITS,
|
CONF_DATA_BITS,
|
||||||
CONF_PROTOCOLS,
|
CONF_PROTOCOLS,
|
||||||
@ -48,11 +43,11 @@ from .const import (
|
|||||||
DOMAIN,
|
DOMAIN,
|
||||||
EVENT_RFXTRX_EVENT,
|
EVENT_RFXTRX_EVENT,
|
||||||
SERVICE_SEND,
|
SERVICE_SEND,
|
||||||
|
SIGNAL_EVENT,
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_OFF_DELAY = 2.0
|
DEFAULT_OFF_DELAY = 2.0
|
||||||
|
|
||||||
SIGNAL_EVENT = f"{DOMAIN}_event"
|
|
||||||
CONNECT_TIMEOUT = 30.0
|
CONNECT_TIMEOUT = 30.0
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -461,14 +456,6 @@ def get_device_tuple_from_identifiers(
|
|||||||
return DeviceTuple(identifier2[1], identifier2[2], identifier2[3])
|
return DeviceTuple(identifier2[1], identifier2[2], identifier2[3])
|
||||||
|
|
||||||
|
|
||||||
def get_identifiers_from_device_tuple(
|
|
||||||
device_tuple: DeviceTuple,
|
|
||||||
) -> set[tuple[str, str]]:
|
|
||||||
"""Calculate the device identifier from a device tuple."""
|
|
||||||
# work around legacy identifier, being a multi tuple value
|
|
||||||
return {(DOMAIN, *device_tuple)} # type: ignore[arg-type]
|
|
||||||
|
|
||||||
|
|
||||||
async def async_remove_config_entry_device(
|
async def async_remove_config_entry_device(
|
||||||
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
|
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
|
||||||
) -> bool:
|
) -> bool:
|
||||||
@ -477,102 +464,3 @@ async def async_remove_config_entry_device(
|
|||||||
The actual cleanup is done in the device registry event
|
The actual cleanup is done in the device registry event
|
||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxEntity(RestoreEntity):
|
|
||||||
"""Represents a Rfxtrx device.
|
|
||||||
|
|
||||||
Contains the common logic for Rfxtrx lights and switches.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_attr_assumed_state = True
|
|
||||||
_attr_has_entity_name = True
|
|
||||||
_attr_should_poll = False
|
|
||||||
_device: rfxtrxmod.RFXtrxDevice
|
|
||||||
_event: rfxtrxmod.RFXtrxEvent | None
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
device: rfxtrxmod.RFXtrxDevice,
|
|
||||||
device_id: DeviceTuple,
|
|
||||||
event: rfxtrxmod.RFXtrxEvent | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize the device."""
|
|
||||||
self._attr_device_info = DeviceInfo(
|
|
||||||
identifiers=get_identifiers_from_device_tuple(device_id),
|
|
||||||
model=device.type_string,
|
|
||||||
name=f"{device.type_string} {device.id_string}",
|
|
||||||
)
|
|
||||||
self._attr_unique_id = "_".join(x for x in device_id)
|
|
||||||
self._device = device
|
|
||||||
self._event = event
|
|
||||||
self._device_id = device_id
|
|
||||||
# If id_string is 213c7f2:1, the group_id is 213c7f2, and the device will respond to
|
|
||||||
# group events regardless of their group indices.
|
|
||||||
(self._group_id, _, _) = cast(str, device.id_string).partition(":")
|
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
|
||||||
"""Restore RFXtrx device state (ON/OFF)."""
|
|
||||||
if self._event:
|
|
||||||
self._apply_event(self._event)
|
|
||||||
|
|
||||||
self.async_on_remove(
|
|
||||||
async_dispatcher_connect(self.hass, SIGNAL_EVENT, self._handle_event)
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def extra_state_attributes(self) -> dict[str, str] | None:
|
|
||||||
"""Return the device state attributes."""
|
|
||||||
if not self._event:
|
|
||||||
return None
|
|
||||||
return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event.data)}
|
|
||||||
|
|
||||||
def _event_applies(
|
|
||||||
self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
|
|
||||||
) -> bool:
|
|
||||||
"""Check if event applies to me."""
|
|
||||||
if isinstance(event, rfxtrxmod.ControlEvent):
|
|
||||||
if (
|
|
||||||
"Command" in event.values
|
|
||||||
and event.values["Command"] in COMMAND_GROUP_LIST
|
|
||||||
):
|
|
||||||
device: rfxtrxmod.RFXtrxDevice = event.device
|
|
||||||
(group_id, _, _) = cast(str, device.id_string).partition(":")
|
|
||||||
return group_id == self._group_id
|
|
||||||
|
|
||||||
# Otherwise, the event only applies to the matching device.
|
|
||||||
return device_id == self._device_id
|
|
||||||
|
|
||||||
def _apply_event(self, event: rfxtrxmod.RFXtrxEvent) -> None:
|
|
||||||
"""Apply a received event."""
|
|
||||||
self._event = event
|
|
||||||
|
|
||||||
@callback
|
|
||||||
def _handle_event(
|
|
||||||
self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
|
|
||||||
) -> None:
|
|
||||||
"""Handle a reception of data, overridden by other classes."""
|
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxCommandEntity(RfxtrxEntity):
|
|
||||||
"""Represents a Rfxtrx device.
|
|
||||||
|
|
||||||
Contains the common logic for Rfxtrx lights and switches.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_attr_name = None
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
device: rfxtrxmod.RFXtrxDevice,
|
|
||||||
device_id: DeviceTuple,
|
|
||||||
event: rfxtrxmod.RFXtrxEvent | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialzie a switch or light device."""
|
|
||||||
super().__init__(device, device_id, event=event)
|
|
||||||
|
|
||||||
async def _async_send[*_Ts](
|
|
||||||
self, fun: Callable[[rfxtrxmod.PySerialTransport, *_Ts], None], *args: *_Ts
|
|
||||||
) -> None:
|
|
||||||
rfx_object: rfxtrxmod.Connect = self.hass.data[DOMAIN][DATA_RFXOBJECT]
|
|
||||||
await self.hass.async_add_executor_job(fun, rfx_object.transport, *args)
|
|
||||||
|
@ -19,7 +19,7 @@ from homeassistant.helpers import event as evt
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DeviceTuple, RfxtrxEntity, async_setup_platform_entry, get_pt2262_cmd
|
from . import DeviceTuple, async_setup_platform_entry, get_pt2262_cmd
|
||||||
from .const import (
|
from .const import (
|
||||||
COMMAND_OFF_LIST,
|
COMMAND_OFF_LIST,
|
||||||
COMMAND_ON_LIST,
|
COMMAND_ON_LIST,
|
||||||
@ -27,6 +27,7 @@ from .const import (
|
|||||||
CONF_OFF_DELAY,
|
CONF_OFF_DELAY,
|
||||||
DEVICE_PACKET_TYPE_LIGHTING4,
|
DEVICE_PACKET_TYPE_LIGHTING4,
|
||||||
)
|
)
|
||||||
|
from .entity import RfxtrxEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -46,3 +46,5 @@ EVENT_RFXTRX_EVENT = "rfxtrx_event"
|
|||||||
DATA_RFXOBJECT = "rfxobject"
|
DATA_RFXOBJECT = "rfxobject"
|
||||||
|
|
||||||
DOMAIN = "rfxtrx"
|
DOMAIN = "rfxtrx"
|
||||||
|
|
||||||
|
SIGNAL_EVENT = f"{DOMAIN}_event"
|
||||||
|
@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DeviceTuple, RfxtrxCommandEntity, async_setup_platform_entry
|
from . import DeviceTuple, async_setup_platform_entry
|
||||||
from .const import (
|
from .const import (
|
||||||
COMMAND_OFF_LIST,
|
COMMAND_OFF_LIST,
|
||||||
COMMAND_ON_LIST,
|
COMMAND_ON_LIST,
|
||||||
@ -22,6 +22,7 @@ from .const import (
|
|||||||
CONST_VENETIAN_BLIND_MODE_EU,
|
CONST_VENETIAN_BLIND_MODE_EU,
|
||||||
CONST_VENETIAN_BLIND_MODE_US,
|
CONST_VENETIAN_BLIND_MODE_US,
|
||||||
)
|
)
|
||||||
|
from .entity import RfxtrxCommandEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
123
homeassistant/components/rfxtrx/entity.py
Normal file
123
homeassistant/components/rfxtrx/entity.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
"""Support for RFXtrx devices."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
import RFXtrx as rfxtrxmod
|
||||||
|
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
|
from . import DeviceTuple
|
||||||
|
from .const import ATTR_EVENT, COMMAND_GROUP_LIST, DATA_RFXOBJECT, DOMAIN, SIGNAL_EVENT
|
||||||
|
|
||||||
|
|
||||||
|
def _get_identifiers_from_device_tuple(
|
||||||
|
device_tuple: DeviceTuple,
|
||||||
|
) -> set[tuple[str, str]]:
|
||||||
|
"""Calculate the device identifier from a device tuple."""
|
||||||
|
# work around legacy identifier, being a multi tuple value
|
||||||
|
return {(DOMAIN, *device_tuple)} # type: ignore[arg-type]
|
||||||
|
|
||||||
|
|
||||||
|
class RfxtrxEntity(RestoreEntity):
|
||||||
|
"""Represents a Rfxtrx device.
|
||||||
|
|
||||||
|
Contains the common logic for Rfxtrx lights and switches.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_attr_assumed_state = True
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
_attr_should_poll = False
|
||||||
|
_device: rfxtrxmod.RFXtrxDevice
|
||||||
|
_event: rfxtrxmod.RFXtrxEvent | None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: rfxtrxmod.RFXtrxDevice,
|
||||||
|
device_id: DeviceTuple,
|
||||||
|
event: rfxtrxmod.RFXtrxEvent | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the device."""
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers=_get_identifiers_from_device_tuple(device_id),
|
||||||
|
model=device.type_string,
|
||||||
|
name=f"{device.type_string} {device.id_string}",
|
||||||
|
)
|
||||||
|
self._attr_unique_id = "_".join(x for x in device_id)
|
||||||
|
self._device = device
|
||||||
|
self._event = event
|
||||||
|
self._device_id = device_id
|
||||||
|
# If id_string is 213c7f2:1, the group_id is 213c7f2, and the device will respond to
|
||||||
|
# group events regardless of their group indices.
|
||||||
|
(self._group_id, _, _) = cast(str, device.id_string).partition(":")
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Restore RFXtrx device state (ON/OFF)."""
|
||||||
|
if self._event:
|
||||||
|
self._apply_event(self._event)
|
||||||
|
|
||||||
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(self.hass, SIGNAL_EVENT, self._handle_event)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extra_state_attributes(self) -> dict[str, str] | None:
|
||||||
|
"""Return the device state attributes."""
|
||||||
|
if not self._event:
|
||||||
|
return None
|
||||||
|
return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event.data)}
|
||||||
|
|
||||||
|
def _event_applies(
|
||||||
|
self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
|
||||||
|
) -> bool:
|
||||||
|
"""Check if event applies to me."""
|
||||||
|
if isinstance(event, rfxtrxmod.ControlEvent):
|
||||||
|
if (
|
||||||
|
"Command" in event.values
|
||||||
|
and event.values["Command"] in COMMAND_GROUP_LIST
|
||||||
|
):
|
||||||
|
device: rfxtrxmod.RFXtrxDevice = event.device
|
||||||
|
(group_id, _, _) = cast(str, device.id_string).partition(":")
|
||||||
|
return group_id == self._group_id
|
||||||
|
|
||||||
|
# Otherwise, the event only applies to the matching device.
|
||||||
|
return device_id == self._device_id
|
||||||
|
|
||||||
|
def _apply_event(self, event: rfxtrxmod.RFXtrxEvent) -> None:
|
||||||
|
"""Apply a received event."""
|
||||||
|
self._event = event
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle_event(
|
||||||
|
self, event: rfxtrxmod.RFXtrxEvent, device_id: DeviceTuple
|
||||||
|
) -> None:
|
||||||
|
"""Handle a reception of data, overridden by other classes."""
|
||||||
|
|
||||||
|
|
||||||
|
class RfxtrxCommandEntity(RfxtrxEntity):
|
||||||
|
"""Represents a Rfxtrx device.
|
||||||
|
|
||||||
|
Contains the common logic for Rfxtrx lights and switches.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_attr_name = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: rfxtrxmod.RFXtrxDevice,
|
||||||
|
device_id: DeviceTuple,
|
||||||
|
event: rfxtrxmod.RFXtrxEvent | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Initialzie a switch or light device."""
|
||||||
|
super().__init__(device, device_id, event=event)
|
||||||
|
|
||||||
|
async def _async_send[*_Ts](
|
||||||
|
self, fun: Callable[[rfxtrxmod.PySerialTransport, *_Ts], None], *args: *_Ts
|
||||||
|
) -> None:
|
||||||
|
rfx_object: rfxtrxmod.Connect = self.hass.data[DOMAIN][DATA_RFXOBJECT]
|
||||||
|
await self.hass.async_add_executor_job(fun, rfx_object.transport, *args)
|
@ -14,8 +14,9 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
from . import DeviceTuple, RfxtrxEntity, async_setup_platform_entry
|
from . import DeviceTuple, async_setup_platform_entry
|
||||||
from .const import DEVICE_PACKET_TYPE_LIGHTING4
|
from .const import DEVICE_PACKET_TYPE_LIGHTING4
|
||||||
|
from .entity import RfxtrxEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -14,8 +14,9 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DeviceTuple, RfxtrxCommandEntity, async_setup_platform_entry
|
from . import DeviceTuple, async_setup_platform_entry
|
||||||
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
||||||
|
from .entity import RfxtrxCommandEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -39,8 +39,9 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
from . import DeviceTuple, RfxtrxEntity, async_setup_platform_entry, get_rfx_object
|
from . import DeviceTuple, async_setup_platform_entry, get_rfx_object
|
||||||
from .const import ATTR_EVENT
|
from .const import ATTR_EVENT
|
||||||
|
from .entity import RfxtrxEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -14,13 +14,9 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.event import async_call_later
|
from homeassistant.helpers.event import async_call_later
|
||||||
|
|
||||||
from . import (
|
from . import DEFAULT_OFF_DELAY, DeviceTuple, async_setup_platform_entry
|
||||||
DEFAULT_OFF_DELAY,
|
|
||||||
DeviceTuple,
|
|
||||||
RfxtrxCommandEntity,
|
|
||||||
async_setup_platform_entry,
|
|
||||||
)
|
|
||||||
from .const import CONF_OFF_DELAY
|
from .const import CONF_OFF_DELAY
|
||||||
|
from .entity import RfxtrxCommandEntity
|
||||||
|
|
||||||
SECURITY_PANIC_ON = "Panic"
|
SECURITY_PANIC_ON = "Panic"
|
||||||
SECURITY_PANIC_OFF = "End Panic"
|
SECURITY_PANIC_OFF = "End Panic"
|
||||||
|
@ -14,19 +14,15 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import (
|
from . import DeviceTuple, async_setup_platform_entry, get_pt2262_cmd
|
||||||
DOMAIN,
|
|
||||||
DeviceTuple,
|
|
||||||
RfxtrxCommandEntity,
|
|
||||||
async_setup_platform_entry,
|
|
||||||
get_pt2262_cmd,
|
|
||||||
)
|
|
||||||
from .const import (
|
from .const import (
|
||||||
COMMAND_OFF_LIST,
|
COMMAND_OFF_LIST,
|
||||||
COMMAND_ON_LIST,
|
COMMAND_ON_LIST,
|
||||||
CONF_DATA_BITS,
|
CONF_DATA_BITS,
|
||||||
DEVICE_PACKET_TYPE_LIGHTING4,
|
DEVICE_PACKET_TYPE_LIGHTING4,
|
||||||
|
DOMAIN,
|
||||||
)
|
)
|
||||||
|
from .entity import RfxtrxCommandEntity
|
||||||
|
|
||||||
DATA_SWITCH = f"{DOMAIN}_switch"
|
DATA_SWITCH = f"{DOMAIN}_switch"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user