Add specific EntityDescription to describe device tracker entities (#126586)

* Add TrackerEntityDescription to describe tracker entities

* Improve

* Adjust components

* Add ScannerEntityDescription

* Simplify

* Revert

* Set TrackerEntity default source type to SourceType.GPS

* Fix rebase

* Adjust default

* Remove source_type from EntityDescription

* Fix rebase

* Docstring

* Remove BaseTrackerEntityDescription
This commit is contained in:
epenet 2024-09-25 07:28:29 +02:00 committed by GitHub
parent e10d731049
commit 1adaaf49cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 46 additions and 11 deletions

View file

@ -16,7 +16,9 @@ from homeassistant.loader import bind_hass
from .config_entry import ( # noqa: F401 from .config_entry import ( # noqa: F401
ScannerEntity, ScannerEntity,
ScannerEntityDescription,
TrackerEntity, TrackerEntity,
TrackerEntityDescription,
async_setup_entry, async_setup_entry,
async_unload_entry, async_unload_entry,
) )

View file

@ -24,7 +24,7 @@ from homeassistant.helpers.device_registry import (
EventDeviceRegistryUpdatedData, EventDeviceRegistryUpdatedData,
) )
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity_platform import EntityPlatform from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
@ -198,6 +198,10 @@ class BaseTrackerEntity(Entity):
return attr return attr
class TrackerEntityDescription(EntityDescription, frozen_or_thawed=True):
"""A class that describes tracker entities."""
CACHED_TRACKER_PROPERTIES_WITH_ATTR_ = { CACHED_TRACKER_PROPERTIES_WITH_ATTR_ = {
"latitude", "latitude",
"location_accuracy", "location_accuracy",
@ -211,6 +215,7 @@ class TrackerEntity(
): ):
"""Base class for a tracked device.""" """Base class for a tracked device."""
entity_description: TrackerEntityDescription
_attr_latitude: float | None = None _attr_latitude: float | None = None
_attr_location_accuracy: int = 0 _attr_location_accuracy: int = 0
_attr_location_name: str | None = None _attr_location_name: str | None = None
@ -285,6 +290,10 @@ class TrackerEntity(
return attr return attr
class ScannerEntityDescription(EntityDescription, frozen_or_thawed=True):
"""A class that describes tracker entities."""
CACHED_SCANNER_PROPERTIES_WITH_ATTR_ = { CACHED_SCANNER_PROPERTIES_WITH_ATTR_ = {
"ip_address", "ip_address",
"mac_address", "mac_address",
@ -297,6 +306,7 @@ class ScannerEntity(
): ):
"""Base class for a tracked device that is on a scanned network.""" """Base class for a tracked device that is on a scanned network."""
entity_description: ScannerEntityDescription
_attr_hostname: str | None = None _attr_hostname: str | None = None
_attr_ip_address: str | None = None _attr_ip_address: str | None = None
_attr_mac_address: str | None = None _attr_mac_address: str | None = None

View file

@ -2,9 +2,14 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
from renault_api.kamereon.models import KamereonVehicleLocationData from renault_api.kamereon.models import KamereonVehicleLocationData
from homeassistant.components.device_tracker import TrackerEntity from homeassistant.components.device_tracker import (
TrackerEntity,
TrackerEntityDescription,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -12,6 +17,13 @@ from . import RenaultConfigEntry
from .entity import RenaultDataEntity, RenaultDataEntityDescription from .entity import RenaultDataEntity, RenaultDataEntityDescription
@dataclass(frozen=True, kw_only=True)
class RenaultTrackerEntityDescription(
TrackerEntityDescription, RenaultDataEntityDescription
):
"""Class describing Renault tracker entities."""
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: RenaultConfigEntry, config_entry: RenaultConfigEntry,
@ -32,6 +44,8 @@ class RenaultDeviceTracker(
): ):
"""Mixin for device tracker specific attributes.""" """Mixin for device tracker specific attributes."""
entity_description: RenaultTrackerEntityDescription
@property @property
def latitude(self) -> float | None: def latitude(self) -> float | None:
"""Return latitude value of the device.""" """Return latitude value of the device."""
@ -43,8 +57,8 @@ class RenaultDeviceTracker(
return self.coordinator.data.gpsLongitude if self.coordinator.data else None return self.coordinator.data.gpsLongitude if self.coordinator.data else None
DEVICE_TRACKER_TYPES: tuple[RenaultDataEntityDescription, ...] = ( DEVICE_TRACKER_TYPES: tuple[RenaultTrackerEntityDescription, ...] = (
RenaultDataEntityDescription( RenaultTrackerEntityDescription(
key="location", key="location",
coordinator="location", coordinator="location",
translation_key="location", translation_key="location",

View file

@ -4,10 +4,12 @@ from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from homeassistant.components.device_tracker import TrackerEntity from homeassistant.components.device_tracker import (
TrackerEntity,
TrackerEntityDescription,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import ATTR_ALTITUDE, DOMAIN from .const import ATTR_ALTITUDE, DOMAIN
@ -28,9 +30,7 @@ async def async_setup_entry(
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class StarlinkDeviceTrackerEntityDescription( # pylint: disable=hass-enforce-class-module class StarlinkDeviceTrackerEntityDescription(TrackerEntityDescription):
EntityDescription
):
"""Describes a Starlink button entity.""" """Describes a Starlink button entity."""
latitude_fn: Callable[[StarlinkData], float] latitude_fn: Callable[[StarlinkData], float]

View file

@ -21,6 +21,7 @@ from aiounifi.models.event import Event, EventKey
from homeassistant.components.device_tracker import ( from homeassistant.components.device_tracker import (
DOMAIN as DEVICE_TRACKER_DOMAIN, DOMAIN as DEVICE_TRACKER_DOMAIN,
ScannerEntity, ScannerEntity,
ScannerEntityDescription,
) )
from homeassistant.core import Event as core_Event, HomeAssistant, callback from homeassistant.core import Event as core_Event, HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -141,7 +142,9 @@ def async_device_heartbeat_timedelta_fn(hub: UnifiHub, obj_id: str) -> timedelta
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class UnifiTrackerEntityDescription(UnifiEntityDescription[HandlerT, ApiItemT]): class UnifiTrackerEntityDescription(
UnifiEntityDescription[HandlerT, ApiItemT], ScannerEntityDescription
):
"""Class describing UniFi device tracker entity.""" """Class describing UniFi device tracker entity."""
heartbeat_timedelta_fn: Callable[[UnifiHub, str], timedelta] heartbeat_timedelta_fn: Callable[[UnifiHub, str], timedelta]

View file

@ -36,7 +36,13 @@ _MODULES: dict[str, set[str]] = {
"cover": {"CoverEntity", "CoverEntityDescription"}, "cover": {"CoverEntity", "CoverEntityDescription"},
"date": {"DateEntity", "DateEntityDescription"}, "date": {"DateEntity", "DateEntityDescription"},
"datetime": {"DateTimeEntity", "DateTimeEntityDescription"}, "datetime": {"DateTimeEntity", "DateTimeEntityDescription"},
"device_tracker": {"DeviceTrackerEntity", "ScannerEntity", "TrackerEntity"}, "device_tracker": {
"DeviceTrackerEntity",
"ScannerEntity",
"ScannerEntityDescription",
"TrackerEntity",
"TrackerEntityDescription",
},
"event": {"EventEntity", "EventEntityDescription"}, "event": {"EventEntity", "EventEntityDescription"},
"fan": {"FanEntity", "FanEntityDescription"}, "fan": {"FanEntity", "FanEntityDescription"},
"geo_location": {"GeolocationEvent"}, "geo_location": {"GeolocationEvent"},