From 81561d4d3ecb8990188b4450f3ab76ae9db23a00 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 30 May 2023 22:58:27 -0400 Subject: [PATCH] Add non coordinated Entity to Roborock (#93841) switch to non coordinator entity --- .../components/roborock/coordinator.py | 8 +++ homeassistant/components/roborock/device.py | 68 +++++++++++-------- homeassistant/components/roborock/switch.py | 12 ++-- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/roborock/coordinator.py b/homeassistant/components/roborock/coordinator.py index acaa2bfa3f2..d29d7685f1e 100644 --- a/homeassistant/components/roborock/coordinator.py +++ b/homeassistant/components/roborock/coordinator.py @@ -10,6 +10,7 @@ from roborock.local_api import RoborockLocalClient from roborock.roborock_typing import DeviceProp from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN @@ -40,6 +41,13 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]): ) device_info = DeviceData(device, product_info.model, device_networking.ip) self.api = RoborockLocalClient(device_info) + self.device_specification = DeviceInfo( + name=self.device_info.device.name, + identifiers={(DOMAIN, self.device_info.device.duid)}, + manufacturer="Roborock", + model=self.device_info.product.model, + sw_version=self.device_info.device.fv, + ) async def release(self) -> None: """Disconnect from API.""" diff --git a/homeassistant/components/roborock/device.py b/homeassistant/components/roborock/device.py index 39a9524226d..7f54a416d4a 100644 --- a/homeassistant/components/roborock/device.py +++ b/homeassistant/components/roborock/device.py @@ -4,17 +4,46 @@ from typing import Any from roborock.containers import Status from roborock.exceptions import RoborockException +from roborock.local_api import RoborockLocalClient from roborock.roborock_typing import RoborockCommand from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity import DeviceInfo, Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import RoborockDataUpdateCoordinator -from .const import DOMAIN -class RoborockCoordinatedEntity(CoordinatorEntity[RoborockDataUpdateCoordinator]): +class RoborockEntity(Entity): + """Representation of a base Roborock Entity.""" + + _attr_has_entity_name = True + + def __init__( + self, unique_id: str, device_info: DeviceInfo, api: RoborockLocalClient + ) -> None: + """Initialize the coordinated Roborock Device.""" + self._attr_unique_id = unique_id + self._attr_device_info = device_info + self._api = api + + async def send( + self, command: RoborockCommand, params: dict[str, Any] | list[Any] | None = None + ) -> dict: + """Send a command to a vacuum cleaner.""" + try: + response = await self._api.send_command(command, params) + except RoborockException as err: + raise HomeAssistantError( + f"Error while calling {command.name} with {params}" + ) from err + + return response + + +class RoborockCoordinatedEntity( + RoborockEntity, CoordinatorEntity[RoborockDataUpdateCoordinator] +): """Representation of a base a coordinated Roborock Entity.""" _attr_has_entity_name = True @@ -25,7 +54,13 @@ class RoborockCoordinatedEntity(CoordinatorEntity[RoborockDataUpdateCoordinator] coordinator: RoborockDataUpdateCoordinator, ) -> None: """Initialize the coordinated Roborock Device.""" - super().__init__(coordinator) + RoborockEntity.__init__( + self, + unique_id=unique_id, + device_info=coordinator.device_specification, + api=coordinator.api, + ) + CoordinatorEntity.__init__(self, coordinator=coordinator) self._attr_unique_id = unique_id @property @@ -37,28 +72,3 @@ class RoborockCoordinatedEntity(CoordinatorEntity[RoborockDataUpdateCoordinator] if status: return status return Status({}) - - @property - def device_info(self) -> DeviceInfo: - """Return the device info.""" - return DeviceInfo( - name=self.coordinator.device_info.device.name, - identifiers={(DOMAIN, self.coordinator.device_info.device.duid)}, - manufacturer="Roborock", - model=self.coordinator.device_info.product.model, - sw_version=self.coordinator.device_info.device.fv, - ) - - async def send( - self, command: RoborockCommand, params: dict[str, Any] | list[Any] | None = None - ) -> dict: - """Send a command to a vacuum cleaner.""" - try: - response = await self.coordinator.api.send_command(command, params) - except RoborockException as err: - raise HomeAssistantError( - f"Error while calling {command.name} with {params}" - ) from err - - await self.coordinator.async_request_refresh() - return response diff --git a/homeassistant/components/roborock/switch.py b/homeassistant/components/roborock/switch.py index 7b675c3be38..2bfddefc100 100644 --- a/homeassistant/components/roborock/switch.py +++ b/homeassistant/components/roborock/switch.py @@ -15,7 +15,7 @@ from homeassistant.util import slugify from .const import DOMAIN from .coordinator import RoborockDataUpdateCoordinator -from .device import RoborockCoordinatedEntity +from .device import RoborockEntity _LOGGER = logging.getLogger(__name__) @@ -25,11 +25,11 @@ class RoborockSwitchDescriptionMixin: """Define an entity description mixin for switch entities.""" # Gets the status of the switch - get_value: Callable[[RoborockCoordinatedEntity], Coroutine[Any, Any, dict]] + get_value: Callable[[RoborockEntity], Coroutine[Any, Any, dict]] # Evaluate the result of get_value to determine a bool evaluate_value: Callable[[dict], bool] # Sets the status of the switch - set_command: Callable[[RoborockCoordinatedEntity, bool], Coroutine[Any, Any, dict]] + set_command: Callable[[RoborockEntity, bool], Coroutine[Any, Any, dict]] @dataclass @@ -78,7 +78,7 @@ async def async_setup_entry( ) -class RoborockSwitchEntity(RoborockCoordinatedEntity, SwitchEntity): +class RoborockSwitchEntity(RoborockEntity, SwitchEntity): """A class to let you turn functionality on Roborock devices on and off.""" entity_description: RoborockSwitchDescription @@ -91,17 +91,15 @@ class RoborockSwitchEntity(RoborockCoordinatedEntity, SwitchEntity): ) -> None: """Create a switch entity.""" self.entity_description = entity_description - super().__init__(unique_id, coordinator) + super().__init__(unique_id, coordinator.device_specification, coordinator.api) async def async_turn_off(self, **kwargs: Any) -> None: """Turn off the switch.""" await self.entity_description.set_command(self, False) - return self.async_schedule_update_ha_state(True) async def async_turn_on(self, **kwargs: Any) -> None: """Turn on the switch.""" await self.entity_description.set_command(self, True) - return self.async_schedule_update_ha_state(True) async def async_update(self) -> None: """Update switch."""