diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index c20fbb7c657..c0c6f9732d7 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -1,7 +1,6 @@ """This platform enables the possibility to control a MQTT alarm.""" from __future__ import annotations -import asyncio import functools import logging import re @@ -45,8 +44,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -133,7 +132,11 @@ async def async_setup_platform( """Set up MQTT alarm control panel configured under the alarm_control_panel key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, alarm.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + alarm.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -144,13 +147,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT alarm control panel through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, alarm.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, alarm.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index 1cb90d6c903..cec065e20f2 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -1,7 +1,6 @@ """Support for MQTT binary sensors.""" from __future__ import annotations -import asyncio from datetime import timedelta import functools import logging @@ -42,8 +41,8 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -88,7 +87,11 @@ async def async_setup_platform( """Set up MQTT binary sensor configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, binary_sensor.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + binary_sensor.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -99,12 +102,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT binary sensor through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, binary_sensor.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, binary_sensor.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/button.py b/homeassistant/components/mqtt/button.py index b50856d20c1..afa9900db35 100644 --- a/homeassistant/components/mqtt/button.py +++ b/homeassistant/components/mqtt/button.py @@ -1,7 +1,6 @@ """Support for MQTT buttons.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -26,8 +25,8 @@ from .const import ( from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -68,7 +67,11 @@ async def async_setup_platform( """Set up MQTT button configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, button.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + button.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -79,12 +82,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT button through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, button.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, button.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/camera.py b/homeassistant/components/mqtt/camera.py index ae38e07d17a..86db828b111 100644 --- a/homeassistant/components/mqtt/camera.py +++ b/homeassistant/components/mqtt/camera.py @@ -1,7 +1,6 @@ """Camera that loads a picture from an MQTT topic.""" from __future__ import annotations -import asyncio from base64 import b64decode import functools @@ -23,8 +22,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -66,7 +65,11 @@ async def async_setup_platform( """Set up MQTT camera configured under the camera platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, camera.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + camera.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -77,12 +80,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT camera through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, camera.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, camera.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index 64b462359be..bdcc82f2c39 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -1,7 +1,6 @@ """Support for MQTT climate devices.""" from __future__ import annotations -import asyncio import functools import logging @@ -51,8 +50,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -377,7 +376,11 @@ async def async_setup_platform( """Set up MQTT climate configured under the fan platform key (deprecated).""" # The use of PLATFORM_SCHEMA is deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, climate.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + climate.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -388,12 +391,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT climate device through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, climate.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, climate.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index 5814f3e43f7..325433817c0 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -1,7 +1,6 @@ """Support for MQTT cover devices.""" from __future__ import annotations -import asyncio import functools from json import JSONDecodeError, loads as json_loads import logging @@ -46,8 +45,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -227,7 +226,11 @@ async def async_setup_platform( """Set up MQTT covers configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, cover.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + cover.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -238,13 +241,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT cover through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, cover.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, cover.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/fan.py b/homeassistant/components/mqtt/fan.py index f72b0bdf689..d0b4ff10692 100644 --- a/homeassistant/components/mqtt/fan.py +++ b/homeassistant/components/mqtt/fan.py @@ -1,7 +1,6 @@ """Support for MQTT fans.""" from __future__ import annotations -import asyncio import functools import logging import math @@ -50,8 +49,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -217,7 +216,11 @@ async def async_setup_platform( """Set up MQTT fans configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, fan.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + fan.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -228,13 +231,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT fan through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, fan.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, fan.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/humidifier.py b/homeassistant/components/mqtt/humidifier.py index 000a9b9700e..1c9ec5dc201 100644 --- a/homeassistant/components/mqtt/humidifier.py +++ b/homeassistant/components/mqtt/humidifier.py @@ -1,7 +1,6 @@ """Support for MQTT humidifiers.""" from __future__ import annotations -import asyncio import functools import logging @@ -46,8 +45,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -173,7 +172,11 @@ async def async_setup_platform( """Set up MQTT humidifier configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, humidifier.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + humidifier.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -184,14 +187,12 @@ async def async_setup_entry( ) -> None: """Set up MQTT humidifier through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, humidifier.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, humidifier.DOMAIN, PLATFORM_SCHEMA_MODERN ) - ) # setup for discovery + ) + # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/light/__init__.py b/homeassistant/components/mqtt/light/__init__.py index ab2a3462615..158ea6ffa0d 100644 --- a/homeassistant/components/mqtt/light/__init__.py +++ b/homeassistant/components/mqtt/light/__init__.py @@ -1,7 +1,6 @@ """Support for MQTT lights.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -14,8 +13,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from ..mixins import ( - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -97,7 +96,11 @@ async def async_setup_platform( """Set up MQTT light through configuration.yaml (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, light.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + light.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -108,13 +111,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT lights configured under the light platform key (deprecated).""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, light.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, light.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index 0cfd1d2b70f..862e76635f7 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -1,7 +1,6 @@ """Support for MQTT locks.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -28,8 +27,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -88,7 +87,11 @@ async def async_setup_platform( """Set up MQTT locks configured under the lock platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, lock.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + lock.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -99,13 +102,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT lock through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, lock.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, lock.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 694fae0b3c0..b0f17cc335b 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -2,6 +2,7 @@ from __future__ import annotations from abc import abstractmethod +import asyncio from collections.abc import Callable import json import logging @@ -27,10 +28,11 @@ from homeassistant.const import ( CONF_UNIQUE_ID, CONF_VALUE_TEMPLATE, ) -from homeassistant.core import Event, HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback from homeassistant.helpers import ( config_validation as cv, device_registry as dr, + discovery, entity_registry as er, ) from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED @@ -46,7 +48,10 @@ from homeassistant.helpers.entity import ( async_generate_entity_id, ) from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.reload import async_setup_reload_service +from homeassistant.helpers.reload import ( + async_integration_yaml_config, + async_setup_reload_service, +) from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import debug_info, subscription @@ -260,8 +265,44 @@ class SetupEntity(Protocol): """Define setup_entities type.""" +async def async_setup_platform_discovery( + hass: HomeAssistant, platform_domain: str, schema: vol.Schema +) -> CALLBACK_TYPE: + """Set up platform discovery for manual config.""" + + async def _async_discover_entities(event: Event | None) -> None: + """Discover entities for a platform.""" + if event: + # The platform has been reloaded + config_yaml = await async_integration_yaml_config(hass, DOMAIN) + if not config_yaml: + return + config_yaml = config_yaml.get(DOMAIN, {}) + else: + config_yaml = hass.data.get(DATA_MQTT_CONFIG, {}) + if not config_yaml: + return + if platform_domain not in config_yaml: + return + await asyncio.gather( + *( + discovery.async_load_platform(hass, platform_domain, DOMAIN, config, {}) + for config in await async_get_platform_config_from_yaml( + hass, platform_domain, schema, config_yaml + ) + ) + ) + + unsub = hass.bus.async_listen("event_mqtt_reloaded", _async_discover_entities) + await _async_discover_entities(None) + return unsub + + async def async_get_platform_config_from_yaml( - hass: HomeAssistant, domain: str, schema: vol.Schema + hass: HomeAssistant, + platform_domain: str, + schema: vol.Schema, + config_yaml: ConfigType = None, ) -> list[ConfigType]: """Return a list of validated configurations for the domain.""" @@ -275,12 +316,15 @@ async def async_get_platform_config_from_yaml( try: validated_config.append(schema(config_item)) except vol.MultipleInvalid as err: - async_log_exception(err, domain, config_item, hass) + async_log_exception(err, platform_domain, config_item, hass) return validated_config - config_yaml: ConfigType = hass.data.get(DATA_MQTT_CONFIG, {}) - if not (platform_configs := config_yaml.get(domain)): + if config_yaml is None: + config_yaml = hass.data.get(DATA_MQTT_CONFIG) + if not config_yaml: + return [] + if not (platform_configs := config_yaml.get(platform_domain)): return [] return async_validate_config(hass, platform_configs) @@ -310,7 +354,7 @@ async def async_setup_entry_helper(hass, domain, async_setup, schema): async def async_setup_platform_helper( hass: HomeAssistant, platform_domain: str, - config: ConfigType, + config: ConfigType | DiscoveryInfoType, async_add_entities: AddEntitiesCallback, async_setup_entities: SetupEntity, ) -> None: diff --git a/homeassistant/components/mqtt/number.py b/homeassistant/components/mqtt/number.py index 6ea1f0959f6..1404dc86a3c 100644 --- a/homeassistant/components/mqtt/number.py +++ b/homeassistant/components/mqtt/number.py @@ -1,7 +1,6 @@ """Configure number in a device through MQTT topic.""" from __future__ import annotations -import asyncio import functools import logging @@ -41,8 +40,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -119,7 +118,11 @@ async def async_setup_platform( """Set up MQTT number configured under the number platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, number.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + number.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -130,12 +133,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT number through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, number.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, number.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/scene.py b/homeassistant/components/mqtt/scene.py index ce8f0b0a3e8..9c4a212bd8e 100644 --- a/homeassistant/components/mqtt/scene.py +++ b/homeassistant/components/mqtt/scene.py @@ -1,7 +1,6 @@ """Support for MQTT scenes.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -23,8 +22,8 @@ from .mixins import ( CONF_OBJECT_ID, MQTT_AVAILABILITY_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -65,7 +64,11 @@ async def async_setup_platform( """Set up MQTT scene configured under the scene platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, scene.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + scene.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -76,13 +79,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT scene through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, scene.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, scene.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/select.py b/homeassistant/components/mqtt/select.py index 75e1b4e8efd..994c11653b7 100644 --- a/homeassistant/components/mqtt/select.py +++ b/homeassistant/components/mqtt/select.py @@ -1,7 +1,6 @@ """Configure select in a device through MQTT topic.""" from __future__ import annotations -import asyncio import functools import logging @@ -31,8 +30,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -80,7 +79,11 @@ async def async_setup_platform( """Set up MQTT select configured under the select platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, select.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + select.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -91,12 +94,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT select through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, select.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, select.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index 4dd1ad4d95f..f9e0b5151bb 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -1,7 +1,6 @@ """Support for MQTT sensors.""" from __future__ import annotations -import asyncio from datetime import timedelta import functools import logging @@ -42,8 +41,8 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -133,7 +132,11 @@ async def async_setup_platform( """Set up MQTT sensors configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, sensor.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + sensor.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -144,12 +147,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT sensor through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, sensor.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, sensor.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/siren.py b/homeassistant/components/mqtt/siren.py index 1ecf2c37dbf..fef2a4fb3dd 100644 --- a/homeassistant/components/mqtt/siren.py +++ b/homeassistant/components/mqtt/siren.py @@ -1,7 +1,6 @@ """Support for MQTT sirens.""" from __future__ import annotations -import asyncio import copy import functools import json @@ -52,8 +51,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -129,7 +128,11 @@ async def async_setup_platform( """Set up MQTT sirens configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, siren.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + siren.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -140,13 +143,8 @@ async def async_setup_entry( ) -> None: """Set up MQTT siren through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, siren.DOMAIN, PLATFORM_SCHEMA_MODERN - ) - ) + config_entry.async_on_unload( + await async_setup_platform_discovery(hass, siren.DOMAIN, PLATFORM_SCHEMA_MODERN) ) # setup for discovery setup = functools.partial( diff --git a/homeassistant/components/mqtt/switch.py b/homeassistant/components/mqtt/switch.py index c20ddfe5151..be7fc655e1e 100644 --- a/homeassistant/components/mqtt/switch.py +++ b/homeassistant/components/mqtt/switch.py @@ -1,7 +1,6 @@ """Support for MQTT switches.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -38,8 +37,8 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, warn_for_legacy_schema, ) @@ -83,7 +82,11 @@ async def async_setup_platform( """Set up MQTT switch configured under the fan platform key (deprecated).""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, switch.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + switch.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -94,12 +97,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT switch through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, switch.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, switch.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/homeassistant/components/mqtt/vacuum/__init__.py b/homeassistant/components/mqtt/vacuum/__init__.py index 34205ab7780..206a15a024a 100644 --- a/homeassistant/components/mqtt/vacuum/__init__.py +++ b/homeassistant/components/mqtt/vacuum/__init__.py @@ -1,7 +1,6 @@ """Support for MQTT vacuums.""" from __future__ import annotations -import asyncio import functools import voluptuous as vol @@ -13,8 +12,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from ..mixins import ( - async_get_platform_config_from_yaml, async_setup_entry_helper, + async_setup_platform_discovery, async_setup_platform_helper, ) from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE @@ -77,7 +76,11 @@ async def async_setup_platform( """Set up MQTT vacuum through configuration.yaml.""" # Deprecated in HA Core 2022.6 await async_setup_platform_helper( - hass, vacuum.DOMAIN, config, async_add_entities, _async_setup_entity + hass, + vacuum.DOMAIN, + discovery_info or config, + async_add_entities, + _async_setup_entity, ) @@ -88,12 +91,9 @@ async def async_setup_entry( ) -> None: """Set up MQTT vacuum through configuration.yaml and dynamically through MQTT discovery.""" # load and initialize platform config from configuration.yaml - await asyncio.gather( - *( - _async_setup_entity(hass, async_add_entities, config, config_entry) - for config in await async_get_platform_config_from_yaml( - hass, vacuum.DOMAIN, PLATFORM_SCHEMA_MODERN - ) + config_entry.async_on_unload( + await async_setup_platform_discovery( + hass, vacuum.DOMAIN, PLATFORM_SCHEMA_MODERN ) ) # setup for discovery diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index 37bb783d354..ebb1d78138f 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -1011,7 +1011,7 @@ async def test_cleanup_triggers_and_restoring_state( freezer.move_to("2022-02-02 12:01:10+01:00") await help_test_reload_with_config( - hass, caplog, tmp_path, domain, [config1, config2] + hass, caplog, tmp_path, {domain: [config1, config2]} ) assert "Clean up expire after trigger for binary_sensor.test1" in caplog.text assert "Clean up expire after trigger for binary_sensor.test2" not in caplog.text diff --git a/tests/components/mqtt/test_common.py b/tests/components/mqtt/test_common.py index 50cf7beb0e0..24482129f3d 100644 --- a/tests/components/mqtt/test_common.py +++ b/tests/components/mqtt/test_common.py @@ -1651,10 +1651,10 @@ async def help_test_publishing_with_custom_encoding( mqtt_mock.async_publish.reset_mock() -async def help_test_reload_with_config(hass, caplog, tmp_path, domain, config): +async def help_test_reload_with_config(hass, caplog, tmp_path, config): """Test reloading with supplied config.""" new_yaml_config_file = tmp_path / "configuration.yaml" - new_yaml_config = yaml.dump({domain: config}) + new_yaml_config = yaml.dump(config) new_yaml_config_file.write_text(new_yaml_config) assert new_yaml_config_file.read_text() == new_yaml_config @@ -1679,16 +1679,27 @@ async def help_test_reloadable( old_config_1["name"] = "test_old_1" old_config_2 = copy.deepcopy(config) old_config_2["name"] = "test_old_2" + old_config_3 = copy.deepcopy(config) + old_config_3["name"] = "test_old_3" + old_config_3.pop("platform") + old_config_4 = copy.deepcopy(config) + old_config_4["name"] = "test_old_4" + old_config_4.pop("platform") - assert await async_setup_component( - hass, domain, {domain: [old_config_1, old_config_2]} - ) + old_config = { + domain: [old_config_1, old_config_2], + "mqtt": {domain: [old_config_3, old_config_4]}, + } + + assert await async_setup_component(hass, domain, old_config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() assert hass.states.get(f"{domain}.test_old_1") assert hass.states.get(f"{domain}.test_old_2") - assert len(hass.states.async_all(domain)) == 2 + assert hass.states.get(f"{domain}.test_old_3") + assert hass.states.get(f"{domain}.test_old_4") + assert len(hass.states.async_all(domain)) == 4 # Create temporary fixture for configuration.yaml based on the supplied config and # test a reload with this new config @@ -1698,16 +1709,31 @@ async def help_test_reloadable( new_config_2["name"] = "test_new_2" new_config_3 = copy.deepcopy(config) new_config_3["name"] = "test_new_3" + new_config_3.pop("platform") + new_config_4 = copy.deepcopy(config) + new_config_4["name"] = "test_new_4" + new_config_4.pop("platform") + new_config_5 = copy.deepcopy(config) + new_config_5["name"] = "test_new_5" + new_config_6 = copy.deepcopy(config) + new_config_6["name"] = "test_new_6" + new_config_6.pop("platform") - await help_test_reload_with_config( - hass, caplog, tmp_path, domain, [new_config_1, new_config_2, new_config_3] - ) + new_config = { + domain: [new_config_1, new_config_2, new_config_5], + "mqtt": {domain: [new_config_3, new_config_4, new_config_6]}, + } - assert len(hass.states.async_all(domain)) == 3 + await help_test_reload_with_config(hass, caplog, tmp_path, new_config) + + assert len(hass.states.async_all(domain)) == 6 assert hass.states.get(f"{domain}.test_new_1") assert hass.states.get(f"{domain}.test_new_2") assert hass.states.get(f"{domain}.test_new_3") + assert hass.states.get(f"{domain}.test_new_4") + assert hass.states.get(f"{domain}.test_new_5") + assert hass.states.get(f"{domain}.test_new_6") async def help_test_reloadable_late(hass, caplog, tmp_path, domain, config): @@ -1752,9 +1778,10 @@ async def help_test_reloadable_late(hass, caplog, tmp_path, domain, config): new_config_3 = copy.deepcopy(config) new_config_3["name"] = "test_new_3" - await help_test_reload_with_config( - hass, caplog, tmp_path, domain, [new_config_1, new_config_2, new_config_3] - ) + new_config = { + domain: [new_config_1, new_config_2, new_config_3], + } + await help_test_reload_with_config(hass, caplog, tmp_path, new_config) assert len(hass.states.async_all(domain)) == 3 diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index 894ecc32ecc..7081ae45993 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -1106,7 +1106,7 @@ async def test_cleanup_triggers_and_restoring_state( freezer.move_to("2022-02-02 12:01:10+01:00") await help_test_reload_with_config( - hass, caplog, tmp_path, domain, [config1, config2] + hass, caplog, tmp_path, {domain: [config1, config2]} ) await hass.async_block_till_done()