From 2d2e0d0fb9b2a93d9f6f87f667b47ec5185a4a65 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 26 May 2025 14:45:55 +0200 Subject: [PATCH] Add init type hints to XiaomiCoordinatedMiioEntity derived entities (#145612) --- .../components/xiaomi_miio/binary_sensor.py | 18 +- .../components/xiaomi_miio/button.py | 16 +- .../components/xiaomi_miio/entity.py | 12 +- homeassistant/components/xiaomi_miio/fan.py | 164 +++++++++++++----- .../components/xiaomi_miio/humidifier.py | 50 ++++-- .../components/xiaomi_miio/number.py | 31 ++-- .../components/xiaomi_miio/select.py | 37 +++- .../components/xiaomi_miio/sensor.py | 15 +- .../components/xiaomi_miio/switch.py | 65 ++++--- .../components/xiaomi_miio/vacuum.py | 57 ++++-- 10 files changed, 328 insertions(+), 137 deletions(-) diff --git a/homeassistant/components/xiaomi_miio/binary_sensor.py b/homeassistant/components/xiaomi_miio/binary_sensor.py index b0a990cf9be..205db7cd21c 100644 --- a/homeassistant/components/xiaomi_miio/binary_sensor.py +++ b/homeassistant/components/xiaomi_miio/binary_sensor.py @@ -5,7 +5,9 @@ from __future__ import annotations from collections.abc import Callable, Iterable from dataclasses import dataclass import logging -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any + +from miio import Device as MiioDevice from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, @@ -15,6 +17,7 @@ from homeassistant.components.binary_sensor import ( from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import VacuumCoordinatorDataAttributes from .const import ( @@ -213,12 +216,21 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiGenericBinarySensor(XiaomiCoordinatedMiioEntity, BinarySensorEntity): +class XiaomiGenericBinarySensor( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], BinarySensorEntity +): """Representation of a Xiaomi Humidifier binary sensor.""" entity_description: XiaomiMiioBinarySensorDescription - def __init__(self, device, entry, unique_id, coordinator, description): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioBinarySensorDescription, + ) -> None: """Initialize the entity.""" super().__init__(device, entry, unique_id, coordinator) diff --git a/homeassistant/components/xiaomi_miio/button.py b/homeassistant/components/xiaomi_miio/button.py index 194b73f2372..58236e136cb 100644 --- a/homeassistant/components/xiaomi_miio/button.py +++ b/homeassistant/components/xiaomi_miio/button.py @@ -3,7 +3,9 @@ from __future__ import annotations from dataclasses import dataclass +from typing import Any +from miio import Device as MiioDevice from miio.integrations.vacuum.roborock.vacuum import Consumable from homeassistant.components.button import ( @@ -14,6 +16,7 @@ from homeassistant.components.button import ( from homeassistant.const import CONF_MODEL, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import MODEL_AIRFRESH_A1, MODEL_AIRFRESH_T2017, MODELS_VACUUM from .entity import XiaomiCoordinatedMiioEntity @@ -148,14 +151,23 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiGenericCoordinatedButton(XiaomiCoordinatedMiioEntity, ButtonEntity): +class XiaomiGenericCoordinatedButton( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], ButtonEntity +): """A button implementation for Xiaomi.""" entity_description: XiaomiMiioButtonDescription _attr_device_class = ButtonDeviceClass.RESTART - def __init__(self, device, entry, unique_id, coordinator, description): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioButtonDescription, + ) -> None: """Initialize the plug switch.""" super().__init__(device, entry, unique_id, coordinator) self.entity_description = description diff --git a/homeassistant/components/xiaomi_miio/entity.py b/homeassistant/components/xiaomi_miio/entity.py index cef2137a8c0..f8cdc69a12e 100644 --- a/homeassistant/components/xiaomi_miio/entity.py +++ b/homeassistant/components/xiaomi_miio/entity.py @@ -6,7 +6,7 @@ from functools import partial import logging from typing import TYPE_CHECKING, Any -from miio import DeviceException +from miio import Device as MiioDevice, DeviceException from miio.gateway.devices import SubDevice from homeassistant.const import ATTR_CONNECTIONS, CONF_MAC, CONF_MODEL @@ -70,7 +70,13 @@ class XiaomiCoordinatedMiioEntity[_T: DataUpdateCoordinator[Any]]( _attr_has_entity_name = True - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: _T, + ) -> None: """Initialize the coordinated Xiaomi Miio Device.""" super().__init__(coordinator) self._device = device @@ -88,6 +94,8 @@ class XiaomiCoordinatedMiioEntity[_T: DataUpdateCoordinator[Any]]( @property def device_info(self) -> DeviceInfo: """Return the device info.""" + if TYPE_CHECKING: + assert self._device_id is not None device_info = DeviceInfo( identifiers={(DOMAIN, self._device_id)}, manufacturer="Xiaomi", diff --git a/homeassistant/components/xiaomi_miio/fan.py b/homeassistant/components/xiaomi_miio/fan.py index 4492dcf9f17..aa7069f1e92 100644 --- a/homeassistant/components/xiaomi_miio/fan.py +++ b/homeassistant/components/xiaomi_miio/fan.py @@ -8,6 +8,7 @@ import logging import math from typing import Any +from miio import Device as MiioDevice from miio.fan_common import ( MoveDirection as FanMoveDirection, OperationMode as FanOperationMode, @@ -34,6 +35,7 @@ from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICE, CONF_MODEL from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util.percentage import ( percentage_to_ranged_value, ranged_value_to_percentage, @@ -293,22 +295,30 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiGenericDevice(XiaomiCoordinatedMiioEntity, FanEntity): +class XiaomiGenericDevice( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], FanEntity +): """Representation of a generic Xiaomi device.""" _attr_name = None - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the generic Xiaomi device.""" super().__init__(device, entry, unique_id, coordinator) - self._available_attributes = {} - self._state = None - self._mode = None - self._fan_level = None - self._state_attrs = {} + self._available_attributes: dict[str, Any] = {} + self._state: bool | None = None + self._mode: str | None = None + self._fan_level: int | None = None + self._state_attrs: dict[str, Any] = {} self._device_features = 0 - self._preset_modes = [] + self._preset_modes: list[str] = [] @property @abstractmethod @@ -343,7 +353,8 @@ class XiaomiGenericDevice(XiaomiCoordinatedMiioEntity, FanEntity): ) -> None: """Turn the device on.""" result = await self._try_command( - "Turning the miio device on failed.", self._device.on + "Turning the miio device on failed.", + self._device.on, # type: ignore[attr-defined] ) # If operation mode was set the device must not be turned on. @@ -359,7 +370,8 @@ class XiaomiGenericDevice(XiaomiCoordinatedMiioEntity, FanEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn the device off.""" result = await self._try_command( - "Turning the miio device off failed.", self._device.off + "Turning the miio device off failed.", + self._device.off, # type: ignore[attr-defined] ) if result: @@ -370,7 +382,13 @@ class XiaomiGenericDevice(XiaomiCoordinatedMiioEntity, FanEntity): class XiaomiGenericAirPurifier(XiaomiGenericDevice): """Representation of a generic AirPurifier device.""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the generic AirPurifier device.""" super().__init__(device, entry, unique_id, coordinator) @@ -417,7 +435,13 @@ class XiaomiAirPurifier(XiaomiGenericAirPurifier): REVERSE_SPEED_MODE_MAPPING = {v: k for k, v in SPEED_MODE_MAPPING.items()} - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the plug switch.""" super().__init__(device, entry, unique_id, coordinator) @@ -528,7 +552,7 @@ class XiaomiAirPurifier(XiaomiGenericAirPurifier): if speed_mode: await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class(self.SPEED_MODE_MAPPING[speed_mode]), ) @@ -539,7 +563,7 @@ class XiaomiAirPurifier(XiaomiGenericAirPurifier): """ if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ): self._mode = self.operation_mode_class[preset_mode].value @@ -552,7 +576,7 @@ class XiaomiAirPurifier(XiaomiGenericAirPurifier): await self._try_command( "Setting the extra features of the miio device failed.", - self._device.set_extra_features, + self._device.set_extra_features, # type: ignore[attr-defined] features, ) @@ -599,7 +623,7 @@ class XiaomiAirPurifierMiot(XiaomiAirPurifier): return if await self._try_command( "Setting fan level of the miio device failed.", - self._device.set_fan_level, + self._device.set_fan_level, # type: ignore[attr-defined] fan_level, ): self._fan_level = fan_level @@ -609,7 +633,13 @@ class XiaomiAirPurifierMiot(XiaomiAirPurifier): class XiaomiAirPurifierMB4(XiaomiGenericAirPurifier): """Representation of a Xiaomi Air Purifier MB4.""" - def __init__(self, device, entry, unique_id, coordinator) -> None: + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize Air Purifier MB4.""" super().__init__(device, entry, unique_id, coordinator) @@ -659,7 +689,7 @@ class XiaomiAirPurifierMB4(XiaomiGenericAirPurifier): return if await self._try_command( "Setting fan level of the miio device failed.", - self._device.set_favorite_rpm, + self._device.set_favorite_rpm, # type: ignore[attr-defined] favorite_rpm, ): self._favorite_rpm = favorite_rpm @@ -673,7 +703,7 @@ class XiaomiAirPurifierMB4(XiaomiGenericAirPurifier): if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ): self._mode = self.operation_mode_class[preset_mode].value @@ -712,7 +742,13 @@ class XiaomiAirFresh(XiaomiGenericAirPurifier): "Interval": AirfreshOperationMode.Interval, } - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the miio device.""" super().__init__(device, entry, unique_id, coordinator) @@ -764,7 +800,7 @@ class XiaomiAirFresh(XiaomiGenericAirPurifier): if speed_mode: if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] AirfreshOperationMode(self.SPEED_MODE_MAPPING[speed_mode]), ): self._mode = AirfreshOperationMode( @@ -779,7 +815,7 @@ class XiaomiAirFresh(XiaomiGenericAirPurifier): """ if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ): self._mode = self.operation_mode_class[preset_mode].value @@ -792,7 +828,7 @@ class XiaomiAirFresh(XiaomiGenericAirPurifier): await self._try_command( "Setting the extra features of the miio device failed.", - self._device.set_extra_features, + self._device.set_extra_features, # type: ignore[attr-defined] features, ) @@ -810,10 +846,16 @@ class XiaomiAirFresh(XiaomiGenericAirPurifier): class XiaomiAirFreshA1(XiaomiGenericAirPurifier): """Representation of a Xiaomi Air Fresh A1.""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the miio device.""" super().__init__(device, entry, unique_id, coordinator) - self._favorite_speed = None + self._favorite_speed: int | None = None self._device_features = FEATURE_FLAGS_AIRFRESH_A1 self._preset_modes = PRESET_MODES_AIRFRESH_A1 self._attr_supported_features = ( @@ -857,7 +899,7 @@ class XiaomiAirFreshA1(XiaomiGenericAirPurifier): return if await self._try_command( "Setting fan level of the miio device failed.", - self._device.set_favorite_speed, + self._device.set_favorite_speed, # type: ignore[attr-defined] favorite_speed, ): self._favorite_speed = favorite_speed @@ -867,7 +909,7 @@ class XiaomiAirFreshA1(XiaomiGenericAirPurifier): """Set the preset mode of the fan. This method is a coroutine.""" if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ): self._mode = self.operation_mode_class[preset_mode].value @@ -885,7 +927,13 @@ class XiaomiAirFreshA1(XiaomiGenericAirPurifier): class XiaomiAirFreshT2017(XiaomiAirFreshA1): """Representation of a Xiaomi Air Fresh T2017.""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the miio device.""" super().__init__(device, entry, unique_id, coordinator) self._device_features = FEATURE_FLAGS_AIRFRESH_T2017 @@ -897,7 +945,13 @@ class XiaomiGenericFan(XiaomiGenericDevice): _attr_translation_key = "generic_fan" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the fan.""" super().__init__(device, entry, unique_id, coordinator) @@ -922,9 +976,9 @@ class XiaomiGenericFan(XiaomiGenericDevice): ) if self._model != MODEL_FAN_1C: self._attr_supported_features |= FanEntityFeature.DIRECTION - self._preset_mode = None - self._oscillating = None - self._percentage = None + self._preset_mode: str | None = None + self._oscillating: bool | None = None + self._percentage: int | None = None @property def preset_mode(self) -> str | None: @@ -953,7 +1007,7 @@ class XiaomiGenericFan(XiaomiGenericDevice): """Set oscillation.""" await self._try_command( "Setting oscillate on/off of the miio device failed.", - self._device.set_oscillate, + self._device.set_oscillate, # type: ignore[attr-defined] oscillating, ) self._oscillating = oscillating @@ -966,7 +1020,7 @@ class XiaomiGenericFan(XiaomiGenericDevice): await self._try_command( "Setting move direction of the miio device failed.", - self._device.set_rotate, + self._device.set_rotate, # type: ignore[attr-defined] FanMoveDirection(FAN_DIRECTIONS_MAP[direction]), ) @@ -974,7 +1028,13 @@ class XiaomiGenericFan(XiaomiGenericDevice): class XiaomiFan(XiaomiGenericFan): """Representation of a Xiaomi Fan.""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the fan.""" super().__init__(device, entry, unique_id, coordinator) @@ -1018,13 +1078,13 @@ class XiaomiFan(XiaomiGenericFan): if preset_mode == ATTR_MODE_NATURE: await self._try_command( "Setting natural fan speed percentage of the miio device failed.", - self._device.set_natural_speed, + self._device.set_natural_speed, # type: ignore[attr-defined] self._percentage, ) else: await self._try_command( "Setting direct fan speed percentage of the miio device failed.", - self._device.set_direct_speed, + self._device.set_direct_speed, # type: ignore[attr-defined] self._percentage, ) @@ -1041,13 +1101,13 @@ class XiaomiFan(XiaomiGenericFan): if self._nature_mode: await self._try_command( "Setting fan speed percentage of the miio device failed.", - self._device.set_natural_speed, + self._device.set_natural_speed, # type: ignore[attr-defined] percentage, ) else: await self._try_command( "Setting fan speed percentage of the miio device failed.", - self._device.set_direct_speed, + self._device.set_direct_speed, # type: ignore[attr-defined] percentage, ) self._percentage = percentage @@ -1061,7 +1121,13 @@ class XiaomiFan(XiaomiGenericFan): class XiaomiFanP5(XiaomiGenericFan): """Representation of a Xiaomi Fan P5.""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the fan.""" super().__init__(device, entry, unique_id, coordinator) @@ -1089,7 +1155,7 @@ class XiaomiFanP5(XiaomiGenericFan): """Set the preset mode of the fan.""" await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ) self._preset_mode = preset_mode @@ -1104,7 +1170,7 @@ class XiaomiFanP5(XiaomiGenericFan): await self._try_command( "Setting fan speed percentage of the miio device failed.", - self._device.set_speed, + self._device.set_speed, # type: ignore[attr-defined] percentage, ) self._percentage = percentage @@ -1145,7 +1211,7 @@ class XiaomiFanMiot(XiaomiGenericFan): """Set the preset mode of the fan.""" await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.operation_mode_class[preset_mode], ) self._preset_mode = preset_mode @@ -1160,7 +1226,7 @@ class XiaomiFanMiot(XiaomiGenericFan): result = await self._try_command( "Setting fan speed percentage of the miio device failed.", - self._device.set_speed, + self._device.set_speed, # type: ignore[attr-defined] percentage, ) if result: @@ -1184,7 +1250,13 @@ class XiaomiFanZA5(XiaomiFanMiot): class XiaomiFan1C(XiaomiFanMiot): """Representation of a Xiaomi Fan 1C (Standing Fan 2 Lite).""" - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize MIOT fan with speed count.""" super().__init__(device, entry, unique_id, coordinator) self._speed_count = 3 @@ -1221,7 +1293,7 @@ class XiaomiFan1C(XiaomiFanMiot): result = await self._try_command( "Setting fan speed percentage of the miio device failed.", - self._device.set_speed, + self._device.set_speed, # type: ignore[attr-defined] speed, ) diff --git a/homeassistant/components/xiaomi_miio/humidifier.py b/homeassistant/components/xiaomi_miio/humidifier.py index bf87f18e14a..49ae58ed2ef 100644 --- a/homeassistant/components/xiaomi_miio/humidifier.py +++ b/homeassistant/components/xiaomi_miio/humidifier.py @@ -4,6 +4,7 @@ import logging import math from typing import Any +from miio import Device as MiioDevice from miio.integrations.humidifier.deerma.airhumidifier_mjjsq import ( OperationMode as AirhumidifierMjjsqOperationMode, ) @@ -23,6 +24,7 @@ from homeassistant.components.humidifier import ( from homeassistant.const import ATTR_MODE, CONF_DEVICE, CONF_MODEL from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util.percentage import percentage_to_ranged_value from .const import ( @@ -108,26 +110,35 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiGenericHumidifier(XiaomiCoordinatedMiioEntity, HumidifierEntity): +class XiaomiGenericHumidifier( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], HumidifierEntity +): """Representation of a generic Xiaomi humidifier device.""" _attr_device_class = HumidifierDeviceClass.HUMIDIFIER _attr_supported_features = HumidifierEntityFeature.MODES _attr_name = None - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the generic Xiaomi device.""" super().__init__(device, entry, unique_id, coordinator=coordinator) - self._attributes = {} - self._mode = None + self._attributes: dict[str, Any] = {} + self._mode: str | int | None = None self._humidity_steps = 100 self._target_humidity: float | None = None async def async_turn_on(self, **kwargs: Any) -> None: """Turn the device on.""" result = await self._try_command( - "Turning the miio device on failed.", self._device.on + "Turning the miio device on failed.", + self._device.on, # type: ignore[attr-defined] ) if result: self._attr_is_on = True @@ -136,7 +147,8 @@ class XiaomiGenericHumidifier(XiaomiCoordinatedMiioEntity, HumidifierEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn the device off.""" result = await self._try_command( - "Turning the miio device off failed.", self._device.off + "Turning the miio device off failed.", + self._device.off, # type: ignore[attr-defined] ) if result: @@ -159,7 +171,13 @@ class XiaomiAirHumidifier(XiaomiGenericHumidifier, HumidifierEntity): available_modes: list[str] - def __init__(self, device, entry, unique_id, coordinator): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, + coordinator: DataUpdateCoordinator[Any], + ) -> None: """Initialize the plug switch.""" super().__init__(device, entry, unique_id, coordinator) @@ -228,7 +246,7 @@ class XiaomiAirHumidifier(XiaomiGenericHumidifier, HumidifierEntity): _LOGGER.debug("Setting the target humidity to: %s", target_humidity) if await self._try_command( "Setting target humidity of the miio device failed.", - self._device.set_target_humidity, + self._device.set_target_humidity, # type: ignore[attr-defined] target_humidity, ): self._target_humidity = target_humidity @@ -243,7 +261,7 @@ class XiaomiAirHumidifier(XiaomiGenericHumidifier, HumidifierEntity): _LOGGER.debug("Setting the operation mode to: Auto") if await self._try_command( "Setting operation mode of the miio device to MODE_AUTO failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] AirhumidifierOperationMode.Auto, ): self._mode = AirhumidifierOperationMode.Auto.value @@ -261,7 +279,7 @@ class XiaomiAirHumidifier(XiaomiGenericHumidifier, HumidifierEntity): _LOGGER.debug("Setting the operation mode to: %s", mode) if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] AirhumidifierOperationMode[mode], ): self._mode = mode.lower() @@ -306,7 +324,7 @@ class XiaomiAirHumidifierMiot(XiaomiAirHumidifier): _LOGGER.debug("Setting the humidity to: %s", target_humidity) if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_target_humidity, + self._device.set_target_humidity, # type: ignore[attr-defined] target_humidity, ): self._target_humidity = target_humidity @@ -320,7 +338,7 @@ class XiaomiAirHumidifierMiot(XiaomiAirHumidifier): _LOGGER.debug("Setting the operation mode to: Auto") if await self._try_command( "Setting operation mode of the miio device to MODE_AUTO failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] AirhumidifierMiotOperationMode.Auto, ): self._mode = 0 @@ -339,7 +357,7 @@ class XiaomiAirHumidifierMiot(XiaomiAirHumidifier): if self.is_on: if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.REVERSE_MODE_MAPPING[mode], ): self._mode = self.REVERSE_MODE_MAPPING[mode].value @@ -381,7 +399,7 @@ class XiaomiAirHumidifierMjjsq(XiaomiAirHumidifier): _LOGGER.debug("Setting the humidity to: %s", target_humidity) if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_target_humidity, + self._device.set_target_humidity, # type: ignore[attr-defined] target_humidity, ): self._target_humidity = target_humidity @@ -395,7 +413,7 @@ class XiaomiAirHumidifierMjjsq(XiaomiAirHumidifier): _LOGGER.debug("Setting the operation mode to: Humidity") if await self._try_command( "Setting operation mode of the miio device to MODE_HUMIDITY failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] AirhumidifierMjjsqOperationMode.Humidity, ): self._mode = 3 @@ -411,7 +429,7 @@ class XiaomiAirHumidifierMjjsq(XiaomiAirHumidifier): if self.is_on: if await self._try_command( "Setting operation mode of the miio device failed.", - self._device.set_mode, + self._device.set_mode, # type: ignore[attr-defined] self.MODE_MAPPING[mode], ): self._mode = self.MODE_MAPPING[mode].value diff --git a/homeassistant/components/xiaomi_miio/number.py b/homeassistant/components/xiaomi_miio/number.py index 9863397c82a..2f7066c6fdf 100644 --- a/homeassistant/components/xiaomi_miio/number.py +++ b/homeassistant/components/xiaomi_miio/number.py @@ -4,8 +4,9 @@ from __future__ import annotations import dataclasses from dataclasses import dataclass +from typing import Any -from miio import Device +from miio import Device as MiioDevice from homeassistant.components.number import ( DOMAIN as PLATFORM_DOMAIN, @@ -350,17 +351,19 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): +class XiaomiNumberEntity( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], NumberEntity +): """Representation of a generic Xiaomi attribute selector.""" entity_description: XiaomiMiioNumberDescription def __init__( self, - device: Device, + device: MiioDevice, entry: XiaomiMiioConfigEntry, unique_id: str, - coordinator: DataUpdateCoordinator, + coordinator: DataUpdateCoordinator[Any], description: XiaomiMiioNumberDescription, ) -> None: """Initialize the generic Xiaomi attribute selector.""" @@ -402,7 +405,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the target motor speed.""" return await self._try_command( "Setting the target motor speed of the miio device failed.", - self._device.set_speed, + self._device.set_speed, # type: ignore[attr-defined] motor_speed, ) @@ -410,7 +413,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the favorite level.""" return await self._try_command( "Setting the favorite level of the miio device failed.", - self._device.set_favorite_level, + self._device.set_favorite_level, # type: ignore[attr-defined] level, ) @@ -418,7 +421,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the fan level.""" return await self._try_command( "Setting the fan level of the miio device failed.", - self._device.set_fan_level, + self._device.set_fan_level, # type: ignore[attr-defined] level, ) @@ -426,21 +429,23 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the volume.""" return await self._try_command( "Setting the volume of the miio device failed.", - self._device.set_volume, + self._device.set_volume, # type: ignore[attr-defined] volume, ) async def async_set_oscillation_angle(self, angle: int) -> bool: """Set the volume.""" return await self._try_command( - "Setting angle of the miio device failed.", self._device.set_angle, angle + "Setting angle of the miio device failed.", + self._device.set_angle, # type: ignore[attr-defined] + angle, ) async def async_set_delay_off_countdown(self, delay_off_countdown: int) -> bool: """Set the delay off countdown.""" return await self._try_command( "Setting delay off miio device failed.", - self._device.delay_off, + self._device.delay_off, # type: ignore[attr-defined] delay_off_countdown, ) @@ -448,7 +453,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the led brightness level.""" return await self._try_command( "Setting the led brightness level of the miio device failed.", - self._device.set_led_brightness_level, + self._device.set_led_brightness_level, # type: ignore[attr-defined] level, ) @@ -456,7 +461,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the led brightness level.""" return await self._try_command( "Setting the led brightness level of the miio device failed.", - self._device.set_led_brightness, + self._device.set_led_brightness, # type: ignore[attr-defined] level, ) @@ -464,6 +469,6 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): """Set the target motor speed.""" return await self._try_command( "Setting the favorite rpm of the miio device failed.", - self._device.set_favorite_rpm, + self._device.set_favorite_rpm, # type: ignore[attr-defined] rpm, ) diff --git a/homeassistant/components/xiaomi_miio/select.py b/homeassistant/components/xiaomi_miio/select.py index 734de2c0ff4..6dff7cf8ede 100644 --- a/homeassistant/components/xiaomi_miio/select.py +++ b/homeassistant/components/xiaomi_miio/select.py @@ -4,8 +4,9 @@ from __future__ import annotations from dataclasses import dataclass, field import logging -from typing import NamedTuple +from typing import Any, NamedTuple +from miio import Device as MiioDevice from miio.fan_common import LedBrightness as FanLedBrightness from miio.integrations.airpurifier.dmaker.airfresh_t2017 import ( DisplayOrientation as AirfreshT2017DisplayOrientation, @@ -32,6 +33,7 @@ from homeassistant.components.select import SelectEntity, SelectEntityDescriptio from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import ( CONF_FLOW_TYPE, @@ -87,7 +89,7 @@ class AttributeEnumMapping(NamedTuple): enum_class: type -MODEL_TO_ATTR_MAP: dict[str, list] = { +MODEL_TO_ATTR_MAP: dict[str, list[AttributeEnumMapping]] = { MODEL_AIRFRESH_T2017: [ AttributeEnumMapping(ATTR_DISPLAY_ORIENTATION, AirfreshT2017DisplayOrientation), AttributeEnumMapping(ATTR_PTC_LEVEL, AirfreshT2017PtcLevel), @@ -232,10 +234,21 @@ async def async_setup_entry( ) -class XiaomiSelector(XiaomiCoordinatedMiioEntity, SelectEntity): +class XiaomiSelector( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], SelectEntity +): """Representation of a generic Xiaomi attribute selector.""" - def __init__(self, device, entry, unique_id, coordinator, description): + entity_description: XiaomiMiioSelectDescription + + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioSelectDescription, + ) -> None: """Initialize the generic Xiaomi attribute selector.""" super().__init__(device, entry, unique_id, coordinator) self.entity_description = description @@ -244,9 +257,15 @@ class XiaomiSelector(XiaomiCoordinatedMiioEntity, SelectEntity): class XiaomiGenericSelector(XiaomiSelector): """Representation of a Xiaomi generic selector.""" - entity_description: XiaomiMiioSelectDescription - - def __init__(self, device, entry, unique_id, coordinator, description, enum_class): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioSelectDescription, + enum_class: type, + ) -> None: """Initialize the generic Xiaomi attribute selector.""" super().__init__(device, entry, unique_id, coordinator, description) self._current_attr = enum_class( @@ -257,10 +276,10 @@ class XiaomiGenericSelector(XiaomiSelector): if description.options_map: self._options_map = {} - for key, val in enum_class._member_map_.items(): + for key, val in enum_class._member_map_.items(): # type: ignore[attr-defined] self._options_map[description.options_map[key]] = val else: - self._options_map = enum_class._member_map_ + self._options_map = enum_class._member_map_ # type: ignore[attr-defined] self._reverse_map = {val: key for key, val in self._options_map.items()} self._enum_class = enum_class diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index 4ed09d93734..c0631d66e56 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -5,7 +5,7 @@ from __future__ import annotations from collections.abc import Iterable from dataclasses import dataclass import logging -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from miio import AirQualityMonitor, Device as MiioDevice, DeviceException from miio.gateway.devices import SubDevice @@ -854,12 +854,21 @@ async def async_setup_entry( async_add_entities(entities) -class XiaomiGenericSensor(XiaomiCoordinatedMiioEntity, SensorEntity): +class XiaomiGenericSensor( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], SensorEntity +): """Representation of a Xiaomi generic sensor.""" entity_description: XiaomiMiioSensorDescription - def __init__(self, device, entry, unique_id, coordinator, description): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioSensorDescription, + ) -> None: """Initialize the entity.""" super().__init__(device, entry, unique_id, coordinator) self.entity_description = description diff --git a/homeassistant/components/xiaomi_miio/switch.py b/homeassistant/components/xiaomi_miio/switch.py index ae5dc96075e..6711c45922b 100644 --- a/homeassistant/components/xiaomi_miio/switch.py +++ b/homeassistant/components/xiaomi_miio/switch.py @@ -8,7 +8,13 @@ from functools import partial import logging from typing import Any -from miio import AirConditioningCompanionV3, ChuangmiPlug, DeviceException, PowerStrip +from miio import ( + AirConditioningCompanionV3, + ChuangmiPlug, + Device as MiioDevice, + DeviceException, + PowerStrip, +) from miio.gateway.devices import SubDevice from miio.gateway.devices.switch import Switch from miio.powerstrip import PowerMode @@ -520,12 +526,21 @@ async def async_setup_other_entry( async_add_entities(entities) -class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): +class XiaomiGenericCoordinatedSwitch( + XiaomiCoordinatedMiioEntity[DataUpdateCoordinator[Any]], SwitchEntity +): """Representation of a Xiaomi Plug Generic.""" entity_description: XiaomiMiioSwitchDescription - def __init__(self, device, entry, unique_id, coordinator, description): + def __init__( + self, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str, + coordinator: DataUpdateCoordinator[Any], + description: XiaomiMiioSwitchDescription, + ) -> None: """Initialize the plug switch.""" super().__init__(device, entry, unique_id, coordinator) @@ -574,7 +589,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the buzzer on.""" return await self._try_command( "Turning the buzzer of the miio device on failed.", - self._device.set_buzzer, + self._device.set_buzzer, # type: ignore[attr-defined] True, ) @@ -582,7 +597,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the buzzer off.""" return await self._try_command( "Turning the buzzer of the miio device off failed.", - self._device.set_buzzer, + self._device.set_buzzer, # type: ignore[attr-defined] False, ) @@ -590,7 +605,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the child lock on.""" return await self._try_command( "Turning the child lock of the miio device on failed.", - self._device.set_child_lock, + self._device.set_child_lock, # type: ignore[attr-defined] True, ) @@ -598,7 +613,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the child lock off.""" return await self._try_command( "Turning the child lock of the miio device off failed.", - self._device.set_child_lock, + self._device.set_child_lock, # type: ignore[attr-defined] False, ) @@ -606,7 +621,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the display on.""" return await self._try_command( "Turning the display of the miio device on failed.", - self._device.set_display, + self._device.set_display, # type: ignore[attr-defined] True, ) @@ -614,7 +629,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the display off.""" return await self._try_command( "Turning the display of the miio device off failed.", - self._device.set_display, + self._device.set_display, # type: ignore[attr-defined] False, ) @@ -622,7 +637,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the dry mode on.""" return await self._try_command( "Turning the dry mode of the miio device on failed.", - self._device.set_dry, + self._device.set_dry, # type: ignore[attr-defined] True, ) @@ -630,7 +645,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the dry mode off.""" return await self._try_command( "Turning the dry mode of the miio device off failed.", - self._device.set_dry, + self._device.set_dry, # type: ignore[attr-defined] False, ) @@ -638,7 +653,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the dry mode on.""" return await self._try_command( "Turning the clean mode of the miio device on failed.", - self._device.set_clean_mode, + self._device.set_clean_mode, # type: ignore[attr-defined] True, ) @@ -646,7 +661,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the dry mode off.""" return await self._try_command( "Turning the clean mode of the miio device off failed.", - self._device.set_clean_mode, + self._device.set_clean_mode, # type: ignore[attr-defined] False, ) @@ -654,7 +669,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the led on.""" return await self._try_command( "Turning the led of the miio device on failed.", - self._device.set_led, + self._device.set_led, # type: ignore[attr-defined] True, ) @@ -662,7 +677,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the led off.""" return await self._try_command( "Turning the led of the miio device off failed.", - self._device.set_led, + self._device.set_led, # type: ignore[attr-defined] False, ) @@ -670,7 +685,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the learn mode on.""" return await self._try_command( "Turning the learn mode of the miio device on failed.", - self._device.set_learn_mode, + self._device.set_learn_mode, # type: ignore[attr-defined] True, ) @@ -678,7 +693,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn the learn mode off.""" return await self._try_command( "Turning the learn mode of the miio device off failed.", - self._device.set_learn_mode, + self._device.set_learn_mode, # type: ignore[attr-defined] False, ) @@ -686,7 +701,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn auto detect on.""" return await self._try_command( "Turning auto detect of the miio device on failed.", - self._device.set_auto_detect, + self._device.set_auto_detect, # type: ignore[attr-defined] True, ) @@ -694,7 +709,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn auto detect off.""" return await self._try_command( "Turning auto detect of the miio device off failed.", - self._device.set_auto_detect, + self._device.set_auto_detect, # type: ignore[attr-defined] False, ) @@ -702,7 +717,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer on.""" return await self._try_command( "Turning ionizer of the miio device on failed.", - self._device.set_ionizer, + self._device.set_ionizer, # type: ignore[attr-defined] True, ) @@ -710,7 +725,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer off.""" return await self._try_command( "Turning ionizer of the miio device off failed.", - self._device.set_ionizer, + self._device.set_ionizer, # type: ignore[attr-defined] False, ) @@ -718,7 +733,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer on.""" return await self._try_command( "Turning ionizer of the miio device on failed.", - self._device.set_anion, + self._device.set_anion, # type: ignore[attr-defined] True, ) @@ -726,7 +741,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer off.""" return await self._try_command( "Turning ionizer of the miio device off failed.", - self._device.set_anion, + self._device.set_anion, # type: ignore[attr-defined] False, ) @@ -734,7 +749,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer on.""" return await self._try_command( "Turning ionizer of the miio device on failed.", - self._device.set_ptc, + self._device.set_ptc, # type: ignore[attr-defined] True, ) @@ -742,7 +757,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Turn ionizer off.""" return await self._try_command( "Turning ionizer of the miio device off failed.", - self._device.set_ptc, + self._device.set_ptc, # type: ignore[attr-defined] False, ) diff --git a/homeassistant/components/xiaomi_miio/vacuum.py b/homeassistant/components/xiaomi_miio/vacuum.py index 62343391cf4..ca6ab084324 100644 --- a/homeassistant/components/xiaomi_miio/vacuum.py +++ b/homeassistant/components/xiaomi_miio/vacuum.py @@ -6,7 +6,7 @@ from functools import partial import logging from typing import Any -from miio import DeviceException +from miio import Device as MiioDevice, DeviceException import voluptuous as vol from homeassistant.components.vacuum import ( @@ -196,9 +196,9 @@ class MiroboVacuum( def __init__( self, - device, - entry, - unique_id, + device: MiioDevice, + entry: XiaomiMiioConfigEntry, + unique_id: str | None, coordinator: DataUpdateCoordinator[VacuumCoordinatorData], ) -> None: """Initialize the Xiaomi vacuum cleaner robot handler.""" @@ -281,16 +281,23 @@ class MiroboVacuum( async def async_start(self) -> None: """Start or resume the cleaning task.""" await self._try_command( - "Unable to start the vacuum: %s", self._device.resume_or_start + "Unable to start the vacuum: %s", + self._device.resume_or_start, # type: ignore[attr-defined] ) async def async_pause(self) -> None: """Pause the cleaning task.""" - await self._try_command("Unable to set start/pause: %s", self._device.pause) + await self._try_command( + "Unable to set start/pause: %s", + self._device.pause, # type: ignore[attr-defined] + ) async def async_stop(self, **kwargs: Any) -> None: """Stop the vacuum cleaner.""" - await self._try_command("Unable to stop: %s", self._device.stop) + await self._try_command( + "Unable to stop: %s", + self._device.stop, # type: ignore[attr-defined] + ) async def async_set_fan_speed(self, fan_speed: str, **kwargs: Any) -> None: """Set fan speed.""" @@ -307,22 +314,31 @@ class MiroboVacuum( ) return await self._try_command( - "Unable to set fan speed: %s", self._device.set_fan_speed, fan_speed_int + "Unable to set fan speed: %s", + self._device.set_fan_speed, # type: ignore[attr-defined] + fan_speed_int, ) async def async_return_to_base(self, **kwargs: Any) -> None: """Set the vacuum cleaner to return to the dock.""" - await self._try_command("Unable to return home: %s", self._device.home) + await self._try_command( + "Unable to return home: %s", + self._device.home, # type: ignore[attr-defined] + ) async def async_clean_spot(self, **kwargs: Any) -> None: """Perform a spot clean-up.""" await self._try_command( - "Unable to start the vacuum for a spot clean-up: %s", self._device.spot + "Unable to start the vacuum for a spot clean-up: %s", + self._device.spot, # type: ignore[attr-defined] ) async def async_locate(self, **kwargs: Any) -> None: """Locate the vacuum cleaner.""" - await self._try_command("Unable to locate the botvac: %s", self._device.find) + await self._try_command( + "Unable to locate the botvac: %s", + self._device.find, # type: ignore[attr-defined] + ) async def async_send_command( self, @@ -341,13 +357,15 @@ class MiroboVacuum( async def async_remote_control_start(self) -> None: """Start remote control mode.""" await self._try_command( - "Unable to start remote control the vacuum: %s", self._device.manual_start + "Unable to start remote control the vacuum: %s", + self._device.manual_start, # type: ignore[attr-defined] ) async def async_remote_control_stop(self) -> None: """Stop remote control mode.""" await self._try_command( - "Unable to stop remote control the vacuum: %s", self._device.manual_stop + "Unable to stop remote control the vacuum: %s", + self._device.manual_stop, # type: ignore[attr-defined] ) async def async_remote_control_move( @@ -356,7 +374,7 @@ class MiroboVacuum( """Move vacuum with remote control mode.""" await self._try_command( "Unable to move with remote control the vacuum: %s", - self._device.manual_control, + self._device.manual_control, # type: ignore[attr-defined] velocity=velocity, rotation=rotation, duration=duration, @@ -368,7 +386,7 @@ class MiroboVacuum( """Move vacuum one step with remote control mode.""" await self._try_command( "Unable to remote control the vacuum: %s", - self._device.manual_control_once, + self._device.manual_control_once, # type: ignore[attr-defined] velocity=velocity, rotation=rotation, duration=duration, @@ -378,7 +396,7 @@ class MiroboVacuum( """Goto the specified coordinates.""" await self._try_command( "Unable to send the vacuum cleaner to the specified coordinates: %s", - self._device.goto, + self._device.goto, # type: ignore[attr-defined] x_coord=x_coord, y_coord=y_coord, ) @@ -390,7 +408,7 @@ class MiroboVacuum( await self._try_command( "Unable to start cleaning of the specified segments: %s", - self._device.segment_clean, + self._device.segment_clean, # type: ignore[attr-defined] segments=segments, ) @@ -400,7 +418,10 @@ class MiroboVacuum( _zone.append(repeats) _LOGGER.debug("Zone with repeats: %s", zone) try: - await self.hass.async_add_executor_job(self._device.zoned_clean, zone) + await self.hass.async_add_executor_job( + self._device.zoned_clean, # type: ignore[attr-defined] + zone, + ) await self.coordinator.async_refresh() except (OSError, DeviceException) as exc: _LOGGER.error("Unable to send zoned_clean command to the vacuum: %s", exc)