diff --git a/.strict-typing b/.strict-typing index 09578153163..7d2f83a0e8d 100644 --- a/.strict-typing +++ b/.strict-typing @@ -25,6 +25,7 @@ homeassistant.components.canary.* homeassistant.components.cover.* homeassistant.components.device_automation.* homeassistant.components.device_tracker.* +homeassistant.components.devolo_home_control.* homeassistant.components.dnsip.* homeassistant.components.dsmr.* homeassistant.components.dunehd.* diff --git a/homeassistant/components/devolo_home_control/__init__.py b/homeassistant/components/devolo_home_control/__init__.py index 4c8757e4eff..297d3ac09c9 100644 --- a/homeassistant/components/devolo_home_control/__init__.py +++ b/homeassistant/components/devolo_home_control/__init__.py @@ -1,6 +1,10 @@ """The devolo_home_control integration.""" +from __future__ import annotations + import asyncio from functools import partial +from types import MappingProxyType +from typing import Any from devolo_home_control_api.exceptions.gateway import GatewayOfflineError from devolo_home_control_api.homecontrol import HomeControl @@ -9,7 +13,7 @@ from devolo_home_control_api.mydevolo import Mydevolo from homeassistant.components import zeroconf from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, EVENT_HOMEASSISTANT_STOP -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from .const import ( @@ -37,7 +41,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: gateway_ids = await hass.async_add_executor_job(mydevolo.get_gateway_ids) - if GATEWAY_SERIAL_PATTERN.match(entry.unique_id): + if entry.unique_id and GATEWAY_SERIAL_PATTERN.match(entry.unique_id): uuid = await hass.async_add_executor_job(mydevolo.uuid) hass.config_entries.async_update_entry(entry, unique_id=uuid) @@ -60,7 +64,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.config_entries.async_setup_platforms(entry, PLATFORMS) - def shutdown(event): + def shutdown(event: Event) -> None: for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: gateway.websocket_disconnect( f"websocket disconnect requested by {EVENT_HOMEASSISTANT_STOP}" @@ -88,7 +92,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return unload -def configure_mydevolo(conf: dict) -> Mydevolo: +def configure_mydevolo(conf: dict[str, Any] | MappingProxyType[str, Any]) -> Mydevolo: """Configure mydevolo.""" mydevolo = Mydevolo() mydevolo.user = conf[CONF_USERNAME] diff --git a/homeassistant/components/devolo_home_control/binary_sensor.py b/homeassistant/components/devolo_home_control/binary_sensor.py index e99c96832ae..c8ce1c3585d 100644 --- a/homeassistant/components/devolo_home_control/binary_sensor.py +++ b/homeassistant/components/devolo_home_control/binary_sensor.py @@ -1,4 +1,9 @@ """Platform for binary sensor integration.""" +from __future__ import annotations + +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + from homeassistant.components.binary_sensor import ( DEVICE_CLASS_DOOR, DEVICE_CLASS_HEAT, @@ -11,6 +16,7 @@ from homeassistant.components.binary_sensor import ( ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_device import DevoloDeviceEntity @@ -26,10 +32,10 @@ DEVICE_CLASS_MAPPING = { async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all binary sensor and multi level sensor devices and setup them via config entry.""" - entities = [] + entities: list[BinarySensorEntity] = [] for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: for device in gateway.binary_sensor_devices: @@ -61,7 +67,9 @@ async def async_setup_entry( class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity): """Representation of a binary sensor within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize a devolo binary sensor.""" self._binary_sensor_property = device_instance.binary_sensor_property.get( element_uid @@ -91,12 +99,12 @@ class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity): self._enabled_default = False @property - def is_on(self): + def is_on(self) -> bool: """Return the state.""" - return self._value + return bool(self._value) @property - def device_class(self): + def device_class(self) -> str | None: """Return device class.""" return self._device_class @@ -104,7 +112,13 @@ class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity): class DevoloRemoteControl(DevoloDeviceEntity, BinarySensorEntity): """Representation of a remote control within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid, key): + def __init__( + self, + homecontrol: HomeControl, + device_instance: Zwave, + element_uid: str, + key: int, + ) -> None: """Initialize a devolo remote control.""" self._remote_control_property = device_instance.remote_control_property.get( element_uid @@ -120,11 +134,11 @@ class DevoloRemoteControl(DevoloDeviceEntity, BinarySensorEntity): self._state = False @property - def is_on(self): + def is_on(self) -> bool: """Return the state.""" return self._state - def _sync(self, message): + def _sync(self, message: tuple) -> None: """Update the binary sensor state.""" if ( message[0] == self._remote_control_property.element_uid diff --git a/homeassistant/components/devolo_home_control/climate.py b/homeassistant/components/devolo_home_control/climate.py index 018c9cf36ec..6b890544da5 100644 --- a/homeassistant/components/devolo_home_control/climate.py +++ b/homeassistant/components/devolo_home_control/climate.py @@ -1,6 +1,8 @@ """Platform for climate integration.""" from __future__ import annotations +from typing import Any + from homeassistant.components.climate import ( ATTR_TEMPERATURE, HVAC_MODE_HEAT, @@ -11,13 +13,14 @@ from homeassistant.components.climate import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all cover devices and setup them via config entry.""" entities = [] @@ -82,12 +85,14 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit @property def min_temp(self) -> float: """Return the minimum set temperature value.""" - return self._multi_level_switch_property.min + min_temp: float = self._multi_level_switch_property.min + return min_temp @property def max_temp(self) -> float: """Return the maximum set temperature value.""" - return self._multi_level_switch_property.max + max_temp: float = self._multi_level_switch_property.max + return max_temp @property def precision(self) -> float: @@ -95,7 +100,7 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit return PRECISION_TENTHS @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" return SUPPORT_TARGET_TEMPERATURE @@ -107,6 +112,6 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit def set_hvac_mode(self, hvac_mode: str) -> None: """Do nothing as devolo devices do not support changing the hvac mode.""" - def set_temperature(self, **kwargs): + def set_temperature(self, **kwargs: Any) -> None: """Set new target temperature.""" self._multi_level_switch_property.set(kwargs[ATTR_TEMPERATURE]) diff --git a/homeassistant/components/devolo_home_control/config_flow.py b/homeassistant/components/devolo_home_control/config_flow.py index 10172b94452..e6b3dcbe329 100644 --- a/homeassistant/components/devolo_home_control/config_flow.py +++ b/homeassistant/components/devolo_home_control/config_flow.py @@ -1,9 +1,15 @@ """Config flow to configure the devolo home control integration.""" +from __future__ import annotations + +from typing import Any + import voluptuous as vol from homeassistant import config_entries +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.typing import DiscoveryInfoType from . import configure_mydevolo @@ -16,16 +22,18 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 - def __init__(self): + def __init__(self) -> None: """Initialize devolo Home Control flow.""" self.data_schema = { vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str, } - self._reauth_entry = None + self._reauth_entry: ConfigEntry | None = None self._url = DEFAULT_MYDEVOLO - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initiated by the user.""" if self.show_advanced_options: self.data_schema[vol.Required(CONF_MYDEVOLO, default=self._url)] = str @@ -36,7 +44,9 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): except CredentialsInvalid: return self._show_form(step_id="user", errors={"base": "invalid_auth"}) - async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Handle zeroconf discovery.""" # Check if it is a gateway if discovery_info.get("properties", {}).get("MT") in SUPPORTED_MODEL_TYPES: @@ -44,7 +54,9 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self.async_step_zeroconf_confirm() return self.async_abort(reason="Not a devolo Home Control gateway.") - async def async_step_zeroconf_confirm(self, user_input=None): + async def async_step_zeroconf_confirm( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initiated by zeroconf.""" if user_input is None: return self._show_form(step_id="zeroconf_confirm") @@ -55,7 +67,7 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): step_id="zeroconf_confirm", errors={"base": "invalid_auth"} ) - async def async_step_reauth(self, user_input): + async def async_step_reauth(self, user_input: dict[str, Any]) -> FlowResult: """Handle reauthentication.""" self._reauth_entry = self.hass.config_entries.async_get_entry( self.context["entry_id"] @@ -67,7 +79,9 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): } return await self.async_step_reauth_confirm() - async def async_step_reauth_confirm(self, user_input=None): + async def async_step_reauth_confirm( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initiated by reauthentication.""" if user_input is None: return self._show_form(step_id="reauth_confirm") @@ -82,7 +96,7 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): step_id="reauth_confirm", errors={"base": "reauth_failed"} ) - async def _connect_mydevolo(self, user_input): + async def _connect_mydevolo(self, user_input: dict[str, Any]) -> FlowResult: """Connect to mydevolo.""" user_input[CONF_MYDEVOLO] = user_input.get(CONF_MYDEVOLO, self._url) mydevolo = configure_mydevolo(conf=user_input) @@ -118,7 +132,9 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return self.async_abort(reason="reauth_successful") @callback - def _show_form(self, step_id, errors=None): + def _show_form( + self, step_id: str, errors: dict[str, str] | None = None + ) -> FlowResult: """Show the form to the user.""" return self.async_show_form( step_id=step_id, diff --git a/homeassistant/components/devolo_home_control/cover.py b/homeassistant/components/devolo_home_control/cover.py index d552c53bbfc..b2ea2f66b67 100644 --- a/homeassistant/components/devolo_home_control/cover.py +++ b/homeassistant/components/devolo_home_control/cover.py @@ -1,4 +1,8 @@ """Platform for cover integration.""" +from __future__ import annotations + +from typing import Any + from homeassistant.components.cover import ( DEVICE_CLASS_BLIND, SUPPORT_CLOSE, @@ -8,13 +12,14 @@ from homeassistant.components.cover import ( ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all cover devices and setup them via config entry.""" entities = [] @@ -38,33 +43,33 @@ class DevoloCoverDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, CoverEntity): """Representation of a cover device within devolo Home Control.""" @property - def current_cover_position(self): + def current_cover_position(self) -> int: """Return the current position. 0 is closed. 100 is open.""" return self._value @property - def device_class(self): + def device_class(self) -> str: """Return the class of the device.""" return DEVICE_CLASS_BLIND @property - def is_closed(self): + def is_closed(self) -> bool: """Return if the blind is closed or not.""" return not bool(self._value) @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_SET_POSITION - def open_cover(self, **kwargs): + def open_cover(self, **kwargs: Any) -> None: """Open the blind.""" self._multi_level_switch_property.set(100) - def close_cover(self, **kwargs): + def close_cover(self, **kwargs: Any) -> None: """Close the blind.""" self._multi_level_switch_property.set(0) - def set_cover_position(self, **kwargs): + def set_cover_position(self, **kwargs: Any) -> None: """Set the blind to the given position.""" self._multi_level_switch_property.set(kwargs["position"]) diff --git a/homeassistant/components/devolo_home_control/devolo_device.py b/homeassistant/components/devolo_home_control/devolo_device.py index 6aef842ffff..e8eec3ca7dc 100644 --- a/homeassistant/components/devolo_home_control/devolo_device.py +++ b/homeassistant/components/devolo_home_control/devolo_device.py @@ -1,7 +1,12 @@ """Base class for a device entity integrated in devolo Home Control.""" +from __future__ import annotations + import logging -from homeassistant.helpers.entity import Entity +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + +from homeassistant.helpers.entity import DeviceInfo, Entity from .const import DOMAIN from .subscriber import Subscriber @@ -12,26 +17,30 @@ _LOGGER = logging.getLogger(__name__) class DevoloDeviceEntity(Entity): """Abstract representation of a device within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize a devolo device entity.""" self._device_instance = device_instance self._unique_id = element_uid self._homecontrol = homecontrol - self._name = device_instance.settings_property["general_device_settings"].name + self._name: str = device_instance.settings_property[ + "general_device_settings" + ].name self._area = device_instance.settings_property["general_device_settings"].zone - self._device_class = None - self._value = None - self._unit = None + self._device_class: str | None = None + self._value: int + self._unit = "" self._enabled_default = True # This is not doing I/O. It fetches an internal state of the API - self._available = device_instance.is_online() + self._available: bool = device_instance.is_online() # Get the brand and model information self._brand = device_instance.brand self._model = device_instance.name - self.subscriber = None + self.subscriber: Subscriber | None = None self.sync_callback = self._sync async def async_added_to_hass(self) -> None: @@ -48,12 +57,12 @@ class DevoloDeviceEntity(Entity): ) @property - def unique_id(self): + def unique_id(self) -> str: """Return the unique ID of the entity.""" return self._unique_id @property - def device_info(self): + def device_info(self) -> DeviceInfo: """Return the device info.""" return { "identifiers": {(DOMAIN, self._device_instance.uid)}, @@ -69,12 +78,12 @@ class DevoloDeviceEntity(Entity): return self._enabled_default @property - def should_poll(self): + def should_poll(self) -> bool: """Return the polling state.""" return False @property - def name(self): + def name(self) -> str: """Return the display name of this entity.""" return self._name @@ -83,7 +92,7 @@ class DevoloDeviceEntity(Entity): """Return the online state.""" return self._available - def _sync(self, message): + def _sync(self, message: tuple) -> None: """Update the state.""" if message[0] == self._unique_id: self._value = message[1] @@ -91,7 +100,7 @@ class DevoloDeviceEntity(Entity): self._generic_message(message) self.schedule_update_ha_state() - def _generic_message(self, message): + def _generic_message(self, message: tuple) -> None: """Handle generic messages.""" if len(message) == 3 and message[2] == "battery_level": self._value = message[1] diff --git a/homeassistant/components/devolo_home_control/devolo_multi_level_switch.py b/homeassistant/components/devolo_home_control/devolo_multi_level_switch.py index 482edd51f1e..eafd1e63b1f 100644 --- a/homeassistant/components/devolo_home_control/devolo_multi_level_switch.py +++ b/homeassistant/components/devolo_home_control/devolo_multi_level_switch.py @@ -1,11 +1,16 @@ """Base class for multi level switches in devolo Home Control.""" +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + from .devolo_device import DevoloDeviceEntity class DevoloMultiLevelSwitchDeviceEntity(DevoloDeviceEntity): """Representation of a multi level switch device within devolo Home Control. Something like a dimmer or a thermostat.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize a multi level switch within devolo Home Control.""" super().__init__( homecontrol=homecontrol, diff --git a/homeassistant/components/devolo_home_control/light.py b/homeassistant/components/devolo_home_control/light.py index 7fd59bd7d11..27c637cf114 100644 --- a/homeassistant/components/devolo_home_control/light.py +++ b/homeassistant/components/devolo_home_control/light.py @@ -1,4 +1,11 @@ """Platform for light integration.""" +from __future__ import annotations + +from typing import Any + +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + from homeassistant.components.light import ( ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, @@ -6,13 +13,14 @@ from homeassistant.components.light import ( ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all light devices and setup them via config entry.""" entities = [] @@ -35,7 +43,9 @@ async def async_setup_entry( class DevoloLightDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, LightEntity): """Representation of a light within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize a devolo multi level switch.""" super().__init__( homecontrol=homecontrol, @@ -48,21 +58,21 @@ class DevoloLightDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, LightEntity): ) @property - def brightness(self): + def brightness(self) -> int: """Return the brightness value of the light.""" return round(self._value / 100 * 255) @property - def is_on(self): + def is_on(self) -> bool: """Return the state of the light.""" return bool(self._value) @property - def supported_features(self): + def supported_features(self) -> int: """Return the supported features.""" return SUPPORT_BRIGHTNESS - def turn_on(self, **kwargs) -> None: + def turn_on(self, **kwargs: Any) -> None: """Turn device on.""" if kwargs.get(ATTR_BRIGHTNESS) is not None: self._multi_level_switch_property.set( @@ -76,7 +86,7 @@ class DevoloLightDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, LightEntity): # If there is no binary switch attached to the device, turn it on to 100 %. self._multi_level_switch_property.set(100) - def turn_off(self, **kwargs) -> None: + def turn_off(self, **kwargs: Any) -> None: """Turn device off.""" if self._binary_switch_property is not None: self._binary_switch_property.set(False) diff --git a/homeassistant/components/devolo_home_control/sensor.py b/homeassistant/components/devolo_home_control/sensor.py index e3091305375..3ab449b2c91 100644 --- a/homeassistant/components/devolo_home_control/sensor.py +++ b/homeassistant/components/devolo_home_control/sensor.py @@ -1,4 +1,9 @@ """Platform for sensor integration.""" +from __future__ import annotations + +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + from homeassistant.components.sensor import ( DEVICE_CLASS_BATTERY, DEVICE_CLASS_ENERGY, @@ -12,6 +17,7 @@ from homeassistant.components.sensor import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import PERCENTAGE from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_device import DevoloDeviceEntity @@ -28,10 +34,10 @@ DEVICE_CLASS_MAPPING = { async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all sensor devices and setup them via config entry.""" - entities = [] + entities: list[SensorEntity] = [] for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: for device in gateway.multi_level_sensor_devices: @@ -71,17 +77,17 @@ class DevoloMultiLevelDeviceEntity(DevoloDeviceEntity, SensorEntity): """Abstract representation of a multi level sensor within devolo Home Control.""" @property - def device_class(self) -> str: + def device_class(self) -> str | None: """Return device class.""" return self._device_class @property - def state(self): + def state(self) -> int: """Return the state of the sensor.""" return self._value @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit of measurement of this entity.""" return self._unit @@ -91,10 +97,10 @@ class DevoloGenericMultiLevelDeviceEntity(DevoloMultiLevelDeviceEntity): def __init__( self, - homecontrol, - device_instance, - element_uid, - ): + homecontrol: HomeControl, + device_instance: Zwave, + element_uid: str, + ) -> None: """Initialize a devolo multi level sensor.""" self._multi_level_sensor_property = device_instance.multi_level_sensor_property[ element_uid @@ -123,7 +129,9 @@ class DevoloGenericMultiLevelDeviceEntity(DevoloMultiLevelDeviceEntity): class DevoloBatteryEntity(DevoloMultiLevelDeviceEntity): """Representation of a battery entity within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize a battery sensor.""" super().__init__( @@ -141,7 +149,13 @@ class DevoloBatteryEntity(DevoloMultiLevelDeviceEntity): class DevoloConsumptionEntity(DevoloMultiLevelDeviceEntity): """Representation of a consumption entity within devolo Home Control.""" - def __init__(self, homecontrol, device_instance, element_uid, consumption): + def __init__( + self, + homecontrol: HomeControl, + device_instance: Zwave, + element_uid: str, + consumption: str, + ) -> None: """Initialize a devolo consumption sensor.""" super().__init__( @@ -163,11 +177,11 @@ class DevoloConsumptionEntity(DevoloMultiLevelDeviceEntity): self._name += f" {consumption}" @property - def unique_id(self): + def unique_id(self) -> str: """Return the unique ID of the entity.""" return f"{self._unique_id}_{self._sensor_type}" - def _sync(self, message): + def _sync(self, message: tuple) -> None: """Update the consumption sensor state.""" if message[0] == self._unique_id: self._value = getattr( diff --git a/homeassistant/components/devolo_home_control/subscriber.py b/homeassistant/components/devolo_home_control/subscriber.py index d291e4b174f..9899aa3a587 100644 --- a/homeassistant/components/devolo_home_control/subscriber.py +++ b/homeassistant/components/devolo_home_control/subscriber.py @@ -1,6 +1,7 @@ """Subscriber for devolo home control API publisher.""" import logging +from typing import Callable _LOGGER = logging.getLogger(__name__) @@ -8,12 +9,12 @@ _LOGGER = logging.getLogger(__name__) class Subscriber: """Subscriber class for the publisher in mprm websocket class.""" - def __init__(self, name, callback): + def __init__(self, name: str, callback: Callable) -> None: """Initiate the subscriber.""" self.name = name self.callback = callback - def update(self, message): + def update(self, message: str) -> None: """Trigger hass to update the device.""" _LOGGER.debug('%s got message "%s"', self.name, message) self.callback(message) diff --git a/homeassistant/components/devolo_home_control/switch.py b/homeassistant/components/devolo_home_control/switch.py index 2a96198826b..dcfa22db692 100644 --- a/homeassistant/components/devolo_home_control/switch.py +++ b/homeassistant/components/devolo_home_control/switch.py @@ -1,14 +1,22 @@ """Platform for switch integration.""" +from __future__ import annotations + +from typing import Any + +from devolo_home_control_api.devices.zwave import Zwave +from devolo_home_control_api.homecontrol import HomeControl + from homeassistant.components.switch import SwitchEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .devolo_device import DevoloDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Get all devices and setup the switch devices via config entry.""" entities = [] @@ -33,7 +41,9 @@ async def async_setup_entry( class DevoloSwitch(DevoloDeviceEntity, SwitchEntity): """Representation of a switch.""" - def __init__(self, homecontrol, device_instance, element_uid): + def __init__( + self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str + ) -> None: """Initialize an devolo Switch.""" super().__init__( homecontrol=homecontrol, @@ -43,7 +53,8 @@ class DevoloSwitch(DevoloDeviceEntity, SwitchEntity): self._binary_switch_property = self._device_instance.binary_switch_property.get( self._unique_id ) - self._is_on = self._binary_switch_property.state + self._is_on: bool = self._binary_switch_property.state + self._consumption: float | None if hasattr(self._device_instance, "consumption_property"): self._consumption = self._device_instance.consumption_property.get( @@ -53,26 +64,26 @@ class DevoloSwitch(DevoloDeviceEntity, SwitchEntity): self._consumption = None @property - def is_on(self): + def is_on(self) -> bool: """Return the state.""" return self._is_on @property - def current_power_w(self): + def current_power_w(self) -> float | None: """Return the current consumption.""" return self._consumption - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Switch on the device.""" self._is_on = True self._binary_switch_property.set(state=True) - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Switch off the device.""" self._is_on = False self._binary_switch_property.set(state=False) - def _sync(self, message): + def _sync(self, message: tuple) -> None: """Update the binary switch state and consumption.""" if message[0].startswith("devolo.BinarySwitch"): self._is_on = self._device_instance.binary_switch_property[message[0]].state diff --git a/mypy.ini b/mypy.ini index 5f2eeb11c7d..09869a5b5fe 100644 --- a/mypy.ini +++ b/mypy.ini @@ -286,6 +286,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.devolo_home_control.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +no_implicit_optional = true +warn_return_any = true +warn_unreachable = true + [mypy-homeassistant.components.dnsip.*] check_untyped_defs = true disallow_incomplete_defs = true @@ -1063,9 +1074,6 @@ ignore_errors = true [mypy-homeassistant.components.denonavr.*] ignore_errors = true -[mypy-homeassistant.components.devolo_home_control.*] -ignore_errors = true - [mypy-homeassistant.components.dhcp.*] ignore_errors = true diff --git a/script/hassfest/mypy_config.py b/script/hassfest/mypy_config.py index e59a59de7c9..c63033dacc8 100644 --- a/script/hassfest/mypy_config.py +++ b/script/hassfest/mypy_config.py @@ -42,7 +42,6 @@ IGNORED_MODULES: Final[list[str]] = [ "homeassistant.components.deconz.*", "homeassistant.components.demo.*", "homeassistant.components.denonavr.*", - "homeassistant.components.devolo_home_control.*", "homeassistant.components.dhcp.*", "homeassistant.components.directv.*", "homeassistant.components.doorbird.*",