Use runtime_data in xiaomi_miio (#145517)

* Use runtime_data in xiaomi_miio

* Reduce changes
This commit is contained in:
epenet 2025-05-23 17:03:33 +02:00 committed by GitHub
parent 086e97821f
commit 83ec45e4fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 161 additions and 155 deletions

View File

@ -35,7 +35,6 @@ from miio import (
) )
from miio.gateway.gateway import GatewayException from miio.gateway.gateway import GatewayException
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MODEL, CONF_TOKEN, Platform from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MODEL, CONF_TOKEN, Platform
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
@ -47,8 +46,6 @@ from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
CONF_GATEWAY, CONF_GATEWAY,
DOMAIN, DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_FAN_1C, MODEL_FAN_1C,
@ -75,6 +72,7 @@ from .const import (
SetupException, SetupException,
) )
from .gateway import ConnectXiaomiGateway from .gateway import ConnectXiaomiGateway
from .typing import XiaomiMiioConfigEntry, XiaomiMiioRuntimeData
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -125,9 +123,8 @@ MODEL_TO_CLASS_MAP = {
} }
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: XiaomiMiioConfigEntry) -> bool:
"""Set up the Xiaomi Miio components from a config entry.""" """Set up the Xiaomi Miio components from a config entry."""
hass.data.setdefault(DOMAIN, {})
if entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY: if entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
await async_setup_gateway_entry(hass, entry) await async_setup_gateway_entry(hass, entry)
return True return True
@ -291,14 +288,13 @@ def _async_update_data_vacuum(
async def async_create_miio_device_and_coordinator( async def async_create_miio_device_and_coordinator(
hass: HomeAssistant, entry: ConfigEntry hass: HomeAssistant, entry: XiaomiMiioConfigEntry
) -> None: ) -> None:
"""Set up a data coordinator and one miio device to service multiple entities.""" """Set up a data coordinator and one miio device to service multiple entities."""
model: str = entry.data[CONF_MODEL] model: str = entry.data[CONF_MODEL]
host = entry.data[CONF_HOST] host = entry.data[CONF_HOST]
token = entry.data[CONF_TOKEN] token = entry.data[CONF_TOKEN]
name = entry.title name = entry.title
device: MiioDevice | None = None
migrate = False migrate = False
update_method = _async_update_data_default update_method = _async_update_data_default
coordinator_class: type[DataUpdateCoordinator[Any]] = DataUpdateCoordinator coordinator_class: type[DataUpdateCoordinator[Any]] = DataUpdateCoordinator
@ -323,6 +319,7 @@ async def async_create_miio_device_and_coordinator(
_LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5])
device: MiioDevice
# Humidifiers # Humidifiers
if model in MODELS_HUMIDIFIER_MIOT: if model in MODELS_HUMIDIFIER_MIOT:
device = AirHumidifierMiot(host, token, lazy_discover=lazy_discover) device = AirHumidifierMiot(host, token, lazy_discover=lazy_discover)
@ -394,16 +391,18 @@ async def async_create_miio_device_and_coordinator(
# Polling interval. Will only be polled if there are subscribers. # Polling interval. Will only be polled if there are subscribers.
update_interval=UPDATE_INTERVAL, update_interval=UPDATE_INTERVAL,
) )
hass.data[DOMAIN][entry.entry_id] = {
KEY_DEVICE: device,
KEY_COORDINATOR: coordinator,
}
# Trigger first data fetch # Trigger first data fetch
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
entry.runtime_data = XiaomiMiioRuntimeData(
device=device, device_coordinator=coordinator
)
async def async_setup_gateway_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_setup_gateway_entry(
hass: HomeAssistant, entry: XiaomiMiioConfigEntry
) -> None:
"""Set up the Xiaomi Gateway component from a config entry.""" """Set up the Xiaomi Gateway component from a config entry."""
host = entry.data[CONF_HOST] host = entry.data[CONF_HOST]
token = entry.data[CONF_TOKEN] token = entry.data[CONF_TOKEN]
@ -461,17 +460,18 @@ async def async_setup_gateway_entry(hass: HomeAssistant, entry: ConfigEntry) ->
update_interval=UPDATE_INTERVAL, update_interval=UPDATE_INTERVAL,
) )
hass.data[DOMAIN][entry.entry_id] = { entry.runtime_data = XiaomiMiioRuntimeData(
CONF_GATEWAY: gateway.gateway_device, gateway=gateway.gateway_device, gateway_coordinators=coordinator_dict
KEY_COORDINATOR: coordinator_dict, )
}
await hass.config_entries.async_forward_entry_setups(entry, GATEWAY_PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, GATEWAY_PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener)) entry.async_on_unload(entry.add_update_listener(update_listener))
async def async_setup_device_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_device_entry(
hass: HomeAssistant, entry: XiaomiMiioConfigEntry
) -> bool:
"""Set up the Xiaomi Miio device component from a config entry.""" """Set up the Xiaomi Miio device component from a config entry."""
platforms = get_platforms(entry) platforms = get_platforms(entry)
await async_create_miio_device_and_coordinator(hass, entry) await async_create_miio_device_and_coordinator(hass, entry)
@ -486,20 +486,17 @@ async def async_setup_device_entry(hass: HomeAssistant, entry: ConfigEntry) -> b
return True return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: async def async_unload_entry(
hass: HomeAssistant, config_entry: XiaomiMiioConfigEntry
) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
platforms = get_platforms(config_entry) platforms = get_platforms(config_entry)
unload_ok = await hass.config_entries.async_unload_platforms( return await hass.config_entries.async_unload_platforms(config_entry, platforms)
config_entry, platforms
)
if unload_ok:
hass.data[DOMAIN].pop(config_entry.entry_id)
return unload_ok
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> None: async def update_listener(
hass: HomeAssistant, config_entry: XiaomiMiioConfigEntry
) -> None:
"""Handle options update.""" """Handle options update."""
await hass.config_entries.async_reload(config_entry.entry_id) await hass.config_entries.async_reload(config_entry.entry_id)

