diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 315f116ed92..c14266e296f 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -30,6 +30,7 @@ from homeassistant.helpers import ( ) from homeassistant.helpers.device_registry import DeviceEntry from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity_platform import async_get_platforms from homeassistant.helpers.reload import ( async_integration_yaml_config, async_reload_integration_platforms, @@ -75,7 +76,7 @@ from .const import ( # noqa: F401 PLATFORMS, RELOADABLE_PLATFORMS, ) -from .mixins import MqttData, async_discover_yaml_entities +from .mixins import MqttData from .models import ( # noqa: F401 MqttCommandTemplate, MqttValueTemplate, @@ -422,13 +423,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await async_reload_integration_platforms(hass, DOMAIN, RELOADABLE_PLATFORMS) # Reload the modern yaml platforms + mqtt_platforms = async_get_platforms(hass, DOMAIN) + tasks = [ + entity.async_remove() + for mqtt_platform in mqtt_platforms + for entity in mqtt_platform.entities.values() + if not entity._discovery_data # type: ignore[attr-defined] # pylint: disable=protected-access + if mqtt_platform.config_entry + and mqtt_platform.domain in RELOADABLE_PLATFORMS + ] + await asyncio.gather(*tasks) + config_yaml = await async_integration_yaml_config(hass, DOMAIN) or {} mqtt_data.updated_config = config_yaml.get(DOMAIN, {}) await asyncio.gather( *( [ - async_discover_yaml_entities(hass, component) + mqtt_data.reload_handlers[component]() for component in RELOADABLE_PLATFORMS + if component in mqtt_data.reload_handlers ] ) ) diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index cf7262f9468..c3502cd8e64 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -44,7 +44,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -146,9 +145,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT alarm control panel through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, alarm.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index adb4c12daf9..f0e5ecc9df8 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -42,7 +42,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -102,9 +101,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT binary sensor through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, binary_sensor.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/button.py b/homeassistant/components/mqtt/button.py index 0881b963b04..a14bf87c3be 100644 --- a/homeassistant/components/mqtt/button.py +++ b/homeassistant/components/mqtt/button.py @@ -25,7 +25,6 @@ from .const import ( from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -81,9 +80,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT button through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, button.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/camera.py b/homeassistant/components/mqtt/camera.py index 61c87e86888..f6039251882 100644 --- a/homeassistant/components/mqtt/camera.py +++ b/homeassistant/components/mqtt/camera.py @@ -23,7 +23,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -105,9 +104,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT camera through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, camera.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index 3f0f8a89b3e..96c7ca3665b 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -50,7 +50,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -350,9 +349,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT climate device through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, climate.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index fd96fe524d9..1f5d26c3a78 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -46,7 +46,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -242,9 +241,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT cover through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, cover.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/fan.py b/homeassistant/components/mqtt/fan.py index fab748d2bfc..584df08e7d7 100644 --- a/homeassistant/components/mqtt/fan.py +++ b/homeassistant/components/mqtt/fan.py @@ -50,7 +50,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -241,9 +240,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT fan through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, fan.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/humidifier.py b/homeassistant/components/mqtt/humidifier.py index 3a1271ea2c9..837bbb8b909 100644 --- a/homeassistant/components/mqtt/humidifier.py +++ b/homeassistant/components/mqtt/humidifier.py @@ -46,7 +46,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -187,9 +186,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT humidifier through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, humidifier.DOMAIN) - # 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 76c2980e63b..b7d52919d5e 100644 --- a/homeassistant/components/mqtt/light/__init__.py +++ b/homeassistant/components/mqtt/light/__init__.py @@ -14,7 +14,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from ..mixins import ( - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -111,9 +110,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lights configured under the light platform key (deprecated).""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, light.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index 4910eafae75..dca02f909dc 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -28,7 +28,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -102,9 +101,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lock through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, lock.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index a16394667d8..477be399e26 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -39,7 +39,6 @@ from homeassistant.core import ( 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 @@ -286,6 +285,9 @@ class MqttData: last_discovery: float = 0.0 reload_dispatchers: list[CALLBACK_TYPE] = field(default_factory=list) reload_entry: bool = False + reload_handlers: dict[str, Callable[[], Coroutine[Any, Any, None]]] = field( + default_factory=dict + ) reload_needed: bool = False subscriptions_to_restore: list[Subscription] = field(default_factory=list) updated_config: ConfigType = field(default_factory=dict) @@ -305,30 +307,6 @@ class SetupEntity(Protocol): """Define setup_entities type.""" -async def async_discover_yaml_entities( - hass: HomeAssistant, platform_domain: str -) -> None: - """Discover entities for a platform.""" - mqtt_data: MqttData = hass.data[DATA_MQTT] - if mqtt_data.updated_config: - # The platform has been reloaded - config_yaml = mqtt_data.updated_config - else: - config_yaml = mqtt_data.config or {} - 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, config_yaml - ) - ) - ) - - async def async_get_platform_config_from_yaml( hass: HomeAssistant, platform_domain: str, @@ -350,7 +328,7 @@ async def async_setup_entry_helper( hass: HomeAssistant, domain: str, async_setup: partial[Coroutine[HomeAssistant, str, None]], - schema: vol.Schema, + discovery_schema: vol.Schema, ) -> None: """Set up entity, automation or tag creation dynamically through MQTT discovery.""" mqtt_data: MqttData = hass.data[DATA_MQTT] @@ -367,7 +345,7 @@ async def async_setup_entry_helper( return discovery_data = discovery_payload.discovery_data try: - config = schema(discovery_payload) + config = discovery_schema(discovery_payload) await async_setup(config, discovery_data=discovery_data) except Exception: discovery_hash = discovery_data[ATTR_DISCOVERY_HASH] @@ -383,6 +361,31 @@ async def async_setup_entry_helper( ) ) + async def _async_setup_entities() -> None: + """Set up MQTT items from configuration.yaml.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] + if mqtt_data.updated_config: + # The platform has been reloaded + config_yaml = mqtt_data.updated_config + else: + config_yaml = mqtt_data.config or {} + if not config_yaml: + return + if domain not in config_yaml: + return + await asyncio.gather( + *[ + async_setup(config) + for config in await async_get_platform_config_from_yaml( + hass, domain, config_yaml + ) + ] + ) + + # discover manual configured MQTT items + mqtt_data.reload_handlers[domain] = _async_setup_entities + await _async_setup_entities() + async def async_setup_platform_helper( hass: HomeAssistant, diff --git a/homeassistant/components/mqtt/number.py b/homeassistant/components/mqtt/number.py index eeac406f668..09f9d122b98 100644 --- a/homeassistant/components/mqtt/number.py +++ b/homeassistant/components/mqtt/number.py @@ -44,7 +44,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -138,9 +137,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT number through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, number.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/scene.py b/homeassistant/components/mqtt/scene.py index 70a4cad7f37..e237d70e903 100644 --- a/homeassistant/components/mqtt/scene.py +++ b/homeassistant/components/mqtt/scene.py @@ -23,7 +23,6 @@ from .mixins import ( CONF_OBJECT_ID, MQTT_AVAILABILITY_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -79,9 +78,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT scene through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, scene.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/select.py b/homeassistant/components/mqtt/select.py index ec88b1732d4..a6de0495690 100644 --- a/homeassistant/components/mqtt/select.py +++ b/homeassistant/components/mqtt/select.py @@ -30,7 +30,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -93,9 +92,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT select through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, select.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index b361ce06a81..7c98fdf51b7 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -1,7 +1,7 @@ """Support for MQTT sensors.""" from __future__ import annotations -from datetime import timedelta +from datetime import datetime, timedelta import functools import logging @@ -30,7 +30,7 @@ from homeassistant.core import HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_point_in_utc_time -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType from homeassistant.util import dt as dt_util from . import subscription @@ -41,7 +41,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -146,9 +145,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT sensor through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, sensor.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) @@ -347,12 +343,12 @@ class MqttSensor(MqttEntity, RestoreSensor): self.async_write_ha_state() @property - def native_unit_of_measurement(self): + def native_unit_of_measurement(self) -> str | None: """Return the unit this state is expressed in.""" return self._config.get(CONF_UNIT_OF_MEASUREMENT) @property - def native_value(self): + def native_value(self) -> StateType | datetime: """Return the state of the entity.""" return self._state diff --git a/homeassistant/components/mqtt/siren.py b/homeassistant/components/mqtt/siren.py index 1f5111a5499..c8332046092 100644 --- a/homeassistant/components/mqtt/siren.py +++ b/homeassistant/components/mqtt/siren.py @@ -49,7 +49,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -140,9 +139,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT siren through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, siren.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/switch.py b/homeassistant/components/mqtt/switch.py index b5c7ab13dfc..af16b14bea1 100644 --- a/homeassistant/components/mqtt/switch.py +++ b/homeassistant/components/mqtt/switch.py @@ -42,7 +42,6 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -101,9 +100,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT switch through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, switch.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/vacuum/__init__.py b/homeassistant/components/mqtt/vacuum/__init__.py index cdd14e6d8e3..abab55c632c 100644 --- a/homeassistant/components/mqtt/vacuum/__init__.py +++ b/homeassistant/components/mqtt/vacuum/__init__.py @@ -11,11 +11,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType -from ..mixins import ( - async_discover_yaml_entities, - async_setup_entry_helper, - async_setup_platform_helper, -) +from ..mixins import async_setup_entry_helper, async_setup_platform_helper from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE from .schema_legacy import ( DISCOVERY_SCHEMA_LEGACY, @@ -90,9 +86,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT vacuum through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, vacuum.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 46649bf703f..90df45b65a1 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -29,11 +29,13 @@ from homeassistant.core import CoreState, HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, template from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity_platform import async_get_platforms from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow from .test_common import ( help_test_entry_reload_with_new_config, + help_test_reload_with_config, help_test_setup_manual_entity_from_yaml, ) @@ -2986,3 +2988,68 @@ async def test_remove_unknown_conf_entry_options(hass, mqtt_client_mock, caplog) "MQTT config entry: {'protocol'}. Add them to configuration.yaml if they " "are needed" ) in caplog.text + + +@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.LIGHT]) +async def test_link_config_entry(hass, tmp_path, caplog): + """Test manual and dynamically setup entities are linked to the config entry.""" + config_manual = { + "mqtt": { + "light": [ + { + "name": "test_manual", + "unique_id": "test_manual_unique_id123", + "command_topic": "test-topic_manual", + } + ] + } + } + config_discovery = { + "name": "test_discovery", + "unique_id": "test_discovery_unique456", + "command_topic": "test-topic_discovery", + } + + # set up manual item + await help_test_setup_manual_entity_from_yaml(hass, config_manual) + + # set up item through discovery + async_fire_mqtt_message( + hass, "homeassistant/light/bla/config", json.dumps(config_discovery) + ) + await hass.async_block_till_done() + + assert hass.states.get("light.test_manual") is not None + assert hass.states.get("light.test_discovery") is not None + entity_names = ["test_manual", "test_discovery"] + + # Check if both entities were linked to the MQTT config entry + mqtt_config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] + mqtt_platforms = async_get_platforms(hass, mqtt.DOMAIN) + + def _check_entities(): + entities = [] + for mqtt_platform in mqtt_platforms: + assert mqtt_platform.config_entry is mqtt_config_entry + entities += (entity for entity in mqtt_platform.entities.values()) + + for entity in entities: + assert entity.name in entity_names + return len(entities) + + assert _check_entities() == 2 + + # reload entry and assert again + await help_test_entry_reload_with_new_config(hass, tmp_path, config_manual) + # manual set up item should remain + assert _check_entities() == 1 + # set up item through discovery + async_fire_mqtt_message( + hass, "homeassistant/light/bla/config", json.dumps(config_discovery) + ) + await hass.async_block_till_done() + assert _check_entities() == 2 + + # reload manual configured items and assert again + await help_test_reload_with_config(hass, caplog, tmp_path, config_manual) + assert _check_entities() == 2