From 14bc65e8e7edc8d3922288e5a7b8e593371dfda5 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:06:10 +0200 Subject: [PATCH] Move gardena_bluetooth base entity to separate module (#126484) --- .../components/gardena_bluetooth/__init__.py | 8 ++-- .../gardena_bluetooth/binary_sensor.py | 5 ++- .../components/gardena_bluetooth/button.py | 5 ++- .../gardena_bluetooth/coordinator.py | 41 +----------------- .../components/gardena_bluetooth/entity.py | 43 +++++++++++++++++++ .../components/gardena_bluetooth/number.py | 11 ++--- .../components/gardena_bluetooth/sensor.py | 11 ++--- .../components/gardena_bluetooth/switch.py | 7 +-- .../components/gardena_bluetooth/valve.py | 7 +-- .../components/gardena_bluetooth/conftest.py | 7 +-- 10 files changed, 73 insertions(+), 72 deletions(-) create mode 100644 homeassistant/components/gardena_bluetooth/entity.py diff --git a/homeassistant/components/gardena_bluetooth/__init__.py b/homeassistant/components/gardena_bluetooth/__init__.py index ed5b1c14ba3..b6a26456168 100644 --- a/homeassistant/components/gardena_bluetooth/__init__.py +++ b/homeassistant/components/gardena_bluetooth/__init__.py @@ -18,7 +18,7 @@ from homeassistant.helpers.device_registry import DeviceInfo import homeassistant.util.dt as dt_util from .const import DOMAIN -from .coordinator import Coordinator, DeviceUnavailable +from .coordinator import DeviceUnavailable, GardenaBluetoothCoordinator PLATFORMS: list[Platform] = [ Platform.BINARY_SENSOR, @@ -75,7 +75,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: model=model, ) - coordinator = Coordinator(hass, LOGGER, client, uuids, device, address) + coordinator = GardenaBluetoothCoordinator( + hass, LOGGER, client, uuids, device, address + ) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) @@ -87,7 +89,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): - coordinator: Coordinator = hass.data[DOMAIN].pop(entry.entry_id) + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN].pop(entry.entry_id) await coordinator.async_shutdown() return unload_ok diff --git a/homeassistant/components/gardena_bluetooth/binary_sensor.py b/homeassistant/components/gardena_bluetooth/binary_sensor.py index c552beaf878..be6d8bbeede 100644 --- a/homeassistant/components/gardena_bluetooth/binary_sensor.py +++ b/homeassistant/components/gardena_bluetooth/binary_sensor.py @@ -18,7 +18,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN -from .coordinator import Coordinator, GardenaBluetoothDescriptorEntity +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothDescriptorEntity @dataclass(frozen=True) @@ -55,7 +56,7 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up binary sensor based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities = [ GardenaBluetoothBinarySensor(coordinator, description, description.context) for description in DESCRIPTIONS diff --git a/homeassistant/components/gardena_bluetooth/button.py b/homeassistant/components/gardena_bluetooth/button.py index bdcf9094f5c..67377dc684e 100644 --- a/homeassistant/components/gardena_bluetooth/button.py +++ b/homeassistant/components/gardena_bluetooth/button.py @@ -14,7 +14,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN -from .coordinator import Coordinator, GardenaBluetoothDescriptorEntity +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothDescriptorEntity @dataclass(frozen=True) @@ -44,7 +45,7 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up button based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities = [ GardenaBluetoothButton(coordinator, description, description.context) for description in DESCRIPTIONS diff --git a/homeassistant/components/gardena_bluetooth/coordinator.py b/homeassistant/components/gardena_bluetooth/coordinator.py index 296eff2686e..5caafe0e794 100644 --- a/homeassistant/components/gardena_bluetooth/coordinator.py +++ b/homeassistant/components/gardena_bluetooth/coordinator.py @@ -4,7 +4,6 @@ from __future__ import annotations from datetime import timedelta import logging -from typing import Any from gardena_bluetooth.client import Client from gardena_bluetooth.exceptions import ( @@ -16,12 +15,7 @@ from gardena_bluetooth.parse import Characteristic, CharacteristicType from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.device_registry import DeviceInfo -from homeassistant.helpers.entity import EntityDescription -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, - UpdateFailed, -) +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed SCAN_INTERVAL = timedelta(seconds=60) LOGGER = logging.getLogger(__name__) @@ -31,7 +25,7 @@ class DeviceUnavailable(HomeAssistantError): """Raised if device can't be found.""" -class Coordinator(DataUpdateCoordinator[dict[str, bytes]]): +class GardenaBluetoothCoordinator(DataUpdateCoordinator[dict[str, bytes]]): """Class to manage fetching data.""" def __init__( @@ -102,34 +96,3 @@ class Coordinator(DataUpdateCoordinator[dict[str, bytes]]): self.data[char.uuid] = char.encode(value) await self.async_refresh() - - -class GardenaBluetoothEntity(CoordinatorEntity[Coordinator]): - """Coordinator entity for Gardena Bluetooth.""" - - _attr_has_entity_name = True - - def __init__(self, coordinator: Coordinator, context: Any = None) -> None: - """Initialize coordinator entity.""" - super().__init__(coordinator, context) - self._attr_device_info = coordinator.device_info - - @property - def available(self) -> bool: - """Return if entity is available.""" - return self.coordinator.last_update_success and self._attr_available - - -class GardenaBluetoothDescriptorEntity(GardenaBluetoothEntity): - """Coordinator entity for entities with entity description.""" - - def __init__( - self, - coordinator: Coordinator, - description: EntityDescription, - context: set[str], - ) -> None: - """Initialize description entity.""" - super().__init__(coordinator, context) - self._attr_unique_id = f"{coordinator.address}-{description.key}" - self.entity_description = description diff --git a/homeassistant/components/gardena_bluetooth/entity.py b/homeassistant/components/gardena_bluetooth/entity.py new file mode 100644 index 00000000000..a0344fc4ca0 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/entity.py @@ -0,0 +1,43 @@ +"""Provides the DataUpdateCoordinator.""" + +from __future__ import annotations + +from typing import Any + +from homeassistant.helpers.entity import EntityDescription +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .coordinator import GardenaBluetoothCoordinator + + +class GardenaBluetoothEntity(CoordinatorEntity[GardenaBluetoothCoordinator]): + """Coordinator entity for Gardena Bluetooth.""" + + _attr_has_entity_name = True + + def __init__( + self, coordinator: GardenaBluetoothCoordinator, context: Any = None + ) -> None: + """Initialize coordinator entity.""" + super().__init__(coordinator, context) + self._attr_device_info = coordinator.device_info + + @property + def available(self) -> bool: + """Return if entity is available.""" + return self.coordinator.last_update_success and self._attr_available + + +class GardenaBluetoothDescriptorEntity(GardenaBluetoothEntity): + """Coordinator entity for entities with entity description.""" + + def __init__( + self, + coordinator: GardenaBluetoothCoordinator, + description: EntityDescription, + context: set[str], + ) -> None: + """Initialize description entity.""" + super().__init__(coordinator, context) + self._attr_unique_id = f"{coordinator.address}-{description.key}" + self.entity_description = description diff --git a/homeassistant/components/gardena_bluetooth/number.py b/homeassistant/components/gardena_bluetooth/number.py index cbc4866b0ff..d3c178ee637 100644 --- a/homeassistant/components/gardena_bluetooth/number.py +++ b/homeassistant/components/gardena_bluetooth/number.py @@ -23,11 +23,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN -from .coordinator import ( - Coordinator, - GardenaBluetoothDescriptorEntity, - GardenaBluetoothEntity, -) +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothDescriptorEntity, GardenaBluetoothEntity @dataclass(frozen=True) @@ -111,7 +108,7 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up entity based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities: list[NumberEntity] = [ GardenaBluetoothNumber(coordinator, description, description.context) for description in DESCRIPTIONS @@ -159,7 +156,7 @@ class GardenaBluetoothRemainingOpenSetNumber(GardenaBluetoothEntity, NumberEntit def __init__( self, - coordinator: Coordinator, + coordinator: GardenaBluetoothCoordinator, ) -> None: """Initialize the remaining time entity.""" super().__init__(coordinator, {Valve.remaining_open_time.uuid}) diff --git a/homeassistant/components/gardena_bluetooth/sensor.py b/homeassistant/components/gardena_bluetooth/sensor.py index 3e6ddf9a2df..19fefefa9aa 100644 --- a/homeassistant/components/gardena_bluetooth/sensor.py +++ b/homeassistant/components/gardena_bluetooth/sensor.py @@ -21,11 +21,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback import homeassistant.util.dt as dt_util from .const import DOMAIN -from .coordinator import ( - Coordinator, - GardenaBluetoothDescriptorEntity, - GardenaBluetoothEntity, -) +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothDescriptorEntity, GardenaBluetoothEntity @dataclass(frozen=True) @@ -101,7 +98,7 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Gardena Bluetooth sensor based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities: list[GardenaBluetoothEntity] = [ GardenaBluetoothSensor(coordinator, description, description.context) for description in DESCRIPTIONS @@ -140,7 +137,7 @@ class GardenaBluetoothRemainSensor(GardenaBluetoothEntity, SensorEntity): def __init__( self, - coordinator: Coordinator, + coordinator: GardenaBluetoothCoordinator, ) -> None: """Initialize the sensor.""" super().__init__(coordinator, {Valve.remaining_open_time.uuid}) diff --git a/homeassistant/components/gardena_bluetooth/switch.py b/homeassistant/components/gardena_bluetooth/switch.py index d010665e427..58b4b2e4e51 100644 --- a/homeassistant/components/gardena_bluetooth/switch.py +++ b/homeassistant/components/gardena_bluetooth/switch.py @@ -13,14 +13,15 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN -from .coordinator import Coordinator, GardenaBluetoothEntity +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothEntity async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up switch based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities = [] if GardenaBluetoothValveSwitch.characteristics.issubset( coordinator.characteristics @@ -41,7 +42,7 @@ class GardenaBluetoothValveSwitch(GardenaBluetoothEntity, SwitchEntity): def __init__( self, - coordinator: Coordinator, + coordinator: GardenaBluetoothCoordinator, ) -> None: """Initialize the switch.""" super().__init__( diff --git a/homeassistant/components/gardena_bluetooth/valve.py b/homeassistant/components/gardena_bluetooth/valve.py index 3faf758f7e9..877cc5b505e 100644 --- a/homeassistant/components/gardena_bluetooth/valve.py +++ b/homeassistant/components/gardena_bluetooth/valve.py @@ -12,7 +12,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN -from .coordinator import Coordinator, GardenaBluetoothEntity +from .coordinator import GardenaBluetoothCoordinator +from .entity import GardenaBluetoothEntity FALLBACK_WATERING_TIME_IN_SECONDS = 60 * 60 @@ -21,7 +22,7 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up switch based on a config entry.""" - coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + coordinator: GardenaBluetoothCoordinator = hass.data[DOMAIN][entry.entry_id] entities = [] if GardenaBluetoothValve.characteristics.issubset(coordinator.characteristics): entities.append(GardenaBluetoothValve(coordinator)) @@ -45,7 +46,7 @@ class GardenaBluetoothValve(GardenaBluetoothEntity, ValveEntity): def __init__( self, - coordinator: Coordinator, + coordinator: GardenaBluetoothCoordinator, ) -> None: """Initialize the switch.""" super().__init__( diff --git a/tests/components/gardena_bluetooth/conftest.py b/tests/components/gardena_bluetooth/conftest.py index 882c9b1b090..d363e0e69f3 100644 --- a/tests/components/gardena_bluetooth/conftest.py +++ b/tests/components/gardena_bluetooth/conftest.py @@ -112,10 +112,5 @@ def mock_client( @pytest.fixture(autouse=True) -def enable_all_entities(): +def enable_all_entities(entity_registry_enabled_by_default: None) -> None: """Make sure all entities are enabled.""" - with patch( - "homeassistant.components.gardena_bluetooth.coordinator.GardenaBluetoothEntity.entity_registry_enabled_default", - new=Mock(return_value=True), - ): - yield