View File

@ -6,7 +6,6 @@ import logging
from miio import AirQualityMonitor, AirQualityMonitorCGDN1, DeviceException from miio import AirQualityMonitor, AirQualityMonitorCGDN1, DeviceException
from homeassistant.components.air_quality import AirQualityEntity from homeassistant.components.air_quality import AirQualityEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MODEL, CONF_TOKEN from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MODEL, CONF_TOKEN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@ -19,6 +18,7 @@ from .const import (
MODEL_AIRQUALITYMONITOR_V1, MODEL_AIRQUALITYMONITOR_V1,
) )
from .entity import XiaomiMiioEntity from .entity import XiaomiMiioEntity
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -241,7 +241,7 @@ DEVICE_MAP: dict[str, dict[str, Callable]] = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi Air Quality from a config entry.""" """Set up the Xiaomi Air Quality from a config entry."""

View File

@ -12,12 +12,12 @@ from homeassistant.components.alarm_control_panel import (
AlarmControlPanelEntityFeature, AlarmControlPanelEntityFeature,
AlarmControlPanelState, AlarmControlPanelState,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import CONF_GATEWAY, DOMAIN from .const import DOMAIN
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -28,12 +28,12 @@ XIAOMI_STATE_ARMING_VALUE = "oning"
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi Gateway Alarm from a config entry.""" """Set up the Xiaomi Gateway Alarm from a config entry."""
entities = [] entities = []
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY] gateway = config_entry.runtime_data.gateway
entity = XiaomiGatewayAlarm( entity = XiaomiGatewayAlarm(
gateway, gateway,
f"{config_entry.title} Alarm", f"{config_entry.title} Alarm",

View File

@ -5,13 +5,13 @@ from __future__ import annotations
from collections.abc import Callable, Iterable from collections.abc import Callable, Iterable
from dataclasses import dataclass from dataclasses import dataclass
import logging import logging
from typing import TYPE_CHECKING
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass, BinarySensorDeviceClass,
BinarySensorEntity, BinarySensorEntity,
BinarySensorEntityDescription, BinarySensorEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@ -19,9 +19,6 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import VacuumCoordinatorDataAttributes from . import VacuumCoordinatorDataAttributes
from .const import ( from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_FAN_ZA5, MODEL_FAN_ZA5,
@ -33,6 +30,7 @@ from .const import (
MODELS_VACUUM_WITH_SEPARATE_MOP, MODELS_VACUUM_WITH_SEPARATE_MOP,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -133,13 +131,17 @@ HUMIDIFIER_MIOT_BINARY_SENSORS = (ATTR_WATER_TANK_DETACHED,)
HUMIDIFIER_MJJSQ_BINARY_SENSORS = (ATTR_NO_WATER, ATTR_WATER_TANK_DETACHED) HUMIDIFIER_MJJSQ_BINARY_SENSORS = (ATTR_NO_WATER, ATTR_WATER_TANK_DETACHED)
def _setup_vacuum_sensors(hass, config_entry, async_add_entities): def _setup_vacuum_sensors(
hass: HomeAssistant,
config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Only vacuums with mop should have binary sensor registered.""" """Only vacuums with mop should have binary sensor registered."""
if config_entry.data[CONF_MODEL] not in MODELS_VACUUM_WITH_MOP: if config_entry.data[CONF_MODEL] not in MODELS_VACUUM_WITH_MOP:
return return
device = hass.data[DOMAIN][config_entry.entry_id].get(KEY_DEVICE) device = config_entry.runtime_data.device
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] coordinator = config_entry.runtime_data.device_coordinator
entities = [] entities = []
sensors = VACUUM_SENSORS sensors = VACUUM_SENSORS
@ -147,6 +149,8 @@ def _setup_vacuum_sensors(hass, config_entry, async_add_entities):
sensors = VACUUM_SENSORS_SEPARATE_MOP sensors = VACUUM_SENSORS_SEPARATE_MOP
for sensor, description in sensors.items(): for sensor, description in sensors.items():
if TYPE_CHECKING:
assert description.parent_key is not None
parent_key_data = getattr(coordinator.data, description.parent_key) parent_key_data = getattr(coordinator.data, description.parent_key)
if getattr(parent_key_data, description.key, None) is None: if getattr(parent_key_data, description.key, None) is None:
_LOGGER.debug( _LOGGER.debug(
@ -170,7 +174,7 @@ def _setup_vacuum_sensors(hass, config_entry, async_add_entities):
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi sensor from a config entry.""" """Set up the Xiaomi sensor from a config entry."""
@ -198,10 +202,10 @@ async def async_setup_entry(
continue continue
entities.append( entities.append(
XiaomiGenericBinarySensor( XiaomiGenericBinarySensor(
hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE], config_entry.runtime_data.device,
config_entry, config_entry,
f"{description.key}_{config_entry.unique_id}", f"{description.key}_{config_entry.unique_id}",
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], config_entry.runtime_data.device_coordinator,
description, description,
) )
) )

View File

@ -11,20 +11,13 @@ from homeassistant.components.button import (
ButtonEntity, ButtonEntity,
ButtonEntityDescription, ButtonEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_MODEL, EntityCategory from homeassistant.const import CONF_MODEL, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import ( from .const import MODEL_AIRFRESH_A1, MODEL_AIRFRESH_T2017, MODELS_VACUUM
DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017,
MODELS_VACUUM,
)
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
# Fans # Fans
ATTR_RESET_DUST_FILTER = "reset_dust_filter" ATTR_RESET_DUST_FILTER = "reset_dust_filter"
@ -123,7 +116,7 @@ MODEL_TO_BUTTON_MAP: dict[str, tuple[str, ...]] = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the button from a config entry.""" """Set up the button from a config entry."""
@ -135,8 +128,8 @@ async def async_setup_entry(
entities = [] entities = []
buttons = MODEL_TO_BUTTON_MAP[model] buttons = MODEL_TO_BUTTON_MAP[model]
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] device = config_entry.runtime_data.device
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] coordinator = config_entry.runtime_data.device_coordinator
for description in BUTTON_TYPES: for description in BUTTON_TYPES:
if description.key not in buttons: if description.key not in buttons:

View File

@ -11,12 +11,7 @@ from micloud import MiCloud
from micloud.micloudexception import MiCloudAccessDenied from micloud.micloudexception import MiCloudAccessDenied
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ( from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
ConfigEntry,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MAC, CONF_MODEL, CONF_TOKEN from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MAC, CONF_MODEL, CONF_TOKEN
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.device_registry import format_mac from homeassistant.helpers.device_registry import format_mac
@ -40,6 +35,7 @@ from .const import (
SetupException, SetupException,
) )
from .device import ConnectXiaomiDevice from .device import ConnectXiaomiDevice
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -116,7 +112,9 @@ class XiaomiMiioFlowHandler(ConfigFlow, domain=DOMAIN):
@staticmethod @staticmethod
@callback @callback
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlowHandler: def async_get_options_flow(
config_entry: XiaomiMiioConfigEntry,
) -> OptionsFlowHandler:
"""Get the options flow.""" """Get the options flow."""
return OptionsFlowHandler() return OptionsFlowHandler()

View File

@ -27,9 +27,6 @@ CONF_MANUAL = "manual"
# Options flow # Options flow
CONF_CLOUD_SUBDEVICES = "cloud_subdevices" CONF_CLOUD_SUBDEVICES = "cloud_subdevices"
# Keys
KEY_COORDINATOR = "coordinator"
KEY_DEVICE = "device"
# Attributes # Attributes
ATTR_AVAILABLE = "available" ATTR_AVAILABLE = "available"

View File

@ -5,11 +5,11 @@ from __future__ import annotations
from typing import Any from typing import Any
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_DEVICE, CONF_MAC, CONF_TOKEN, CONF_UNIQUE_ID
from homeassistant.const import CONF_MAC, CONF_TOKEN, CONF_UNIQUE_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .const import CONF_CLOUD_PASSWORD, CONF_CLOUD_USERNAME, DOMAIN, KEY_COORDINATOR from .const import CONF_CLOUD_PASSWORD, CONF_CLOUD_USERNAME, CONF_FLOW_TYPE
from .typing import XiaomiMiioConfigEntry
TO_REDACT = { TO_REDACT = {
CONF_CLOUD_PASSWORD, CONF_CLOUD_PASSWORD,
@ -21,18 +21,17 @@ TO_REDACT = {
async def async_get_config_entry_diagnostics( async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry hass: HomeAssistant, config_entry: XiaomiMiioConfigEntry
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
diagnostics_data: dict[str, Any] = { diagnostics_data: dict[str, Any] = {
"config_entry": async_redact_data(config_entry.as_dict(), TO_REDACT) "config_entry": async_redact_data(config_entry.as_dict(), TO_REDACT)
} }
# not every device uses DataUpdateCoordinator if config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE:
if coordinator := hass.data[DOMAIN][config_entry.entry_id].get(KEY_COORDINATOR): coordinator = config_entry.runtime_data.device_coordinator
if isinstance(coordinator.data, dict): if isinstance(coordinator.data, dict):
diagnostics_data["coordinator_data"] = coordinator.data diagnostics_data["coordinator_data"] = coordinator.data
else: else:
diagnostics_data["coordinator_data"] = repr(coordinator.data) diagnostics_data["coordinator_data"] = repr(coordinator.data)
return diagnostics_data return diagnostics_data

View File

@ -30,7 +30,6 @@ from miio.integrations.fan.zhimi.zhimi_miot import (
import voluptuous as vol import voluptuous as vol
from homeassistant.components.fan import FanEntity, FanEntityFeature from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICE, CONF_MODEL from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICE, CONF_MODEL
from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
@ -64,8 +63,6 @@ from .const import (
FEATURE_FLAGS_FAN_ZA5, FEATURE_FLAGS_FAN_ZA5,
FEATURE_RESET_FILTER, FEATURE_RESET_FILTER,
FEATURE_SET_EXTRA_FEATURES, FEATURE_SET_EXTRA_FEATURES,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_AIRPURIFIER_2H, MODEL_AIRPURIFIER_2H,
@ -94,7 +91,7 @@ from .const import (
SERVICE_SET_EXTRA_FEATURES, SERVICE_SET_EXTRA_FEATURES,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import ServiceMethodDetails from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -204,7 +201,7 @@ FAN_DIRECTIONS_MAP = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Fan from a config entry.""" """Set up the Fan from a config entry."""
@ -218,8 +215,8 @@ async def async_setup_entry(
model = config_entry.data[CONF_MODEL] model = config_entry.data[CONF_MODEL]
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] device = config_entry.runtime_data.device
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] coordinator = config_entry.runtime_data.device_coordinator
if model in (MODEL_AIRPURIFIER_3C, MODEL_AIRPURIFIER_3C_REV_A): if model in (MODEL_AIRPURIFIER_3C, MODEL_AIRPURIFIER_3C_REV_A):
entity = XiaomiAirPurifierMB4( entity = XiaomiAirPurifierMB4(

View File

@ -20,7 +20,6 @@ from homeassistant.components.humidifier import (
HumidifierEntity, HumidifierEntity,
HumidifierEntityFeature, HumidifierEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_MODE, CONF_DEVICE, CONF_MODEL from homeassistant.const import ATTR_MODE, CONF_DEVICE, CONF_MODEL
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@ -28,9 +27,6 @@ from homeassistant.util.percentage import percentage_to_ranged_value
from .const import ( from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CA1,
MODEL_AIRHUMIDIFIER_CA4, MODEL_AIRHUMIDIFIER_CA4,
MODEL_AIRHUMIDIFIER_CB1, MODEL_AIRHUMIDIFIER_CB1,
@ -38,6 +34,7 @@ from .const import (
MODELS_HUMIDIFIER_MJJSQ, MODELS_HUMIDIFIER_MJJSQ,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -70,7 +67,7 @@ AVAILABLE_MODES_OTHER = [
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Humidifier from a config entry.""" """Set up the Humidifier from a config entry."""
@ -81,28 +78,26 @@ async def async_setup_entry(
entity: HumidifierEntity entity: HumidifierEntity
model = config_entry.data[CONF_MODEL] model = config_entry.data[CONF_MODEL]
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] device = config_entry.runtime_data.device
coordinator = config_entry.runtime_data.device_coordinator
if model in MODELS_HUMIDIFIER_MIOT: if model in MODELS_HUMIDIFIER_MIOT:
air_humidifier = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
entity = XiaomiAirHumidifierMiot( entity = XiaomiAirHumidifierMiot(
air_humidifier, device,
config_entry, config_entry,
unique_id, unique_id,
coordinator, coordinator,
) )
elif model in MODELS_HUMIDIFIER_MJJSQ: elif model in MODELS_HUMIDIFIER_MJJSQ:
air_humidifier = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
entity = XiaomiAirHumidifierMjjsq( entity = XiaomiAirHumidifierMjjsq(
air_humidifier, device,
config_entry, config_entry,
unique_id, unique_id,
coordinator, coordinator,
) )
else: else:
air_humidifier = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
entity = XiaomiAirHumidifier( entity = XiaomiAirHumidifier(
air_humidifier, device,
config_entry, config_entry,
unique_id, unique_id,
coordinator, coordinator,

View File

@ -33,7 +33,6 @@ from homeassistant.components.light import (
ColorMode, ColorMode,
LightEntity, LightEntity,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
CONF_DEVICE, CONF_DEVICE,
@ -51,7 +50,6 @@ from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
CONF_GATEWAY, CONF_GATEWAY,
DOMAIN, DOMAIN,
KEY_COORDINATOR,
MODELS_LIGHT_BULB, MODELS_LIGHT_BULB,
MODELS_LIGHT_CEILING, MODELS_LIGHT_CEILING,
MODELS_LIGHT_EYECARE, MODELS_LIGHT_EYECARE,
@ -67,7 +65,7 @@ from .const import (
SERVICE_SET_SCENE, SERVICE_SET_SCENE,
) )
from .entity import XiaomiGatewayDevice, XiaomiMiioEntity from .entity import XiaomiGatewayDevice, XiaomiMiioEntity
from .typing import ServiceMethodDetails from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -131,7 +129,7 @@ SERVICE_TO_METHOD = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi light from a config entry.""" """Set up the Xiaomi light from a config entry."""
@ -140,7 +138,7 @@ async def async_setup_entry(
light: MiioDevice light: MiioDevice
if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY: if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY] gateway = config_entry.runtime_data.gateway
# Gateway light # Gateway light
if gateway.model not in [ if gateway.model not in [
GATEWAY_MODEL_AC_V1, GATEWAY_MODEL_AC_V1,
@ -154,7 +152,7 @@ async def async_setup_entry(
sub_devices = gateway.devices sub_devices = gateway.devices
for sub_device in sub_devices.values(): for sub_device in sub_devices.values():
if sub_device.device_type == "LightBulb": if sub_device.device_type == "LightBulb":
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR][ coordinator = config_entry.runtime_data.gateway_coordinators[
sub_device.sid sub_device.sid
] ]
entities.append( entities.append(

View File

@ -12,7 +12,6 @@ from homeassistant.components.number import (
NumberEntity, NumberEntity,
NumberEntityDescription, NumberEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
CONF_DEVICE, CONF_DEVICE,
CONF_MODEL, CONF_MODEL,
@ -61,8 +60,6 @@ from .const import (
FEATURE_SET_MOTOR_SPEED, FEATURE_SET_MOTOR_SPEED,
FEATURE_SET_OSCILLATION_ANGLE, FEATURE_SET_OSCILLATION_ANGLE,
FEATURE_SET_VOLUME, FEATURE_SET_VOLUME,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_AIRFRESH_VA2, MODEL_AIRFRESH_VA2,
@ -99,6 +96,7 @@ from .const import (
MODELS_PURIFIER_MIOT, MODELS_PURIFIER_MIOT,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
ATTR_DELAY_OFF_COUNTDOWN = "delay_off_countdown" ATTR_DELAY_OFF_COUNTDOWN = "delay_off_countdown"
ATTR_FAN_LEVEL = "fan_level" ATTR_FAN_LEVEL = "fan_level"
@ -288,7 +286,7 @@ FAVORITE_LEVEL_VALUES = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Selectors from a config entry.""" """Set up the Selectors from a config entry."""
@ -296,7 +294,8 @@ async def async_setup_entry(
if config_entry.data[CONF_FLOW_TYPE] != CONF_DEVICE: if config_entry.data[CONF_FLOW_TYPE] != CONF_DEVICE:
return return
model = config_entry.data[CONF_MODEL] model = config_entry.data[CONF_MODEL]
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] device = config_entry.runtime_data.device
coordinator = config_entry.runtime_data.device_coordinator
if model in MODEL_TO_FEATURES_MAP: if model in MODEL_TO_FEATURES_MAP:
features = MODEL_TO_FEATURES_MAP[model] features = MODEL_TO_FEATURES_MAP[model]
@ -343,7 +342,7 @@ async def async_setup_entry(
device, device,
config_entry, config_entry,
f"{description.key}_{config_entry.unique_id}", f"{description.key}_{config_entry.unique_id}",
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], coordinator,
description, description,
) )
) )
@ -359,7 +358,7 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity):
def __init__( def __init__(
self, self,
device: Device, device: Device,
entry: ConfigEntry, entry: XiaomiMiioConfigEntry,
unique_id: str, unique_id: str,
coordinator: DataUpdateCoordinator, coordinator: DataUpdateCoordinator,
description: XiaomiMiioNumberDescription, description: XiaomiMiioNumberDescription,

View File

@ -29,16 +29,12 @@ from miio.integrations.humidifier.zhimi.airhumidifier_miot import (
) )
from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory from homeassistant.const import CONF_DEVICE, CONF_MODEL, EntityCategory
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import ( from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_AIRFRESH_VA2, MODEL_AIRFRESH_VA2,
MODEL_AIRFRESH_VA4, MODEL_AIRFRESH_VA4,
@ -64,6 +60,7 @@ from .const import (
MODEL_FAN_ZA4, MODEL_FAN_ZA4,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
ATTR_DISPLAY_ORIENTATION = "display_orientation" ATTR_DISPLAY_ORIENTATION = "display_orientation"
ATTR_LED_BRIGHTNESS = "led_brightness" ATTR_LED_BRIGHTNESS = "led_brightness"
@ -204,7 +201,7 @@ SELECTOR_TYPES = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Selectors from a config entry.""" """Set up the Selectors from a config entry."""
@ -216,8 +213,8 @@ async def async_setup_entry(
return return
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] device = config_entry.runtime_data.device
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] coordinator = config_entry.runtime_data.device_coordinator
attributes = MODEL_TO_ATTR_MAP[model] attributes = MODEL_TO_ATTR_MAP[model]
async_add_entities( async_add_entities(

View File

@ -5,8 +5,9 @@ from __future__ import annotations
from collections.abc import Iterable from collections.abc import Iterable
from dataclasses import dataclass from dataclasses import dataclass
import logging import logging
from typing import TYPE_CHECKING
from miio import AirQualityMonitor, DeviceException from miio import AirQualityMonitor, Device as MiioDevice, DeviceException
from miio.gateway.gateway import ( from miio.gateway.gateway import (
GATEWAY_MODEL_AC_V1, GATEWAY_MODEL_AC_V1,
GATEWAY_MODEL_AC_V2, GATEWAY_MODEL_AC_V2,
@ -22,7 +23,6 @@ from homeassistant.components.sensor import (
SensorEntityDescription, SensorEntityDescription,
SensorStateClass, SensorStateClass,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_BATTERY_LEVEL, ATTR_BATTERY_LEVEL,
ATTR_TEMPERATURE, ATTR_TEMPERATURE,
@ -53,8 +53,6 @@ from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
CONF_GATEWAY, CONF_GATEWAY,
DOMAIN, DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_AIRFRESH_VA2, MODEL_AIRFRESH_VA2,
@ -91,6 +89,7 @@ from .const import (
ROCKROBO_GENERIC, ROCKROBO_GENERIC,
) )
from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -724,13 +723,19 @@ VACUUM_SENSORS = {
} }
def _setup_vacuum_sensors(hass, config_entry, async_add_entities): def _setup_vacuum_sensors(
hass: HomeAssistant,
config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Xiaomi vacuum sensors.""" """Set up the Xiaomi vacuum sensors."""
device = hass.data[DOMAIN][config_entry.entry_id].get(KEY_DEVICE) device = config_entry.runtime_data.device
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] coordinator = config_entry.runtime_data.device_coordinator
entities = [] entities = []
for sensor, description in VACUUM_SENSORS.items(): for sensor, description in VACUUM_SENSORS.items():
if TYPE_CHECKING:
assert description.parent_key is not None
parent_key_data = getattr(coordinator.data, description.parent_key) parent_key_data = getattr(coordinator.data, description.parent_key)
if getattr(parent_key_data, description.key, None) is None: if getattr(parent_key_data, description.key, None) is None:
_LOGGER.debug( _LOGGER.debug(
@ -754,14 +759,14 @@ def _setup_vacuum_sensors(hass, config_entry, async_add_entities):
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi sensor from a config entry.""" """Set up the Xiaomi sensor from a config entry."""
entities: list[SensorEntity] = [] entities: list[SensorEntity] = []
if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY: if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY] gateway = config_entry.runtime_data.gateway
# Gateway illuminance sensor # Gateway illuminance sensor
if gateway.model not in [ if gateway.model not in [
GATEWAY_MODEL_AC_V1, GATEWAY_MODEL_AC_V1,
@ -779,9 +784,7 @@ async def async_setup_entry(
# Gateway sub devices # Gateway sub devices
sub_devices = gateway.devices sub_devices = gateway.devices
for sub_device in sub_devices.values(): for sub_device in sub_devices.values():
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR][ coordinator = config_entry.runtime_data.gateway_coordinators[sub_device.sid]
sub_device.sid
]
for sensor, description in SENSOR_TYPES.items(): for sensor, description in SENSOR_TYPES.items():
if sensor not in sub_device.status: if sensor not in sub_device.status:
continue continue
@ -791,6 +794,7 @@ async def async_setup_entry(
) )
) )
elif config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE: elif config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE:
device: MiioDevice
host = config_entry.data[CONF_HOST] host = config_entry.data[CONF_HOST]
token = config_entry.data[CONF_TOKEN] token = config_entry.data[CONF_TOKEN]
model: str = config_entry.data[CONF_MODEL] model: str = config_entry.data[CONF_MODEL]
@ -811,7 +815,8 @@ async def async_setup_entry(
) )
) )
else: else:
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] device = config_entry.runtime_data.device
coordinator = config_entry.runtime_data.device_coordinator
sensors: Iterable[str] = [] sensors: Iterable[str] = []
if model in MODEL_TO_SENSORS_MAP: if model in MODEL_TO_SENSORS_MAP:
sensors = MODEL_TO_SENSORS_MAP[model] sensors = MODEL_TO_SENSORS_MAP[model]
@ -839,7 +844,7 @@ async def async_setup_entry(
device, device,
config_entry, config_entry,
f"{sensor}_{config_entry.unique_id}", f"{sensor}_{config_entry.unique_id}",
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], coordinator,
description, description,
) )
) )

View File

@ -17,7 +17,6 @@ from homeassistant.components.switch import (
SwitchEntity, SwitchEntity,
SwitchEntityDescription, SwitchEntityDescription,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
ATTR_MODE, ATTR_MODE,
@ -72,8 +71,6 @@ from .const import (
FEATURE_SET_LEARN_MODE, FEATURE_SET_LEARN_MODE,
FEATURE_SET_LED, FEATURE_SET_LED,
FEATURE_SET_PTC, FEATURE_SET_PTC,
KEY_COORDINATOR,
KEY_DEVICE,
MODEL_AIRFRESH_A1, MODEL_AIRFRESH_A1,
MODEL_AIRFRESH_T2017, MODEL_AIRFRESH_T2017,
MODEL_AIRFRESH_VA2, MODEL_AIRFRESH_VA2,
@ -116,7 +113,7 @@ from .const import (
SUCCESS, SUCCESS,
) )
from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity
from .typing import ServiceMethodDetails from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -340,7 +337,7 @@ SWITCH_TYPES = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the switch from a config entry.""" """Set up the switch from a config entry."""
@ -351,12 +348,16 @@ async def async_setup_entry(
await async_setup_other_entry(hass, config_entry, async_add_entities) await async_setup_other_entry(hass, config_entry, async_add_entities)
async def async_setup_coordinated_entry(hass, config_entry, async_add_entities): async def async_setup_coordinated_entry(
hass: HomeAssistant,
config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the coordinated switch from a config entry.""" """Set up the coordinated switch from a config entry."""
model = config_entry.data[CONF_MODEL] model = config_entry.data[CONF_MODEL]
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] device = config_entry.runtime_data.device
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] coordinator = config_entry.runtime_data.device_coordinator
if DATA_KEY not in hass.data: if DATA_KEY not in hass.data:
hass.data[DATA_KEY] = {} hass.data[DATA_KEY] = {}
@ -387,24 +388,26 @@ async def async_setup_coordinated_entry(hass, config_entry, async_add_entities):
) )
async def async_setup_other_entry(hass, config_entry, async_add_entities): async def async_setup_other_entry(
hass: HomeAssistant,
config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the other type switch from a config entry.""" """Set up the other type switch from a config entry."""
entities = [] entities: list[SwitchEntity] = []
host = config_entry.data[CONF_HOST] host = config_entry.data[CONF_HOST]
token = config_entry.data[CONF_TOKEN] token = config_entry.data[CONF_TOKEN]
name = config_entry.title name = config_entry.title
model = config_entry.data[CONF_MODEL] model = config_entry.data[CONF_MODEL]
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY: if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY] gateway = config_entry.runtime_data.gateway
# Gateway sub devices # Gateway sub devices
sub_devices = gateway.devices sub_devices = gateway.devices
for sub_device in sub_devices.values(): for sub_device in sub_devices.values():
if sub_device.device_type != "Switch": if sub_device.device_type != "Switch":
continue continue
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR][ coordinator = config_entry.runtime_data.gateway_coordinators[sub_device.sid]
sub_device.sid
]
switch_variables = set(sub_device.status) & set(GATEWAY_SWITCH_VARS) switch_variables = set(sub_device.status) & set(GATEWAY_SWITCH_VARS)
if switch_variables: if switch_variables:
entities.extend( entities.extend(
@ -420,13 +423,14 @@ async def async_setup_other_entry(hass, config_entry, async_add_entities):
config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY
and model == "lumi.acpartner.v3" and model == "lumi.acpartner.v3"
): ):
device: SwitchEntity
if DATA_KEY not in hass.data: if DATA_KEY not in hass.data:
hass.data[DATA_KEY] = {} hass.data[DATA_KEY] = {}
_LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5])
if model in ["chuangmi.plug.v1", "chuangmi.plug.v3", "chuangmi.plug.hmi208"]: if model in ["chuangmi.plug.v1", "chuangmi.plug.v3", "chuangmi.plug.hmi208"]:
plug = ChuangmiPlug(host, token, model=model) chuangmi_plug = ChuangmiPlug(host, token, model=model)
# The device has two switchable channels (mains and a USB port). # The device has two switchable channels (mains and a USB port).
# A switch device per channel will be created. # A switch device per channel will be created.
@ -436,13 +440,13 @@ async def async_setup_other_entry(hass, config_entry, async_add_entities):
else: else:
unique_id_ch = f"{unique_id}-mains" unique_id_ch = f"{unique_id}-mains"
device = ChuangMiPlugSwitch( device = ChuangMiPlugSwitch(
name, plug, config_entry, unique_id_ch, channel_usb name, chuangmi_plug, config_entry, unique_id_ch, channel_usb
) )
entities.append(device) entities.append(device)
hass.data[DATA_KEY][host] = device hass.data[DATA_KEY][host] = device
elif model in ["qmi.powerstrip.v1", "zimi.powerstrip.v2"]: elif model in ["qmi.powerstrip.v1", "zimi.powerstrip.v2"]:
plug = PowerStrip(host, token, model=model) power_strip = PowerStrip(host, token, model=model)
device = XiaomiPowerStripSwitch(name, plug, config_entry, unique_id) device = XiaomiPowerStripSwitch(name, power_strip, config_entry, unique_id)
entities.append(device) entities.append(device)
hass.data[DATA_KEY][host] = device hass.data[DATA_KEY][host] = device
elif model in [ elif model in [
@ -452,14 +456,16 @@ async def async_setup_other_entry(hass, config_entry, async_add_entities):
"chuangmi.plug.hmi205", "chuangmi.plug.hmi205",
"chuangmi.plug.hmi206", "chuangmi.plug.hmi206",
]: ]:
plug = ChuangmiPlug(host, token, model=model) chuangmi_plug = ChuangmiPlug(host, token, model=model)
device = XiaomiPlugGenericSwitch(name, plug, config_entry, unique_id) device = XiaomiPlugGenericSwitch(
name, chuangmi_plug, config_entry, unique_id
)
entities.append(device) entities.append(device)
hass.data[DATA_KEY][host] = device hass.data[DATA_KEY][host] = device
elif model in ["lumi.acpartner.v3"]: elif model in ["lumi.acpartner.v3"]:
plug = AirConditioningCompanionV3(host, token) ac_companion = AirConditioningCompanionV3(host, token)
device = XiaomiAirConditioningCompanionSwitch( device = XiaomiAirConditioningCompanionSwitch(
name, plug, config_entry, unique_id name, ac_companion, config_entry, unique_id
) )
entities.append(device) entities.append(device)
hass.data[DATA_KEY][host] = device hass.data[DATA_KEY][host] = device

View File

@ -1,12 +1,36 @@
"""Typings for the xiaomi_miio integration.""" """Typings for the xiaomi_miio integration."""
from typing import NamedTuple from dataclasses import dataclass
from typing import Any, NamedTuple
from miio import Device as MiioDevice
from miio.gateway.gateway import Gateway
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
class ServiceMethodDetails(NamedTuple): class ServiceMethodDetails(NamedTuple):
"""Details for SERVICE_TO_METHOD mapping.""" """Details for SERVICE_TO_METHOD mapping."""
method: str method: str
schema: vol.Schema | None = None schema: vol.Schema | None = None
@dataclass
class XiaomiMiioRuntimeData:
"""Runtime data for Xiaomi Miio config entry.
Either device/device_coordinator or gateway/gateway_coordinators
must be set, based on CONF_FLOW_TYPE (CONF_DEVICE or CONF_GATEWAY)
"""
device: MiioDevice = None # type: ignore[assignment]
device_coordinator: DataUpdateCoordinator[Any] = None # type: ignore[assignment]
gateway: Gateway = None # type: ignore[assignment]
gateway_coordinators: dict[str, DataUpdateCoordinator[dict[str, bool]]] = None # type: ignore[assignment]
type XiaomiMiioConfigEntry = ConfigEntry[XiaomiMiioRuntimeData]

View File

@ -14,7 +14,6 @@ from homeassistant.components.vacuum import (
VacuumActivity, VacuumActivity,
VacuumEntityFeature, VacuumEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE from homeassistant.const import CONF_DEVICE
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, entity_platform from homeassistant.helpers import config_validation as cv, entity_platform
@ -25,9 +24,6 @@ from homeassistant.util.dt import as_utc
from . import VacuumCoordinatorData from . import VacuumCoordinatorData
from .const import ( from .const import (
CONF_FLOW_TYPE, CONF_FLOW_TYPE,
DOMAIN,
KEY_COORDINATOR,
KEY_DEVICE,
SERVICE_CLEAN_SEGMENT, SERVICE_CLEAN_SEGMENT,
SERVICE_CLEAN_ZONE, SERVICE_CLEAN_ZONE,
SERVICE_GOTO, SERVICE_GOTO,
@ -37,6 +33,7 @@ from .const import (
SERVICE_STOP_REMOTE_CONTROL, SERVICE_STOP_REMOTE_CONTROL,
) )
from .entity import XiaomiCoordinatedMiioEntity from .entity import XiaomiCoordinatedMiioEntity
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -78,7 +75,7 @@ STATE_CODE_TO_STATE = {
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: XiaomiMiioConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Xiaomi vacuum cleaner robot from a config entry.""" """Set up the Xiaomi vacuum cleaner robot from a config entry."""
@ -88,10 +85,10 @@ async def async_setup_entry(
unique_id = config_entry.unique_id unique_id = config_entry.unique_id
mirobo = MiroboVacuum( mirobo = MiroboVacuum(
hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE], config_entry.runtime_data.device,
config_entry, config_entry,
unique_id, unique_id,
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], config_entry.runtime_data.device_coordinator,
) )
entities.append(mirobo) entities.append(mirobo)