mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 15:31:52 -05:00
Extract shared base entity for Subaru (#176246)
This commit is contained in:
@@ -10,15 +10,14 @@ from homeassistant.components.button import ButtonEntity, ButtonEntityDescriptio
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import get_device_info
|
||||
from .const import (
|
||||
SERVICE_REMOTE_START,
|
||||
SERVICE_REMOTE_STOP,
|
||||
VEHICLE_HAS_EV,
|
||||
VEHICLE_HAS_REMOTE_START,
|
||||
VEHICLE_VIN,
|
||||
)
|
||||
from .coordinator import SubaruConfigEntry, SubaruDataUpdateCoordinator
|
||||
from .entity import SubaruEntity
|
||||
from .remote_service import async_call_remote_service
|
||||
|
||||
|
||||
@@ -59,10 +58,9 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
|
||||
class SubaruButton(ButtonEntity):
|
||||
class SubaruButton(SubaruEntity, ButtonEntity):
|
||||
"""Class for a Subaru button."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
entity_description: SubaruButtonEntityDescription
|
||||
|
||||
def __init__(
|
||||
@@ -73,13 +71,10 @@ class SubaruButton(ButtonEntity):
|
||||
description: SubaruButtonEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the button for the vehicle."""
|
||||
super().__init__(vehicle_info, description.key)
|
||||
self.controller = controller
|
||||
self.coordinator = coordinator
|
||||
self.vehicle_info = vehicle_info
|
||||
self.entity_description = description
|
||||
vin = vehicle_info[VEHICLE_VIN]
|
||||
self._attr_unique_id = f"{vin}_{description.key}"
|
||||
self._attr_device_info = get_device_info(vehicle_info)
|
||||
|
||||
@override
|
||||
async def async_press(self) -> None:
|
||||
|
||||
@@ -7,11 +7,10 @@ from subarulink.const import LATITUDE, LONGITUDE, TIMESTAMP
|
||||
from homeassistant.components.device_tracker import TrackerEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import get_device_info
|
||||
from .const import VEHICLE_HAS_REMOTE_SERVICE, VEHICLE_STATUS, VEHICLE_VIN
|
||||
from .const import VEHICLE_HAS_REMOTE_SERVICE, VEHICLE_STATUS
|
||||
from .coordinator import SubaruConfigEntry, SubaruDataUpdateCoordinator
|
||||
from .entity import SubaruCoordinatorEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@@ -29,23 +28,17 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
|
||||
class SubaruDeviceTracker(
|
||||
CoordinatorEntity[SubaruDataUpdateCoordinator], TrackerEntity
|
||||
):
|
||||
class SubaruDeviceTracker(SubaruCoordinatorEntity, TrackerEntity):
|
||||
"""Class for Subaru device tracker."""
|
||||
|
||||
_attr_translation_key = "location"
|
||||
_attr_has_entity_name = True
|
||||
_attr_name = None
|
||||
|
||||
def __init__(
|
||||
self, vehicle_info: dict, coordinator: SubaruDataUpdateCoordinator
|
||||
) -> None:
|
||||
"""Initialize the device tracker."""
|
||||
super().__init__(coordinator)
|
||||
self.vin = vehicle_info[VEHICLE_VIN]
|
||||
self._attr_device_info = get_device_info(vehicle_info)
|
||||
self._attr_unique_id = f"{self.vin}_location"
|
||||
super().__init__(vehicle_info, coordinator, "location")
|
||||
|
||||
@property
|
||||
@override
|
||||
@@ -72,8 +65,8 @@ class SubaruDeviceTracker(
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available."""
|
||||
if vehicle_data := self.coordinator.data.get(self.vin):
|
||||
if status := vehicle_data.get(VEHICLE_STATUS):
|
||||
return status.keys() & {LATITUDE, LONGITUDE, TIMESTAMP}
|
||||
return False
|
||||
"""Return if available; not gated on last_update_success, only on the relevant status keys being present."""
|
||||
if not (vehicle_data := (self.coordinator.data or {}).get(self.vin)):
|
||||
return False
|
||||
status = vehicle_data.get(VEHICLE_STATUS) or {}
|
||||
return bool(status.keys() & {LATITUDE, LONGITUDE, TIMESTAMP})
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Base entities for the Subaru integration."""
|
||||
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import get_device_info
|
||||
from .const import VEHICLE_VIN
|
||||
from .coordinator import SubaruDataUpdateCoordinator
|
||||
|
||||
|
||||
class SubaruEntity(Entity):
|
||||
"""Base class for Subaru entities: device_info, unique_id, has_entity_name."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(self, vehicle_info: dict[str, Any], unique_id_suffix: str) -> None:
|
||||
"""Initialize the entity from the vehicle_info dict."""
|
||||
self.vehicle_info = vehicle_info
|
||||
self.vin: str = vehicle_info[VEHICLE_VIN]
|
||||
self._attr_device_info = get_device_info(vehicle_info)
|
||||
self._attr_unique_id = f"{self.vin}_{unique_id_suffix}"
|
||||
|
||||
|
||||
class SubaruCoordinatorEntity(
|
||||
CoordinatorEntity[SubaruDataUpdateCoordinator], SubaruEntity
|
||||
):
|
||||
"""Base class for coordinator-backed Subaru entities."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vehicle_info: dict[str, Any],
|
||||
coordinator: SubaruDataUpdateCoordinator,
|
||||
unique_id_suffix: str,
|
||||
) -> None:
|
||||
"""Initialize the coordinator-backed entity."""
|
||||
super().__init__(coordinator)
|
||||
SubaruEntity.__init__(self, vehicle_info, unique_id_suffix)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return if available; also gates on data for this vehicle being present."""
|
||||
return super().available and self.vin in self.coordinator.data
|
||||
@@ -11,7 +11,6 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_platform
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import get_device_info
|
||||
from .const import (
|
||||
ATTR_DOOR,
|
||||
SERVICE_UNLOCK_SPECIFIC_DOOR,
|
||||
@@ -19,9 +18,9 @@ from .const import (
|
||||
UNLOCK_VALID_DOORS,
|
||||
VEHICLE_HAS_REMOTE_SERVICE,
|
||||
VEHICLE_NAME,
|
||||
VEHICLE_VIN,
|
||||
)
|
||||
from .coordinator import SubaruConfigEntry
|
||||
from .entity import SubaruEntity
|
||||
from .remote_service import async_call_remote_service
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -50,7 +49,7 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
|
||||
class SubaruLock(LockEntity):
|
||||
class SubaruLock(SubaruEntity, LockEntity):
|
||||
"""Representation of a Subaru door lock.
|
||||
|
||||
Note that the Subaru API currently does not support
|
||||
@@ -58,17 +57,13 @@ class SubaruLock(LockEntity):
|
||||
always unknown.
|
||||
"""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_translation_key = "door_locks"
|
||||
|
||||
def __init__(self, vehicle_info, controller):
|
||||
"""Initialize the locks for the vehicle."""
|
||||
super().__init__(vehicle_info, "door_locks")
|
||||
self.controller = controller
|
||||
self.vehicle_info = vehicle_info
|
||||
vin = vehicle_info[VEHICLE_VIN]
|
||||
self.car_name = vehicle_info[VEHICLE_NAME]
|
||||
self._attr_unique_id = f"{vin}_door_locks"
|
||||
self._attr_device_info = get_device_info(vehicle_info)
|
||||
|
||||
@override
|
||||
async def async_lock(self, **kwargs: Any) -> None:
|
||||
|
||||
@@ -27,11 +27,9 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from homeassistant.util.unit_conversion import DistanceConverter, VolumeConverter
|
||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||
|
||||
from . import get_device_info
|
||||
from .const import (
|
||||
API_GEN_2,
|
||||
API_GEN_3,
|
||||
@@ -42,9 +40,9 @@ from .const import (
|
||||
VEHICLE_HAS_EV,
|
||||
VEHICLE_HEALTH,
|
||||
VEHICLE_STATUS,
|
||||
VEHICLE_VIN,
|
||||
)
|
||||
from .coordinator import SubaruConfigEntry, SubaruDataUpdateCoordinator
|
||||
from .entity import SubaruCoordinatorEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -260,10 +258,9 @@ def create_vehicle_sensors(
|
||||
]
|
||||
|
||||
|
||||
class SubaruSensor(CoordinatorEntity[SubaruDataUpdateCoordinator], SensorEntity):
|
||||
class SubaruSensor(SubaruCoordinatorEntity, SensorEntity):
|
||||
"""Class for Subaru sensors."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
entity_description: SubaruSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
@@ -273,11 +270,8 @@ class SubaruSensor(CoordinatorEntity[SubaruDataUpdateCoordinator], SensorEntity)
|
||||
description: SubaruSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(coordinator)
|
||||
self.vin = vehicle_info[VEHICLE_VIN]
|
||||
super().__init__(vehicle_info, coordinator, description.key)
|
||||
self.entity_description = description
|
||||
self._attr_device_info = get_device_info(vehicle_info)
|
||||
self._attr_unique_id = f"{self.vin}_{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
@@ -312,15 +306,6 @@ class SubaruSensor(CoordinatorEntity[SubaruDataUpdateCoordinator], SensorEntity)
|
||||
return FUEL_CONSUMPTION_LITERS_PER_HUNDRED_KILOMETERS
|
||||
return self.entity_description.native_unit_of_measurement
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available."""
|
||||
last_update_success = super().available
|
||||
if last_update_success and self.vin not in self.coordinator.data:
|
||||
return False
|
||||
return last_update_success
|
||||
|
||||
|
||||
async def _async_migrate_entries(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
|
||||
Reference in New Issue
Block a user