diff --git a/homeassistant/components/devolo_home_control/__init__.py b/homeassistant/components/devolo_home_control/__init__.py index 78e536209d1..cbdc02e44c8 100644 --- a/homeassistant/components/devolo_home_control/__init__.py +++ b/homeassistant/components/devolo_home_control/__init__.py @@ -18,19 +18,15 @@ from homeassistant.core import Event, HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers.device_registry import DeviceEntry -from .const import ( - CONF_MYDEVOLO, - DEFAULT_MYDEVOLO, - DOMAIN, - GATEWAY_SERIAL_PATTERN, - PLATFORMS, -) +from .const import CONF_MYDEVOLO, DEFAULT_MYDEVOLO, GATEWAY_SERIAL_PATTERN, PLATFORMS + +DevoloHomeControlConfigEntry = ConfigEntry[list[HomeControl]] -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_setup_entry( + hass: HomeAssistant, entry: DevoloHomeControlConfigEntry +) -> bool: """Set up the devolo account from a config entry.""" - hass.data.setdefault(DOMAIN, {}) - mydevolo = configure_mydevolo(entry.data) credentials_valid = await hass.async_add_executor_job(mydevolo.credentials_valid) @@ -47,11 +43,22 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: uuid = await hass.async_add_executor_job(mydevolo.uuid) hass.config_entries.async_update_entry(entry, unique_id=uuid) + def shutdown(event: Event) -> None: + for gateway in entry.runtime_data: + gateway.websocket_disconnect( + f"websocket disconnect requested by {EVENT_HOMEASSISTANT_STOP}" + ) + + # Listen when EVENT_HOMEASSISTANT_STOP is fired + entry.async_on_unload( + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, shutdown) + ) + try: zeroconf_instance = await zeroconf.async_get_instance(hass) - hass.data[DOMAIN][entry.entry_id] = {"gateways": [], "listener": None} + entry.runtime_data = [] for gateway_id in gateway_ids: - hass.data[DOMAIN][entry.entry_id]["gateways"].append( + entry.runtime_data.append( await hass.async_add_executor_job( partial( HomeControl, @@ -66,31 +73,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - 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}" - ) - - # Listen when EVENT_HOMEASSISTANT_STOP is fired - hass.data[DOMAIN][entry.entry_id]["listener"] = hass.bus.async_listen_once( - EVENT_HOMEASSISTANT_STOP, shutdown - ) - return True -async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_unload_entry( + hass: HomeAssistant, entry: DevoloHomeControlConfigEntry +) -> bool: """Unload a config entry.""" unload = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) await asyncio.gather( *( hass.async_add_executor_job(gateway.websocket_disconnect) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data ) ) - hass.data[DOMAIN][entry.entry_id]["listener"]() - hass.data[DOMAIN].pop(entry.entry_id) return unload diff --git a/homeassistant/components/devolo_home_control/binary_sensor.py b/homeassistant/components/devolo_home_control/binary_sensor.py index 43793a15368..349780304c6 100644 --- a/homeassistant/components/devolo_home_control/binary_sensor.py +++ b/homeassistant/components/devolo_home_control/binary_sensor.py @@ -9,12 +9,11 @@ from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_device import DevoloDeviceEntity DEVICE_CLASS_MAPPING = { @@ -28,12 +27,14 @@ DEVICE_CLASS_MAPPING = { async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all binary sensor and multi level sensor devices and setup them via config entry.""" entities: list[BinarySensorEntity] = [] - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: + for gateway in entry.runtime_data: entities.extend( DevoloBinaryDeviceEntity( homecontrol=gateway, diff --git a/homeassistant/components/devolo_home_control/climate.py b/homeassistant/components/devolo_home_control/climate.py index f94c7dae15a..29177ae2437 100644 --- a/homeassistant/components/devolo_home_control/climate.py +++ b/homeassistant/components/devolo_home_control/climate.py @@ -13,17 +13,18 @@ from homeassistant.components.climate import ( ClimateEntityFeature, HVACMode, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS, UnitOfTemperature from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all cover devices and setup them via config entry.""" @@ -33,7 +34,7 @@ async def async_setup_entry( device_instance=device, element_uid=multi_level_switch, ) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data for device in gateway.multi_level_switch_devices for multi_level_switch in device.multi_level_switch_property if device.device_model_uid diff --git a/homeassistant/components/devolo_home_control/cover.py b/homeassistant/components/devolo_home_control/cover.py index 03aec622645..f49a9d0f0be 100644 --- a/homeassistant/components/devolo_home_control/cover.py +++ b/homeassistant/components/devolo_home_control/cover.py @@ -9,16 +9,17 @@ from homeassistant.components.cover import ( CoverEntity, CoverEntityFeature, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all cover devices and setup them via config entry.""" @@ -28,7 +29,7 @@ async def async_setup_entry( device_instance=device, element_uid=multi_level_switch, ) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data for device in gateway.multi_level_switch_devices for multi_level_switch in device.multi_level_switch_property if multi_level_switch.startswith("devolo.Blinds") diff --git a/homeassistant/components/devolo_home_control/diagnostics.py b/homeassistant/components/devolo_home_control/diagnostics.py index 33652f8e0bc..1ce65d90fd6 100644 --- a/homeassistant/components/devolo_home_control/diagnostics.py +++ b/homeassistant/components/devolo_home_control/diagnostics.py @@ -4,24 +4,19 @@ from __future__ import annotations from typing import Any -from devolo_home_control_api.homecontrol import HomeControl - from homeassistant.components.diagnostics import async_redact_data -from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry TO_REDACT = {CONF_PASSWORD, CONF_USERNAME} async def async_get_config_entry_diagnostics( - hass: HomeAssistant, entry: ConfigEntry + hass: HomeAssistant, entry: DevoloHomeControlConfigEntry ) -> dict[str, Any]: """Return diagnostics for a config entry.""" - gateways: list[HomeControl] = hass.data[DOMAIN][entry.entry_id]["gateways"] - device_info = [ { "gateway": { @@ -38,7 +33,7 @@ async def async_get_config_entry_diagnostics( for device_id, properties in gateway.devices.items() ], } - for gateway in gateways + for gateway in entry.runtime_data ] return { diff --git a/homeassistant/components/devolo_home_control/light.py b/homeassistant/components/devolo_home_control/light.py index 36c72ca7f57..c855574b83a 100644 --- a/homeassistant/components/devolo_home_control/light.py +++ b/homeassistant/components/devolo_home_control/light.py @@ -8,16 +8,17 @@ from devolo_home_control_api.devices.zwave import Zwave from devolo_home_control_api.homecontrol import HomeControl from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all light devices and setup them via config entry.""" @@ -27,7 +28,7 @@ async def async_setup_entry( device_instance=device, element_uid=multi_level_switch.element_uid, ) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data for device in gateway.multi_level_switch_devices for multi_level_switch in device.multi_level_switch_property.values() if multi_level_switch.switch_type == "dimmer" diff --git a/homeassistant/components/devolo_home_control/sensor.py b/homeassistant/components/devolo_home_control/sensor.py index db630cf3532..134e45a137e 100644 --- a/homeassistant/components/devolo_home_control/sensor.py +++ b/homeassistant/components/devolo_home_control/sensor.py @@ -10,12 +10,11 @@ from homeassistant.components.sensor import ( SensorEntity, SensorStateClass, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import PERCENTAGE, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_device import DevoloDeviceEntity DEVICE_CLASS_MAPPING = { @@ -39,12 +38,14 @@ STATE_CLASS_MAPPING = { async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all sensor devices and setup them via config entry.""" entities: list[SensorEntity] = [] - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: + for gateway in entry.runtime_data: entities.extend( DevoloGenericMultiLevelDeviceEntity( homecontrol=gateway, diff --git a/homeassistant/components/devolo_home_control/siren.py b/homeassistant/components/devolo_home_control/siren.py index fd015860bbb..e896f4d3ed8 100644 --- a/homeassistant/components/devolo_home_control/siren.py +++ b/homeassistant/components/devolo_home_control/siren.py @@ -6,16 +6,17 @@ from devolo_home_control_api.devices.zwave import Zwave from devolo_home_control_api.homecontrol import HomeControl from homeassistant.components.siren import ATTR_TONE, SirenEntity, SirenEntityFeature -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import DevoloHomeControlConfigEntry from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all binary sensor and multi level sensor devices and setup them via config entry.""" @@ -25,7 +26,7 @@ async def async_setup_entry( device_instance=device, element_uid=multi_level_switch, ) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data for device in gateway.multi_level_switch_devices for multi_level_switch in device.multi_level_switch_property if multi_level_switch.startswith("devolo.SirenMultiLevelSwitch") diff --git a/homeassistant/components/devolo_home_control/switch.py b/homeassistant/components/devolo_home_control/switch.py index f599d39d0b6..dd3248be315 100644 --- a/homeassistant/components/devolo_home_control/switch.py +++ b/homeassistant/components/devolo_home_control/switch.py @@ -8,16 +8,17 @@ 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 . import DevoloHomeControlConfigEntry from .devolo_device import DevoloDeviceEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: DevoloHomeControlConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Get all devices and setup the switch devices via config entry.""" @@ -27,7 +28,7 @@ async def async_setup_entry( device_instance=device, element_uid=binary_switch, ) - for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] + for gateway in entry.runtime_data for device in gateway.binary_switch_devices for binary_switch in device.binary_switch_property # Exclude the binary switch which also has multi_level_switches here, diff --git a/tests/components/devolo_home_control/test_init.py b/tests/components/devolo_home_control/test_init.py index a6fa89231c2..9c3b1668991 100644 --- a/tests/components/devolo_home_control/test_init.py +++ b/tests/components/devolo_home_control/test_init.py @@ -6,7 +6,7 @@ from devolo_home_control_api.exceptions.gateway import GatewayOfflineError import pytest from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN -from homeassistant.components.devolo_home_control import DOMAIN +from homeassistant.components.devolo_home_control.const import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import HomeAssistant