diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index 3de496e4291..3cdb3efea7f 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -127,7 +127,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT alarm control panel through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttAlarm, diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index 2046ca4b11b..293b6e5f1f4 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -71,7 +71,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT binary sensor through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttBinarySensor, diff --git a/homeassistant/components/mqtt/button.py b/homeassistant/components/mqtt/button.py index 8c14a42bbe0..6ad11859f44 100644 --- a/homeassistant/components/mqtt/button.py +++ b/homeassistant/components/mqtt/button.py @@ -44,7 +44,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT button through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttButton, diff --git a/homeassistant/components/mqtt/camera.py b/homeassistant/components/mqtt/camera.py index 3b6e616c1c7..fa550b9fd0c 100644 --- a/homeassistant/components/mqtt/camera.py +++ b/homeassistant/components/mqtt/camera.py @@ -61,7 +61,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT camera through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttCamera, diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index 0f7358e0326..f63c9ecc7ae 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -379,7 +379,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT climate through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttClimate, diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index a3bdcf06efa..bd79c0f9470 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -220,7 +220,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT cover through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttCover, diff --git a/homeassistant/components/mqtt/device_automation.py b/homeassistant/components/mqtt/device_automation.py index 25fb510a07e..8d23d32326b 100644 --- a/homeassistant/components/mqtt/device_automation.py +++ b/homeassistant/components/mqtt/device_automation.py @@ -29,7 +29,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> N """Set up MQTT device automation dynamically through MQTT discovery.""" setup = functools.partial(_async_setup_automation, hass, config_entry=config_entry) - await async_setup_non_entity_entry_helper( + async_setup_non_entity_entry_helper( hass, "device_automation", setup, DISCOVERY_SCHEMA ) diff --git a/homeassistant/components/mqtt/device_tracker.py b/homeassistant/components/mqtt/device_tracker.py index a45b2adf02c..082483a64a3 100644 --- a/homeassistant/components/mqtt/device_tracker.py +++ b/homeassistant/components/mqtt/device_tracker.py @@ -83,7 +83,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT event through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttDeviceTracker, diff --git a/homeassistant/components/mqtt/event.py b/homeassistant/components/mqtt/event.py index 8e30979be78..15b70b1b98d 100644 --- a/homeassistant/components/mqtt/event.py +++ b/homeassistant/components/mqtt/event.py @@ -74,7 +74,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT event through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttEvent, diff --git a/homeassistant/components/mqtt/fan.py b/homeassistant/components/mqtt/fan.py index 0018c319a0c..1933b5e17b5 100644 --- a/homeassistant/components/mqtt/fan.py +++ b/homeassistant/components/mqtt/fan.py @@ -191,7 +191,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT fan through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttFan, diff --git a/homeassistant/components/mqtt/humidifier.py b/homeassistant/components/mqtt/humidifier.py index 0db2dadd5cf..8f7eda21240 100644 --- a/homeassistant/components/mqtt/humidifier.py +++ b/homeassistant/components/mqtt/humidifier.py @@ -184,7 +184,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT humidifier through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttHumidifier, diff --git a/homeassistant/components/mqtt/image.py b/homeassistant/components/mqtt/image.py index b11b5520174..d5930a1668a 100644 --- a/homeassistant/components/mqtt/image.py +++ b/homeassistant/components/mqtt/image.py @@ -83,7 +83,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT image through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttImage, diff --git a/homeassistant/components/mqtt/lawn_mower.py b/homeassistant/components/mqtt/lawn_mower.py index 6022ce8afc3..853ce743f12 100644 --- a/homeassistant/components/mqtt/lawn_mower.py +++ b/homeassistant/components/mqtt/lawn_mower.py @@ -81,7 +81,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lawn mower through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttLawnMower, diff --git a/homeassistant/components/mqtt/light/__init__.py b/homeassistant/components/mqtt/light/__init__.py index 29c5cc20d91..ac2d1ff14ee 100644 --- a/homeassistant/components/mqtt/light/__init__.py +++ b/homeassistant/components/mqtt/light/__init__.py @@ -70,7 +70,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lights through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, None, diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index f4a20d538ae..22b0e24b3c6 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -117,7 +117,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lock through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttLock, diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 713b63ef103..090433c7327 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -4,7 +4,6 @@ from __future__ import annotations from abc import ABC, abstractmethod from collections.abc import Callable, Coroutine -import functools from functools import partial import logging from typing import TYPE_CHECKING, Any, Protocol, cast, final @@ -169,17 +168,20 @@ def async_handle_schema_error( ) -async def _async_discover( +def _handle_discovery_failure( hass: HomeAssistant, - domain: str, - setup: Callable[[MQTTDiscoveryPayload], None] | None, - async_setup: Callable[[MQTTDiscoveryPayload], Coroutine[Any, Any, None]] | None, discovery_payload: MQTTDiscoveryPayload, ) -> None: - """Discover and add an MQTT entity, automation or tag. + """Handle discovery failure.""" + discovery_hash = discovery_payload.discovery_data[ATTR_DISCOVERY_HASH] + clear_discovery_hash(hass, discovery_hash) + async_dispatcher_send(hass, MQTT_DISCOVERY_DONE.format(*discovery_hash), None) - setup is to be run in the event loop when there is nothing to be awaited. - """ + +def _verify_mqtt_config_entry_enabled_for_discovery( + hass: HomeAssistant, domain: str, discovery_payload: MQTTDiscoveryPayload +) -> bool: + """Verify MQTT config entry is enabled or log warning.""" if not mqtt_config_entry_enabled(hass): _LOGGER.warning( ( @@ -189,23 +191,8 @@ async def _async_discover( domain, discovery_payload, ) - return - discovery_data = discovery_payload.discovery_data - try: - if setup is not None: - setup(discovery_payload) - elif async_setup is not None: - await async_setup(discovery_payload) - except vol.Invalid as err: - discovery_hash = discovery_data[ATTR_DISCOVERY_HASH] - clear_discovery_hash(hass, discovery_hash) - async_dispatcher_send(hass, MQTT_DISCOVERY_DONE.format(*discovery_hash), None) - async_handle_schema_error(discovery_payload, err) - except Exception: - discovery_hash = discovery_data[ATTR_DISCOVERY_HASH] - clear_discovery_hash(hass, discovery_hash) - async_dispatcher_send(hass, MQTT_DISCOVERY_DONE.format(*discovery_hash), None) - raise + return False + return True class _SetupNonEntityHelperCallbackProtocol(Protocol): # pragma: no cover @@ -216,7 +203,8 @@ class _SetupNonEntityHelperCallbackProtocol(Protocol): # pragma: no cover ) -> None: ... -async def async_setup_non_entity_entry_helper( +@callback +def async_setup_non_entity_entry_helper( hass: HomeAssistant, domain: str, async_setup: _SetupNonEntityHelperCallbackProtocol, @@ -225,25 +213,35 @@ async def async_setup_non_entity_entry_helper( """Set up automation or tag creation dynamically through MQTT discovery.""" mqtt_data = hass.data[DATA_MQTT] - async def async_setup_from_discovery( + async def _async_setup_non_entity_entry_from_discovery( discovery_payload: MQTTDiscoveryPayload, ) -> None: """Set up an MQTT entity, automation or tag from discovery.""" - config: ConfigType = discovery_schema(discovery_payload) - await async_setup(config, discovery_data=discovery_payload.discovery_data) + if not _verify_mqtt_config_entry_enabled_for_discovery( + hass, domain, discovery_payload + ): + return + try: + config: ConfigType = discovery_schema(discovery_payload) + await async_setup(config, discovery_data=discovery_payload.discovery_data) + except vol.Invalid as err: + _handle_discovery_failure(hass, discovery_payload) + async_handle_schema_error(discovery_payload, err) + except Exception: + _handle_discovery_failure(hass, discovery_payload) + raise mqtt_data.reload_dispatchers.append( async_dispatcher_connect( hass, MQTT_DISCOVERY_NEW.format(domain, "mqtt"), - functools.partial( - _async_discover, hass, domain, None, async_setup_from_discovery - ), + _async_setup_non_entity_entry_from_discovery, ) ) -async def async_setup_entity_entry_helper( +@callback +def async_setup_entity_entry_helper( hass: HomeAssistant, entry: ConfigEntry, entity_class: type[MqttEntity] | None, @@ -257,27 +255,36 @@ async def async_setup_entity_entry_helper( mqtt_data = hass.data[DATA_MQTT] @callback - def async_setup_from_discovery( + def _async_setup_entity_entry_from_discovery( discovery_payload: MQTTDiscoveryPayload, ) -> None: """Set up an MQTT entity from discovery.""" nonlocal entity_class - config: DiscoveryInfoType = discovery_schema(discovery_payload) - if schema_class_mapping is not None: - entity_class = schema_class_mapping[config[CONF_SCHEMA]] - if TYPE_CHECKING: - assert entity_class is not None - async_add_entities( - [entity_class(hass, config, entry, discovery_payload.discovery_data)] - ) + if not _verify_mqtt_config_entry_enabled_for_discovery( + hass, domain, discovery_payload + ): + return + try: + config: DiscoveryInfoType = discovery_schema(discovery_payload) + if schema_class_mapping is not None: + entity_class = schema_class_mapping[config[CONF_SCHEMA]] + if TYPE_CHECKING: + assert entity_class is not None + async_add_entities( + [entity_class(hass, config, entry, discovery_payload.discovery_data)] + ) + except vol.Invalid as err: + _handle_discovery_failure(hass, discovery_payload) + async_handle_schema_error(discovery_payload, err) + except Exception: + _handle_discovery_failure(hass, discovery_payload) + raise mqtt_data.reload_dispatchers.append( async_dispatcher_connect( hass, MQTT_DISCOVERY_NEW.format(domain, "mqtt"), - functools.partial( - _async_discover, hass, domain, async_setup_from_discovery, None - ), + _async_setup_entity_entry_from_discovery, ) ) diff --git a/homeassistant/components/mqtt/notify.py b/homeassistant/components/mqtt/notify.py index edc53e572ec..581660b6ecf 100644 --- a/homeassistant/components/mqtt/notify.py +++ b/homeassistant/components/mqtt/notify.py @@ -40,7 +40,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT notify through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttNotify, diff --git a/homeassistant/components/mqtt/number.py b/homeassistant/components/mqtt/number.py index f3d7a432e34..50a4f398c7d 100644 --- a/homeassistant/components/mqtt/number.py +++ b/homeassistant/components/mqtt/number.py @@ -110,7 +110,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT number through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttNumber, diff --git a/homeassistant/components/mqtt/scene.py b/homeassistant/components/mqtt/scene.py index c51166ce457..994a77d3abb 100644 --- a/homeassistant/components/mqtt/scene.py +++ b/homeassistant/components/mqtt/scene.py @@ -44,7 +44,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT scene through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttScene, diff --git a/homeassistant/components/mqtt/select.py b/homeassistant/components/mqtt/select.py index 0adc3344ed3..ea0a0886082 100644 --- a/homeassistant/components/mqtt/select.py +++ b/homeassistant/components/mqtt/select.py @@ -61,7 +61,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT select through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttSelect, diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index 4039ce607e9..12de26b2358 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -110,7 +110,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT sensor through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttSensor, diff --git a/homeassistant/components/mqtt/siren.py b/homeassistant/components/mqtt/siren.py index 5b5835d41d3..49645f7b1b4 100644 --- a/homeassistant/components/mqtt/siren.py +++ b/homeassistant/components/mqtt/siren.py @@ -114,7 +114,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT siren through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttSiren, diff --git a/homeassistant/components/mqtt/switch.py b/homeassistant/components/mqtt/switch.py index bf5af232e04..0ba4c003078 100644 --- a/homeassistant/components/mqtt/switch.py +++ b/homeassistant/components/mqtt/switch.py @@ -60,7 +60,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT switch through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttSwitch, diff --git a/homeassistant/components/mqtt/tag.py b/homeassistant/components/mqtt/tag.py index 59d9c3f87ff..ec6142401e5 100644 --- a/homeassistant/components/mqtt/tag.py +++ b/homeassistant/components/mqtt/tag.py @@ -57,7 +57,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> N """Set up MQTT tag scanner dynamically through MQTT discovery.""" setup = functools.partial(_async_setup_tag, hass, config_entry=config_entry) - await async_setup_non_entity_entry_helper(hass, TAG, setup, DISCOVERY_SCHEMA) + async_setup_non_entity_entry_helper(hass, TAG, setup, DISCOVERY_SCHEMA) async def _async_setup_tag( diff --git a/homeassistant/components/mqtt/text.py b/homeassistant/components/mqtt/text.py index ab79edd3150..73adaa2cb0c 100644 --- a/homeassistant/components/mqtt/text.py +++ b/homeassistant/components/mqtt/text.py @@ -96,7 +96,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT text through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttTextEntity, diff --git a/homeassistant/components/mqtt/update.py b/homeassistant/components/mqtt/update.py index 74d271eb95e..eecd7b967de 100644 --- a/homeassistant/components/mqtt/update.py +++ b/homeassistant/components/mqtt/update.py @@ -80,7 +80,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT update entity through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttUpdate, diff --git a/homeassistant/components/mqtt/vacuum.py b/homeassistant/components/mqtt/vacuum.py index 0b48b7a68ef..fb988751d6b 100644 --- a/homeassistant/components/mqtt/vacuum.py +++ b/homeassistant/components/mqtt/vacuum.py @@ -236,7 +236,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT vacuum through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttStateVacuum, diff --git a/homeassistant/components/mqtt/valve.py b/homeassistant/components/mqtt/valve.py index 33b2c81499c..f3c76462269 100644 --- a/homeassistant/components/mqtt/valve.py +++ b/homeassistant/components/mqtt/valve.py @@ -140,7 +140,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT valve through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttValve, diff --git a/homeassistant/components/mqtt/water_heater.py b/homeassistant/components/mqtt/water_heater.py index 75e2373b01b..ac3c8aacc92 100644 --- a/homeassistant/components/mqtt/water_heater.py +++ b/homeassistant/components/mqtt/water_heater.py @@ -167,7 +167,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT water heater device through YAML and through MQTT discovery.""" - await async_setup_entity_entry_helper( + async_setup_entity_entry_helper( hass, config_entry, MqttWaterHeater,