mirror of https://github.com/home-assistant/core
188 lines
6.4 KiB
Python
188 lines
6.4 KiB
Python
"""Support for Roborock device base class."""
|
|
|
|
from typing import Any
|
|
|
|
from roborock.api import RoborockClient
|
|
from roborock.command_cache import CacheableAttribute
|
|
from roborock.containers import Consumable, Status
|
|
from roborock.exceptions import RoborockException
|
|
from roborock.roborock_message import RoborockDataProtocol
|
|
from roborock.roborock_typing import RoborockCommand
|
|
from roborock.version_1_apis.roborock_client_v1 import AttributeCache, RoborockClientV1
|
|
from roborock.version_1_apis.roborock_mqtt_client_v1 import RoborockMqttClientV1
|
|
from roborock.version_a01_apis import RoborockClientA01
|
|
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.device_registry import DeviceInfo
|
|
from homeassistant.helpers.entity import Entity
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
|
|
from .const import DOMAIN
|
|
from .coordinator import RoborockDataUpdateCoordinator, RoborockDataUpdateCoordinatorA01
|
|
|
|
|
|
class RoborockEntity(Entity):
|
|
"""Representation of a base Roborock Entity."""
|
|
|
|
_attr_has_entity_name = True
|
|
|
|
def __init__(
|
|
self,
|
|
unique_id: str,
|
|
device_info: DeviceInfo,
|
|
api: RoborockClient,
|
|
) -> None:
|
|
"""Initialize the Roborock Device."""
|
|
self._attr_unique_id = unique_id
|
|
self._attr_device_info = device_info
|
|
self._api = api
|
|
|
|
|
|
class RoborockEntityV1(RoborockEntity):
|
|
"""Representation of a base Roborock V1 Entity."""
|
|
|
|
_api: RoborockClientV1
|
|
|
|
def __init__(
|
|
self, unique_id: str, device_info: DeviceInfo, api: RoborockClientV1
|
|
) -> None:
|
|
"""Initialize the Roborock Device."""
|
|
super().__init__(unique_id, device_info, api)
|
|
|
|
def get_cache(self, attribute: CacheableAttribute) -> AttributeCache:
|
|
"""Get an item from the api cache."""
|
|
return self._api.cache[attribute]
|
|
|
|
async def send(
|
|
self,
|
|
command: RoborockCommand | str,
|
|
params: dict[str, Any] | list[Any] | int | None = None,
|
|
) -> dict:
|
|
"""Send a command to a vacuum cleaner."""
|
|
try:
|
|
response: dict = await self._api.send_command(command, params)
|
|
except RoborockException as err:
|
|
if isinstance(command, RoborockCommand):
|
|
command_name = command.name
|
|
else:
|
|
command_name = command
|
|
raise HomeAssistantError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="command_failed",
|
|
translation_placeholders={
|
|
"command": command_name,
|
|
},
|
|
) from err
|
|
return response
|
|
|
|
@property
|
|
def api(self) -> RoborockClientV1:
|
|
"""Returns the api."""
|
|
return self._api
|
|
|
|
|
|
class RoborockEntityA01(RoborockEntity):
|
|
"""Representation of a base Roborock Entity for A01 devices."""
|
|
|
|
_api: RoborockClientA01
|
|
|
|
def __init__(
|
|
self, unique_id: str, device_info: DeviceInfo, api: RoborockClientA01
|
|
) -> None:
|
|
"""Initialize the Roborock Device."""
|
|
super().__init__(unique_id, device_info, api)
|
|
|
|
|
|
class RoborockCoordinatedEntityV1(
|
|
RoborockEntityV1, CoordinatorEntity[RoborockDataUpdateCoordinator]
|
|
):
|
|
"""Representation of a base a coordinated Roborock Entity."""
|
|
|
|
_attr_has_entity_name = True
|
|
|
|
def __init__(
|
|
self,
|
|
unique_id: str,
|
|
coordinator: RoborockDataUpdateCoordinator,
|
|
listener_request: list[RoborockDataProtocol]
|
|
| RoborockDataProtocol
|
|
| None = None,
|
|
) -> None:
|
|
"""Initialize the coordinated Roborock Device."""
|
|
RoborockEntityV1.__init__(
|
|
self,
|
|
unique_id=unique_id,
|
|
device_info=coordinator.device_info,
|
|
api=coordinator.api,
|
|
)
|
|
CoordinatorEntity.__init__(self, coordinator=coordinator)
|
|
self._attr_unique_id = unique_id
|
|
if isinstance(listener_request, RoborockDataProtocol):
|
|
listener_request = [listener_request]
|
|
self.listener_requests = listener_request or []
|
|
|
|
async def async_added_to_hass(self) -> None:
|
|
"""Add listeners when the device is added to hass."""
|
|
await super().async_added_to_hass()
|
|
for listener_request in self.listener_requests:
|
|
self.api.add_listener(
|
|
listener_request, self._update_from_listener, cache=self.api.cache
|
|
)
|
|
|
|
async def async_will_remove_from_hass(self) -> None:
|
|
"""Remove listeners when the device is removed from hass."""
|
|
for listener_request in self.listener_requests:
|
|
self.api.remove_listener(listener_request, self._update_from_listener)
|
|
await super().async_will_remove_from_hass()
|
|
|
|
@property
|
|
def _device_status(self) -> Status:
|
|
"""Return the status of the device."""
|
|
data = self.coordinator.data
|
|
return data.status
|
|
|
|
@property
|
|
def cloud_api(self) -> RoborockMqttClientV1:
|
|
"""Return the cloud api."""
|
|
return self.coordinator.cloud_api
|
|
|
|
async def send(
|
|
self,
|
|
command: RoborockCommand | str,
|
|
params: dict[str, Any] | list[Any] | int | None = None,
|
|
) -> dict:
|
|
"""Overloads normal send command but refreshes coordinator."""
|
|
res = await super().send(command, params)
|
|
await self.coordinator.async_refresh()
|
|
return res
|
|
|
|
def _update_from_listener(self, value: Status | Consumable) -> None:
|
|
"""Update the status or consumable data from a listener and then write the new entity state."""
|
|
if isinstance(value, Status):
|
|
self.coordinator.roborock_device_info.props.status = value
|
|
else:
|
|
self.coordinator.roborock_device_info.props.consumable = value
|
|
self.coordinator.data = self.coordinator.roborock_device_info.props
|
|
self.schedule_update_ha_state()
|
|
|
|
|
|
class RoborockCoordinatedEntityA01(
|
|
RoborockEntityA01, CoordinatorEntity[RoborockDataUpdateCoordinatorA01]
|
|
):
|
|
"""Representation of a base a coordinated Roborock Entity."""
|
|
|
|
def __init__(
|
|
self,
|
|
unique_id: str,
|
|
coordinator: RoborockDataUpdateCoordinatorA01,
|
|
) -> None:
|
|
"""Initialize the coordinated Roborock Device."""
|
|
RoborockEntityA01.__init__(
|
|
self,
|
|
unique_id=unique_id,
|
|
device_info=coordinator.device_info,
|
|
api=coordinator.api,
|
|
)
|
|
CoordinatorEntity.__init__(self, coordinator=coordinator)
|
|
self._attr_unique_id = unique_id
|