Use ConfigEntry runtime_data in devolo Home Control (#116672)

This commit is contained in:
Guido Schmitz 2024-05-03 13:55:04 +02:00 committed by GitHub
parent 5274165007
commit cb26e3c633
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 62 additions and 64 deletions

View file

@ -18,19 +18,15 @@ from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.device_registry import DeviceEntry from homeassistant.helpers.device_registry import DeviceEntry
from .const import ( from .const import CONF_MYDEVOLO, DEFAULT_MYDEVOLO, GATEWAY_SERIAL_PATTERN, PLATFORMS
CONF_MYDEVOLO,
DEFAULT_MYDEVOLO, DevoloHomeControlConfigEntry = ConfigEntry[list[HomeControl]]
DOMAIN,
GATEWAY_SERIAL_PATTERN,
PLATFORMS,
)
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.""" """Set up the devolo account from a config entry."""
hass.data.setdefault(DOMAIN, {})
mydevolo = configure_mydevolo(entry.data) mydevolo = configure_mydevolo(entry.data)
credentials_valid = await hass.async_add_executor_job(mydevolo.credentials_valid) 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) uuid = await hass.async_add_executor_job(mydevolo.uuid)
hass.config_entries.async_update_entry(entry, unique_id=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: try:
zeroconf_instance = await zeroconf.async_get_instance(hass) 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: for gateway_id in gateway_ids:
hass.data[DOMAIN][entry.entry_id]["gateways"].append( entry.runtime_data.append(
await hass.async_add_executor_job( await hass.async_add_executor_job(
partial( partial(
HomeControl, 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) 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 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 a config entry."""
unload = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) unload = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
await asyncio.gather( await asyncio.gather(
*( *(
hass.async_add_executor_job(gateway.websocket_disconnect) 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 return unload

View file

@ -9,12 +9,11 @@ from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass, BinarySensorDeviceClass,
BinarySensorEntity, BinarySensorEntity,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_device import DevoloDeviceEntity from .devolo_device import DevoloDeviceEntity
DEVICE_CLASS_MAPPING = { DEVICE_CLASS_MAPPING = {
@ -28,12 +27,14 @@ DEVICE_CLASS_MAPPING = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all binary sensor and multi level sensor devices and setup them via config entry.""" """Get all binary sensor and multi level sensor devices and setup them via config entry."""
entities: list[BinarySensorEntity] = [] entities: list[BinarySensorEntity] = []
for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: for gateway in entry.runtime_data:
entities.extend( entities.extend(
DevoloBinaryDeviceEntity( DevoloBinaryDeviceEntity(
homecontrol=gateway, homecontrol=gateway,

View file

@ -13,17 +13,18 @@ from homeassistant.components.climate import (
ClimateEntityFeature, ClimateEntityFeature,
HVACMode, HVACMode,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS, UnitOfTemperature from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS, UnitOfTemperature
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all cover devices and setup them via config entry.""" """Get all cover devices and setup them via config entry."""
@ -33,7 +34,7 @@ async def async_setup_entry(
device_instance=device, device_instance=device,
element_uid=multi_level_switch, 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 device in gateway.multi_level_switch_devices
for multi_level_switch in device.multi_level_switch_property for multi_level_switch in device.multi_level_switch_property
if device.device_model_uid if device.device_model_uid

View file

@ -9,16 +9,17 @@ from homeassistant.components.cover import (
CoverEntity, CoverEntity,
CoverEntityFeature, CoverEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all cover devices and setup them via config entry.""" """Get all cover devices and setup them via config entry."""
@ -28,7 +29,7 @@ async def async_setup_entry(
device_instance=device, device_instance=device,
element_uid=multi_level_switch, 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 device in gateway.multi_level_switch_devices
for multi_level_switch in device.multi_level_switch_property for multi_level_switch in device.multi_level_switch_property
if multi_level_switch.startswith("devolo.Blinds") if multi_level_switch.startswith("devolo.Blinds")

View file

@ -4,24 +4,19 @@ from __future__ import annotations
from typing import Any from typing import Any
from devolo_home_control_api.homecontrol import HomeControl
from homeassistant.components.diagnostics import async_redact_data from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
TO_REDACT = {CONF_PASSWORD, CONF_USERNAME} TO_REDACT = {CONF_PASSWORD, CONF_USERNAME}
async def async_get_config_entry_diagnostics( async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry hass: HomeAssistant, entry: DevoloHomeControlConfigEntry
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
gateways: list[HomeControl] = hass.data[DOMAIN][entry.entry_id]["gateways"]
device_info = [ device_info = [
{ {
"gateway": { "gateway": {
@ -38,7 +33,7 @@ async def async_get_config_entry_diagnostics(
for device_id, properties in gateway.devices.items() for device_id, properties in gateway.devices.items()
], ],
} }
for gateway in gateways for gateway in entry.runtime_data
] ]
return { return {

View file

@ -8,16 +8,17 @@ from devolo_home_control_api.devices.zwave import Zwave
from devolo_home_control_api.homecontrol import HomeControl from devolo_home_control_api.homecontrol import HomeControl
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all light devices and setup them via config entry.""" """Get all light devices and setup them via config entry."""
@ -27,7 +28,7 @@ async def async_setup_entry(
device_instance=device, device_instance=device,
element_uid=multi_level_switch.element_uid, 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 device in gateway.multi_level_switch_devices
for multi_level_switch in device.multi_level_switch_property.values() for multi_level_switch in device.multi_level_switch_property.values()
if multi_level_switch.switch_type == "dimmer" if multi_level_switch.switch_type == "dimmer"

View file

@ -10,12 +10,11 @@ from homeassistant.components.sensor import (
SensorEntity, SensorEntity,
SensorStateClass, SensorStateClass,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, EntityCategory from homeassistant.const import PERCENTAGE, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_device import DevoloDeviceEntity from .devolo_device import DevoloDeviceEntity
DEVICE_CLASS_MAPPING = { DEVICE_CLASS_MAPPING = {
@ -39,12 +38,14 @@ STATE_CLASS_MAPPING = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all sensor devices and setup them via config entry.""" """Get all sensor devices and setup them via config entry."""
entities: list[SensorEntity] = [] entities: list[SensorEntity] = []
for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"]: for gateway in entry.runtime_data:
entities.extend( entities.extend(
DevoloGenericMultiLevelDeviceEntity( DevoloGenericMultiLevelDeviceEntity(
homecontrol=gateway, homecontrol=gateway,

View file

@ -6,16 +6,17 @@ from devolo_home_control_api.devices.zwave import Zwave
from devolo_home_control_api.homecontrol import HomeControl from devolo_home_control_api.homecontrol import HomeControl
from homeassistant.components.siren import ATTR_TONE, SirenEntity, SirenEntityFeature from homeassistant.components.siren import ATTR_TONE, SirenEntity, SirenEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity from .devolo_multi_level_switch import DevoloMultiLevelSwitchDeviceEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all binary sensor and multi level sensor devices and setup them via config entry.""" """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, device_instance=device,
element_uid=multi_level_switch, 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 device in gateway.multi_level_switch_devices
for multi_level_switch in device.multi_level_switch_property for multi_level_switch in device.multi_level_switch_property
if multi_level_switch.startswith("devolo.SirenMultiLevelSwitch") if multi_level_switch.startswith("devolo.SirenMultiLevelSwitch")

View file

@ -8,16 +8,17 @@ from devolo_home_control_api.devices.zwave import Zwave
from devolo_home_control_api.homecontrol import HomeControl from devolo_home_control_api.homecontrol import HomeControl
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from . import DevoloHomeControlConfigEntry
from .devolo_device import DevoloDeviceEntity from .devolo_device import DevoloDeviceEntity
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant,
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Get all devices and setup the switch devices via config entry.""" """Get all devices and setup the switch devices via config entry."""
@ -27,7 +28,7 @@ async def async_setup_entry(
device_instance=device, device_instance=device,
element_uid=binary_switch, 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 device in gateway.binary_switch_devices
for binary_switch in device.binary_switch_property for binary_switch in device.binary_switch_property
# Exclude the binary switch which also has multi_level_switches here, # Exclude the binary switch which also has multi_level_switches here,

View file

@ -6,7 +6,7 @@ from devolo_home_control_api.exceptions.gateway import GatewayOfflineError
import pytest import pytest
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN 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.config_entries import ConfigEntryState
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant