Bump deebot-client to 8.0.0 (#119515)

Co-authored-by: Franck Nijhof <git@frenck.dev>
pull/116053/head
Robert Resch 2024-06-13 11:49:20 +02:00 committed by GitHub
parent d211af75ef
commit f5b86154b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 100 additions and 160 deletions

View File

@ -4,7 +4,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import Generic
from deebot_client.capabilities import CapabilityEvent, VacuumCapabilities
from deebot_client.capabilities import CapabilityEvent
from deebot_client.events.water_info import WaterInfoEvent
from homeassistant.components.binary_sensor import (
@ -16,12 +16,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcovacsConfigEntry
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EventT,
)
from .entity import EcovacsCapabilityEntityDescription, EcovacsDescriptionEntity, EventT
from .util import get_supported_entitites
@ -38,7 +33,6 @@ class EcovacsBinarySensorEntityDescription(
ENTITY_DESCRIPTIONS: tuple[EcovacsBinarySensorEntityDescription, ...] = (
EcovacsBinarySensorEntityDescription[WaterInfoEvent](
device_capabilities=VacuumCapabilities,
capability_fn=lambda caps: caps.water,
value_fn=lambda e: e.mop_attached,
key="water_mop_attached",
@ -62,7 +56,7 @@ async def async_setup_entry(
class EcovacsBinarySensor(
EcovacsDescriptionEntity[CapabilityDevice, CapabilityEvent[EventT]],
EcovacsDescriptionEntity[CapabilityEvent[EventT]],
BinarySensorEntity,
):
"""Ecovacs binary sensor."""

View File

@ -2,12 +2,7 @@
from dataclasses import dataclass
from deebot_client.capabilities import (
Capabilities,
CapabilityExecute,
CapabilityLifeSpan,
VacuumCapabilities,
)
from deebot_client.capabilities import CapabilityExecute, CapabilityLifeSpan
from deebot_client.events import LifeSpan
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
@ -18,7 +13,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcovacsConfigEntry
from .const import SUPPORTED_LIFESPANS
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EcovacsEntity,
@ -43,7 +37,6 @@ class EcovacsLifespanButtonEntityDescription(ButtonEntityDescription):
ENTITY_DESCRIPTIONS: tuple[EcovacsButtonEntityDescription, ...] = (
EcovacsButtonEntityDescription(
device_capabilities=VacuumCapabilities,
capability_fn=lambda caps: caps.map.relocation if caps.map else None,
key="relocate",
translation_key="relocate",
@ -77,7 +70,7 @@ async def async_setup_entry(
EcovacsResetLifespanButtonEntity(
device, device.capabilities.life_span, description
)
for device in controller.devices(Capabilities)
for device in controller.devices
for description in LIFESPAN_ENTITY_DESCRIPTIONS
if description.component in device.capabilities.life_span.types
)
@ -85,7 +78,7 @@ async def async_setup_entry(
class EcovacsButtonEntity(
EcovacsDescriptionEntity[CapabilityDevice, CapabilityExecute],
EcovacsDescriptionEntity[CapabilityExecute],
ButtonEntity,
):
"""Ecovacs button entity."""
@ -98,7 +91,7 @@ class EcovacsButtonEntity(
class EcovacsResetLifespanButtonEntity(
EcovacsDescriptionEntity[Capabilities, CapabilityLifeSpan],
EcovacsDescriptionEntity[CapabilityLifeSpan],
ButtonEntity,
):
"""Ecovacs reset lifespan button entity."""

View File

@ -9,7 +9,6 @@ from typing import Any
from deebot_client.api_client import ApiClient
from deebot_client.authentication import Authenticator, create_rest_config
from deebot_client.capabilities import Capabilities
from deebot_client.const import UNDEFINED, UndefinedType
from deebot_client.device import Device
from deebot_client.exceptions import DeebotError, InvalidAuthenticationError
@ -18,10 +17,9 @@ from deebot_client.mqtt_client import MqttClient, create_mqtt_config
from deebot_client.util import md5
from deebot_client.util.continents import get_continent
from sucks import EcoVacsAPI, VacBot
from typing_extensions import Generator
from homeassistant.const import CONF_COUNTRY, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError, ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client
from homeassistant.util.ssl import get_default_no_verify_context
@ -119,12 +117,10 @@ class EcovacsController:
await self._mqtt.disconnect()
await self._authenticator.teardown()
@callback
def devices(self, capability: type[Capabilities]) -> Generator[Device]:
"""Return generator for devices with a specific capability."""
for device in self._devices:
if isinstance(device.capabilities, capability):
yield device
@property
def devices(self) -> list[Device]:
"""Return devices."""
return self._devices
@property
def legacy_devices(self) -> list[VacBot]:

View File

@ -4,8 +4,6 @@ from __future__ import annotations
from typing import Any
from deebot_client.capabilities import Capabilities
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
@ -34,7 +32,7 @@ async def async_get_config_entry_diagnostics(
diag["devices"] = [
async_redact_data(device.device_info, REDACT_DEVICE)
for device in controller.devices(Capabilities)
for device in controller.devices
]
diag["legacy_devices"] = [
async_redact_data(device.vacuum, REDACT_DEVICE)

View File

@ -18,11 +18,10 @@ from homeassistant.helpers.entity import Entity, EntityDescription
from .const import DOMAIN
CapabilityEntity = TypeVar("CapabilityEntity")
CapabilityDevice = TypeVar("CapabilityDevice", bound=Capabilities)
EventT = TypeVar("EventT", bound=Event)
class EcovacsEntity(Entity, Generic[CapabilityDevice, CapabilityEntity]):
class EcovacsEntity(Entity, Generic[CapabilityEntity]):
"""Ecovacs entity."""
_attr_should_poll = False
@ -31,7 +30,7 @@ class EcovacsEntity(Entity, Generic[CapabilityDevice, CapabilityEntity]):
def __init__(
self,
device: Device[CapabilityDevice],
device: Device,
capability: CapabilityEntity,
**kwargs: Any,
) -> None:
@ -97,12 +96,12 @@ class EcovacsEntity(Entity, Generic[CapabilityDevice, CapabilityEntity]):
self._device.events.request_refresh(event_type)
class EcovacsDescriptionEntity(EcovacsEntity[CapabilityDevice, CapabilityEntity]):
class EcovacsDescriptionEntity(EcovacsEntity[CapabilityEntity]):
"""Ecovacs entity."""
def __init__(
self,
device: Device[CapabilityDevice],
device: Device,
capability: CapabilityEntity,
entity_description: EntityDescription,
**kwargs: Any,
@ -115,9 +114,8 @@ class EcovacsDescriptionEntity(EcovacsEntity[CapabilityDevice, CapabilityEntity]
@dataclass(kw_only=True, frozen=True)
class EcovacsCapabilityEntityDescription(
EntityDescription,
Generic[CapabilityDevice, CapabilityEntity],
Generic[CapabilityEntity],
):
"""Ecovacs entity description."""
device_capabilities: type[CapabilityDevice]
capability_fn: Callable[[CapabilityDevice], CapabilityEntity | None]
capability_fn: Callable[[Capabilities], CapabilityEntity | None]

View File

@ -1,6 +1,6 @@
"""Event module."""
from deebot_client.capabilities import Capabilities, CapabilityEvent
from deebot_client.capabilities import CapabilityEvent
from deebot_client.device import Device
from deebot_client.events import CleanJobStatus, ReportStatsEvent
@ -22,12 +22,12 @@ async def async_setup_entry(
"""Add entities for passed config_entry in HA."""
controller = config_entry.runtime_data
async_add_entities(
EcovacsLastJobEventEntity(device) for device in controller.devices(Capabilities)
EcovacsLastJobEventEntity(device) for device in controller.devices
)
class EcovacsLastJobEventEntity(
EcovacsEntity[Capabilities, CapabilityEvent[ReportStatsEvent]],
EcovacsEntity[CapabilityEvent[ReportStatsEvent]],
EventEntity,
):
"""Ecovacs last job event entity."""
@ -39,7 +39,7 @@ class EcovacsLastJobEventEntity(
event_types=["finished", "finished_with_warnings", "manually_stopped"],
)
def __init__(self, device: Device[Capabilities]) -> None:
def __init__(self, device: Device) -> None:
"""Initialize entity."""
super().__init__(device, device.capabilities.stats.report)

View File

@ -1,6 +1,6 @@
"""Ecovacs image entities."""
from deebot_client.capabilities import CapabilityMap, VacuumCapabilities
from deebot_client.capabilities import CapabilityMap
from deebot_client.device import Device
from deebot_client.events.map import CachedMapInfoEvent, MapChangedEvent
@ -20,18 +20,18 @@ async def async_setup_entry(
) -> None:
"""Add entities for passed config_entry in HA."""
controller = config_entry.runtime_data
entities = []
for device in controller.devices(VacuumCapabilities):
capabilities: VacuumCapabilities = device.capabilities
if caps := capabilities.map:
entities.append(EcovacsMap(device, caps, hass))
entities = [
EcovacsMap(device, caps, hass)
for device in controller.devices
if (caps := device.capabilities.map)
]
if entities:
async_add_entities(entities)
class EcovacsMap(
EcovacsEntity[VacuumCapabilities, CapabilityMap],
EcovacsEntity[CapabilityMap],
ImageEntity,
):
"""Ecovacs map."""

View File

@ -4,7 +4,7 @@ from __future__ import annotations
import logging
from deebot_client.capabilities import MowerCapabilities
from deebot_client.capabilities import Capabilities, DeviceType
from deebot_client.device import Device
from deebot_client.events import StateEvent
from deebot_client.models import CleanAction, State
@ -42,14 +42,16 @@ async def async_setup_entry(
"""Set up the Ecovacs mowers."""
controller = config_entry.runtime_data
mowers: list[EcovacsMower] = [
EcovacsMower(device) for device in controller.devices(MowerCapabilities)
EcovacsMower(device)
for device in controller.devices
if device.capabilities.device_type is DeviceType.MOWER
]
_LOGGER.debug("Adding Ecovacs Mowers to Home Assistant: %s", mowers)
async_add_entities(mowers)
class EcovacsMower(
EcovacsEntity[MowerCapabilities, MowerCapabilities],
EcovacsEntity[Capabilities],
LawnMowerEntity,
):
"""Ecovacs Mower."""
@ -62,10 +64,9 @@ class EcovacsMower(
entity_description = LawnMowerEntityEntityDescription(key="mower", name=None)
def __init__(self, device: Device[MowerCapabilities]) -> None:
def __init__(self, device: Device) -> None:
"""Initialize the mower."""
capabilities = device.capabilities
super().__init__(device, capabilities)
super().__init__(device, device.capabilities)
async def async_added_to_hass(self) -> None:
"""Set up the event listeners now that hass is ready."""

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/ecovacs",
"iot_class": "cloud_push",
"loggers": ["sleekxmppfs", "sucks", "deebot_client"],
"requirements": ["py-sucks==0.9.10", "deebot-client==7.3.0"]
"requirements": ["py-sucks==0.9.10", "deebot-client==8.0.0"]
}

View File

@ -6,7 +6,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import Generic
from deebot_client.capabilities import Capabilities, CapabilitySet, VacuumCapabilities
from deebot_client.capabilities import CapabilitySet
from deebot_client.events import CleanCountEvent, VolumeEvent
from homeassistant.components.number import NumberEntity, NumberEntityDescription
@ -16,7 +16,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcovacsConfigEntry
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EcovacsEntity,
@ -39,7 +38,6 @@ class EcovacsNumberEntityDescription(
ENTITY_DESCRIPTIONS: tuple[EcovacsNumberEntityDescription, ...] = (
EcovacsNumberEntityDescription[VolumeEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.settings.volume,
value_fn=lambda e: e.volume,
native_max_value_fn=lambda e: e.maximum,
@ -52,7 +50,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsNumberEntityDescription, ...] = (
native_step=1.0,
),
EcovacsNumberEntityDescription[CleanCountEvent](
device_capabilities=VacuumCapabilities,
capability_fn=lambda caps: caps.clean.count,
value_fn=lambda e: e.count,
key="clean_count",
@ -81,7 +78,7 @@ async def async_setup_entry(
class EcovacsNumberEntity(
EcovacsDescriptionEntity[CapabilityDevice, CapabilitySet[EventT, int]],
EcovacsDescriptionEntity[CapabilitySet[EventT, int]],
NumberEntity,
):
"""Ecovacs number entity."""

View File

@ -4,7 +4,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, Generic
from deebot_client.capabilities import CapabilitySetTypes, VacuumCapabilities
from deebot_client.capabilities import CapabilitySetTypes
from deebot_client.device import Device
from deebot_client.events import WaterInfoEvent, WorkModeEvent
@ -14,12 +14,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcovacsConfigEntry
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EventT,
)
from .entity import EcovacsCapabilityEntityDescription, EcovacsDescriptionEntity, EventT
from .util import get_name_key, get_supported_entitites
@ -37,7 +32,6 @@ class EcovacsSelectEntityDescription(
ENTITY_DESCRIPTIONS: tuple[EcovacsSelectEntityDescription, ...] = (
EcovacsSelectEntityDescription[WaterInfoEvent](
device_capabilities=VacuumCapabilities,
capability_fn=lambda caps: caps.water,
current_option_fn=lambda e: get_name_key(e.amount),
options_fn=lambda water: [get_name_key(amount) for amount in water.types],
@ -46,7 +40,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSelectEntityDescription, ...] = (
entity_category=EntityCategory.CONFIG,
),
EcovacsSelectEntityDescription[WorkModeEvent](
device_capabilities=VacuumCapabilities,
capability_fn=lambda caps: caps.clean.work_mode,
current_option_fn=lambda e: get_name_key(e.mode),
options_fn=lambda cap: [get_name_key(mode) for mode in cap.types],
@ -73,7 +66,7 @@ async def async_setup_entry(
class EcovacsSelectEntity(
EcovacsDescriptionEntity[CapabilityDevice, CapabilitySetTypes[EventT, str]],
EcovacsDescriptionEntity[CapabilitySetTypes[EventT, str]],
SelectEntity,
):
"""Ecovacs select entity."""

View File

@ -6,7 +6,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import Generic
from deebot_client.capabilities import Capabilities, CapabilityEvent, CapabilityLifeSpan
from deebot_client.capabilities import CapabilityEvent, CapabilityLifeSpan
from deebot_client.events import (
BatteryEvent,
ErrorEvent,
@ -39,7 +39,6 @@ from homeassistant.helpers.typing import StateType
from . import EcovacsConfigEntry
from .const import SUPPORTED_LIFESPANS
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EcovacsEntity,
@ -63,7 +62,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
# Stats
EcovacsSensorEntityDescription[StatsEvent](
key="stats_area",
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.stats.clean,
value_fn=lambda e: e.area,
translation_key="stats_area",
@ -71,7 +69,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
),
EcovacsSensorEntityDescription[StatsEvent](
key="stats_time",
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.stats.clean,
value_fn=lambda e: e.time,
translation_key="stats_time",
@ -81,7 +78,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
),
# TotalStats
EcovacsSensorEntityDescription[TotalStatsEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.stats.total,
value_fn=lambda e: e.area,
key="total_stats_area",
@ -90,7 +86,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
state_class=SensorStateClass.TOTAL_INCREASING,
),
EcovacsSensorEntityDescription[TotalStatsEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.stats.total,
value_fn=lambda e: e.time,
key="total_stats_time",
@ -101,7 +96,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
state_class=SensorStateClass.TOTAL_INCREASING,
),
EcovacsSensorEntityDescription[TotalStatsEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.stats.total,
value_fn=lambda e: e.cleanings,
key="total_stats_cleanings",
@ -109,7 +103,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
state_class=SensorStateClass.TOTAL_INCREASING,
),
EcovacsSensorEntityDescription[BatteryEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.battery,
value_fn=lambda e: e.value,
key=ATTR_BATTERY_LEVEL,
@ -118,7 +111,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
),
EcovacsSensorEntityDescription[NetworkInfoEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.network,
value_fn=lambda e: e.ip,
key="network_ip",
@ -127,7 +119,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
),
EcovacsSensorEntityDescription[NetworkInfoEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.network,
value_fn=lambda e: e.rssi,
key="network_rssi",
@ -136,7 +127,6 @@ ENTITY_DESCRIPTIONS: tuple[EcovacsSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
),
EcovacsSensorEntityDescription[NetworkInfoEvent](
device_capabilities=Capabilities,
capability_fn=lambda caps: caps.network,
value_fn=lambda e: e.ssid,
key="network_ssid",
@ -181,13 +171,13 @@ async def async_setup_entry(
)
entities.extend(
EcovacsLifespanSensor(device, device.capabilities.life_span, description)
for device in controller.devices(Capabilities)
for device in controller.devices
for description in LIFESPAN_ENTITY_DESCRIPTIONS
if description.component in device.capabilities.life_span.types
)
entities.extend(
EcovacsErrorSensor(device, capability)
for device in controller.devices(Capabilities)
for device in controller.devices
if (capability := device.capabilities.error)
)
@ -195,7 +185,7 @@ async def async_setup_entry(
class EcovacsSensor(
EcovacsDescriptionEntity[CapabilityDevice, CapabilityEvent],
EcovacsDescriptionEntity[CapabilityEvent],
SensorEntity,
):
"""Ecovacs sensor."""
@ -218,7 +208,7 @@ class EcovacsSensor(
class EcovacsLifespanSensor(
EcovacsDescriptionEntity[Capabilities, CapabilityLifeSpan],
EcovacsDescriptionEntity[CapabilityLifeSpan],
SensorEntity,
):
"""Lifespan sensor."""
@ -238,7 +228,7 @@ class EcovacsLifespanSensor(
class EcovacsErrorSensor(
EcovacsEntity[Capabilities, CapabilityEvent[ErrorEvent]],
EcovacsEntity[CapabilityEvent[ErrorEvent]],
SensorEntity,
):
"""Error sensor."""

View File

@ -3,11 +3,7 @@
from dataclasses import dataclass
from typing import Any
from deebot_client.capabilities import (
Capabilities,
CapabilitySetEnable,
VacuumCapabilities,
)
from deebot_client.capabilities import CapabilitySetEnable
from deebot_client.events import EnableEvent
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
@ -17,7 +13,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcovacsConfigEntry
from .entity import (
CapabilityDevice,
EcovacsCapabilityEntityDescription,
EcovacsDescriptionEntity,
EcovacsEntity,
@ -28,86 +23,76 @@ from .util import get_supported_entitites
@dataclass(kw_only=True, frozen=True)
class EcovacsSwitchEntityDescription(
SwitchEntityDescription,
EcovacsCapabilityEntityDescription[CapabilityDevice, CapabilitySetEnable],
EcovacsCapabilityEntityDescription[CapabilitySetEnable],
):
"""Ecovacs switch entity description."""
ENTITY_DESCRIPTIONS: tuple[EcovacsSwitchEntityDescription, ...] = (
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.advanced_mode,
key="advanced_mode",
translation_key="advanced_mode",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[VacuumCapabilities](
device_capabilities=VacuumCapabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.clean.continuous,
key="continuous_cleaning",
translation_key="continuous_cleaning",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[VacuumCapabilities](
device_capabilities=VacuumCapabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.carpet_auto_fan_boost,
key="carpet_auto_fan_boost",
translation_key="carpet_auto_fan_boost",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[VacuumCapabilities](
device_capabilities=VacuumCapabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.clean.preference,
key="clean_preference",
translation_key="clean_preference",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.true_detect,
key="true_detect",
translation_key="true_detect",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.border_switch,
key="border_switch",
translation_key="border_switch",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.child_lock,
key="child_lock",
translation_key="child_lock",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.moveup_warning,
key="move_up_warning",
translation_key="move_up_warning",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.cross_map_border_warning,
key="cross_map_border_warning",
translation_key="cross_map_border_warning",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
),
EcovacsSwitchEntityDescription[Capabilities](
device_capabilities=Capabilities,
EcovacsSwitchEntityDescription(
capability_fn=lambda c: c.settings.safe_protect,
key="safe_protect",
translation_key="safe_protect",
@ -132,7 +117,7 @@ async def async_setup_entry(
class EcovacsSwitchEntity(
EcovacsDescriptionEntity[CapabilityDevice, CapabilitySetEnable],
EcovacsDescriptionEntity[CapabilitySetEnable],
SwitchEntity,
):
"""Ecovacs switch entity."""

View File

@ -7,8 +7,6 @@ import random
import string
from typing import TYPE_CHECKING
from deebot_client.capabilities import Capabilities
from homeassistant.core import HomeAssistant, callback
from homeassistant.util import slugify
@ -40,9 +38,8 @@ def get_supported_entitites(
"""Return all supported entities for all devices."""
return [
entity_class(device, capability, description)
for device in controller.devices(Capabilities)
for device in controller.devices
for description in descriptions
if isinstance(device.capabilities, description.device_capabilities)
if (capability := description.capability_fn(device.capabilities))
]

View File

@ -4,9 +4,9 @@ from __future__ import annotations
from collections.abc import Mapping
import logging
from typing import Any
from typing import TYPE_CHECKING, Any
from deebot_client.capabilities import VacuumCapabilities
from deebot_client.capabilities import Capabilities, DeviceType
from deebot_client.device import Device
from deebot_client.events import BatteryEvent, FanSpeedEvent, RoomsEvent, StateEvent
from deebot_client.models import CleanAction, CleanMode, Room, State
@ -52,7 +52,9 @@ async def async_setup_entry(
controller = config_entry.runtime_data
vacuums: list[EcovacsVacuum | EcovacsLegacyVacuum] = [
EcovacsVacuum(device) for device in controller.devices(VacuumCapabilities)
EcovacsVacuum(device)
for device in controller.devices
if device.capabilities.device_type is DeviceType.VACUUM
]
for device in controller.legacy_devices:
await hass.async_add_executor_job(device.connect_and_wait_until_ready)
@ -232,7 +234,7 @@ _ATTR_ROOMS = "rooms"
class EcovacsVacuum(
EcovacsEntity[VacuumCapabilities, VacuumCapabilities],
EcovacsEntity[Capabilities],
StateVacuumEntity,
):
"""Ecovacs vacuum."""
@ -243,7 +245,6 @@ class EcovacsVacuum(
VacuumEntityFeature.PAUSE
| VacuumEntityFeature.STOP
| VacuumEntityFeature.RETURN_HOME
| VacuumEntityFeature.FAN_SPEED
| VacuumEntityFeature.BATTERY
| VacuumEntityFeature.SEND_COMMAND
| VacuumEntityFeature.LOCATE
@ -255,16 +256,17 @@ class EcovacsVacuum(
key="vacuum", translation_key="vacuum", name=None
)
def __init__(self, device: Device[VacuumCapabilities]) -> None:
def __init__(self, device: Device) -> None:
"""Initialize the vacuum."""
capabilities = device.capabilities
super().__init__(device, capabilities)
super().__init__(device, device.capabilities)
self._rooms: list[Room] = []
self._attr_fan_speed_list = [
get_name_key(level) for level in capabilities.fan_speed.types
]
if fan_speed := self._capability.fan_speed:
self._attr_supported_features |= VacuumEntityFeature.FAN_SPEED
self._attr_fan_speed_list = [
get_name_key(level) for level in fan_speed.types
]
async def async_added_to_hass(self) -> None:
"""Set up the event listeners now that hass is ready."""
@ -274,10 +276,6 @@ class EcovacsVacuum(
self._attr_battery_level = event.value
self.async_write_ha_state()
async def on_fan_speed(event: FanSpeedEvent) -> None:
self._attr_fan_speed = get_name_key(event.speed)
self.async_write_ha_state()
async def on_rooms(event: RoomsEvent) -> None:
self._rooms = event.rooms
self.async_write_ha_state()
@ -287,9 +285,16 @@ class EcovacsVacuum(
self.async_write_ha_state()
self._subscribe(self._capability.battery.event, on_battery)
self._subscribe(self._capability.fan_speed.event, on_fan_speed)
self._subscribe(self._capability.state.event, on_status)
if self._capability.fan_speed:
async def on_fan_speed(event: FanSpeedEvent) -> None:
self._attr_fan_speed = get_name_key(event.speed)
self.async_write_ha_state()
self._subscribe(self._capability.fan_speed.event, on_fan_speed)
if map_caps := self._capability.map:
self._subscribe(map_caps.rooms.event, on_rooms)
@ -319,6 +324,8 @@ class EcovacsVacuum(
async def async_set_fan_speed(self, fan_speed: str, **kwargs: Any) -> None:
"""Set fan speed."""
if TYPE_CHECKING:
assert self._capability.fan_speed
await self._device.execute_command(self._capability.fan_speed.set(fan_speed))
async def async_return_to_base(self, **kwargs: Any) -> None:

View File

@ -706,7 +706,7 @@ debugpy==1.8.1
# decora==0.6
# homeassistant.components.ecovacs
deebot-client==7.3.0
deebot-client==8.0.0
# homeassistant.components.ihc
# homeassistant.components.namecheapdns

View File

@ -584,7 +584,7 @@ dbus-fast==2.21.3
debugpy==1.8.1
# homeassistant.components.ecovacs
deebot-client==7.3.0
deebot-client==8.0.0
# homeassistant.components.ihc
# homeassistant.components.namecheapdns

View File

@ -1,6 +1,5 @@
"""Tests for Ecovacs binary sensors."""
from deebot_client.capabilities import Capabilities
from deebot_client.events import WaterAmount, WaterInfoEvent
import pytest
from syrupy import SnapshotAssertion
@ -38,7 +37,7 @@ async def test_mop_attached(
assert entity_entry == snapshot(name=f"{entity_id}-entity_entry")
assert entity_entry.device_id
device = next(controller.devices(Capabilities))
device = controller.devices[0]
assert (device_entry := device_registry.async_get(entity_entry.device_id))
assert device_entry.identifiers == {(DOMAIN, device.device_info["did"])}

View File

@ -1,6 +1,5 @@
"""Tests for Ecovacs sensors."""
from deebot_client.capabilities import Capabilities
from deebot_client.command import Command
from deebot_client.commands.json import ResetLifeSpan, SetRelocationState
from deebot_client.events import LifeSpan
@ -74,7 +73,7 @@ async def test_buttons(
) -> None:
"""Test that sensor entity snapshots match."""
assert hass.states.async_entity_ids() == [e[0] for e in entities]
device = next(controller.devices(Capabilities))
device = controller.devices[0]
for entity_id, command in entities:
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"
assert state.state == STATE_UNKNOWN

View File

@ -2,7 +2,6 @@
from datetime import timedelta
from deebot_client.capabilities import Capabilities
from deebot_client.events import CleanJobStatus, ReportStatsEvent
from freezegun.api import FrozenDateTimeFactory
import pytest
@ -44,7 +43,7 @@ async def test_last_job(
assert entity_entry == snapshot(name=f"{entity_id}-entity_entry")
assert entity_entry.device_id
device = next(controller.devices(Capabilities))
device = controller.devices[0]
assert (device_entry := device_registry.async_get(entity_entry.device_id))
assert device_entry.identifiers == {(DOMAIN, device.device_info["did"])}

View File

@ -3,7 +3,6 @@
from typing import Any
from unittest.mock import AsyncMock, Mock, patch
from deebot_client.capabilities import Capabilities
from deebot_client.exceptions import DeebotError, InvalidAuthenticationError
import pytest
from syrupy import SnapshotAssertion
@ -121,7 +120,7 @@ async def test_devices_in_dr(
snapshot: SnapshotAssertion,
) -> None:
"""Test all devices are in the device registry."""
for device in controller.devices(Capabilities):
for device in controller.devices:
assert (
device_entry := device_registry.async_get_device(
identifiers={(DOMAIN, device.device_info["did"])}

View File

@ -2,7 +2,6 @@
from dataclasses import dataclass
from deebot_client.capabilities import MowerCapabilities
from deebot_client.command import Command
from deebot_client.commands.json import Charge, CleanV2
from deebot_client.events import StateEvent
@ -56,7 +55,7 @@ async def test_lawn_mower(
assert entity_entry == snapshot(name=f"{entity_id}-entity_entry")
assert entity_entry.device_id
device = next(controller.devices(MowerCapabilities))
device = controller.devices[0]
assert (device_entry := device_registry.async_get(entity_entry.device_id))
assert device_entry.identifiers == {(DOMAIN, device.device_info["did"])}
@ -104,7 +103,7 @@ async def test_mover_services(
tests: list[MowerTestCase],
) -> None:
"""Test mover services."""
device = next(controller.devices(MowerCapabilities))
device = controller.devices[0]
for test in tests:
device._execute_command.reset_mock()

View File

@ -2,7 +2,6 @@
from dataclasses import dataclass
from deebot_client.capabilities import Capabilities
from deebot_client.command import Command
from deebot_client.commands.json import SetVolume
from deebot_client.events import Event, VolumeEvent
@ -66,7 +65,7 @@ async def test_number_entities(
tests: list[NumberTestCase],
) -> None:
"""Test that number entity snapshots match."""
device = next(controller.devices(Capabilities))
device = controller.devices[0]
event_bus = device.events
assert sorted(hass.states.async_entity_ids()) == sorted(
@ -131,7 +130,7 @@ async def test_volume_maximum(
controller: EcovacsController,
) -> None:
"""Test volume maximum."""
device = next(controller.devices(Capabilities))
device = controller.devices[0]
event_bus = device.events
entity_id = "number.ozmo_950_volume"
assert (state := hass.states.get(entity_id))

View File

@ -1,6 +1,5 @@
"""Tests for Ecovacs select entities."""
from deebot_client.capabilities import Capabilities
from deebot_client.command import Command
from deebot_client.commands.json import SetWaterInfo
from deebot_client.event_bus import EventBus
@ -64,7 +63,7 @@ async def test_selects(
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"
assert state.state == STATE_UNKNOWN
device = next(controller.devices(Capabilities))
device = controller.devices[0]
await notify_events(hass, device.events)
for entity_id in entity_ids:
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"
@ -100,7 +99,7 @@ async def test_selects_change(
command: Command,
) -> None:
"""Test that changing select entities works."""
device = next(controller.devices(Capabilities))
device = controller.devices[0]
await notify_events(hass, device.events)
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"

View File

@ -1,6 +1,5 @@
"""Tests for Ecovacs sensors."""
from deebot_client.capabilities import Capabilities
from deebot_client.event_bus import EventBus
from deebot_client.events import (
BatteryEvent,
@ -103,7 +102,7 @@ async def test_sensors(
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"
assert state.state == STATE_UNKNOWN
device = next(controller.devices(Capabilities))
device = controller.devices[0]
await notify_events(hass, device.events)
for entity_id in entity_ids:
assert (state := hass.states.get(entity_id)), f"State of {entity_id} is missing"

View File

@ -2,7 +2,6 @@
from dataclasses import dataclass
from deebot_client.capabilities import Capabilities
from deebot_client.command import Command
from deebot_client.commands.json import (
SetAdvancedMode,
@ -140,7 +139,7 @@ async def test_switch_entities(
tests: list[SwitchTestCase],
) -> None:
"""Test switch entities."""
device = next(controller.devices(Capabilities))
device = controller.devices[0]
event_bus = device.events
assert hass.states.async_entity_ids() == [test.entity_id for test in tests]