Convert mqtt entity discovery to use callbacks (#118200)

This commit is contained in:
J. Nick Koston 2024-05-26 16:12:40 -10:00 committed by GitHub
parent 1602c8063c
commit 811ec57c31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 80 additions and 73 deletions

View file

@ -127,7 +127,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT alarm control panel through YAML and through MQTT discovery.""" """Set up MQTT alarm control panel through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttAlarm, MqttAlarm,

View file

@ -71,7 +71,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT binary sensor through YAML and through MQTT discovery.""" """Set up MQTT binary sensor through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttBinarySensor, MqttBinarySensor,

View file

@ -44,7 +44,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT button through YAML and through MQTT discovery.""" """Set up MQTT button through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttButton, MqttButton,

View file

@ -61,7 +61,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT camera through YAML and through MQTT discovery.""" """Set up MQTT camera through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttCamera, MqttCamera,

View file

@ -379,7 +379,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT climate through YAML and through MQTT discovery.""" """Set up MQTT climate through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttClimate, MqttClimate,

View file

@ -220,7 +220,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT cover through YAML and through MQTT discovery.""" """Set up MQTT cover through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttCover, MqttCover,

View file

@ -29,7 +29,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> N
"""Set up MQTT device automation dynamically through MQTT discovery.""" """Set up MQTT device automation dynamically through MQTT discovery."""
setup = functools.partial(_async_setup_automation, hass, config_entry=config_entry) 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 hass, "device_automation", setup, DISCOVERY_SCHEMA
) )

View file

@ -83,7 +83,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT event through YAML and through MQTT discovery.""" """Set up MQTT event through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttDeviceTracker, MqttDeviceTracker,

View file

@ -74,7 +74,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT event through YAML and through MQTT discovery.""" """Set up MQTT event through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttEvent, MqttEvent,

View file

@ -191,7 +191,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT fan through YAML and through MQTT discovery.""" """Set up MQTT fan through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttFan, MqttFan,

View file

@ -184,7 +184,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT humidifier through YAML and through MQTT discovery.""" """Set up MQTT humidifier through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttHumidifier, MqttHumidifier,

View file

@ -83,7 +83,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT image through YAML and through MQTT discovery.""" """Set up MQTT image through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttImage, MqttImage,

View file

@ -81,7 +81,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT lawn mower through YAML and through MQTT discovery.""" """Set up MQTT lawn mower through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttLawnMower, MqttLawnMower,

View file

@ -70,7 +70,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT lights through YAML and through MQTT discovery.""" """Set up MQTT lights through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
None, None,

View file

@ -117,7 +117,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT lock through YAML and through MQTT discovery.""" """Set up MQTT lock through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttLock, MqttLock,

View file

@ -4,7 +4,6 @@ from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
import functools
from functools import partial from functools import partial
import logging import logging
from typing import TYPE_CHECKING, Any, Protocol, cast, final 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, hass: HomeAssistant,
domain: str,
setup: Callable[[MQTTDiscoveryPayload], None] | None,
async_setup: Callable[[MQTTDiscoveryPayload], Coroutine[Any, Any, None]] | None,
discovery_payload: MQTTDiscoveryPayload, discovery_payload: MQTTDiscoveryPayload,
) -> None: ) -> 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): if not mqtt_config_entry_enabled(hass):
_LOGGER.warning( _LOGGER.warning(
( (
@ -189,23 +191,8 @@ async def _async_discover(
domain, domain,
discovery_payload, discovery_payload,
) )
return return False
discovery_data = discovery_payload.discovery_data return True
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
class _SetupNonEntityHelperCallbackProtocol(Protocol): # pragma: no cover class _SetupNonEntityHelperCallbackProtocol(Protocol): # pragma: no cover
@ -216,7 +203,8 @@ class _SetupNonEntityHelperCallbackProtocol(Protocol): # pragma: no cover
) -> None: ... ) -> None: ...
async def async_setup_non_entity_entry_helper( @callback
def async_setup_non_entity_entry_helper(
hass: HomeAssistant, hass: HomeAssistant,
domain: str, domain: str,
async_setup: _SetupNonEntityHelperCallbackProtocol, 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.""" """Set up automation or tag creation dynamically through MQTT discovery."""
mqtt_data = hass.data[DATA_MQTT] mqtt_data = hass.data[DATA_MQTT]
async def async_setup_from_discovery( async def _async_setup_non_entity_entry_from_discovery(
discovery_payload: MQTTDiscoveryPayload, discovery_payload: MQTTDiscoveryPayload,
) -> None: ) -> None:
"""Set up an MQTT entity, automation or tag from discovery.""" """Set up an MQTT entity, automation or tag from discovery."""
config: ConfigType = discovery_schema(discovery_payload) if not _verify_mqtt_config_entry_enabled_for_discovery(
await async_setup(config, discovery_data=discovery_payload.discovery_data) 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( mqtt_data.reload_dispatchers.append(
async_dispatcher_connect( async_dispatcher_connect(
hass, hass,
MQTT_DISCOVERY_NEW.format(domain, "mqtt"), MQTT_DISCOVERY_NEW.format(domain, "mqtt"),
functools.partial( _async_setup_non_entity_entry_from_discovery,
_async_discover, hass, domain, None, async_setup_from_discovery
),
) )
) )
async def async_setup_entity_entry_helper( @callback
def async_setup_entity_entry_helper(
hass: HomeAssistant, hass: HomeAssistant,
entry: ConfigEntry, entry: ConfigEntry,
entity_class: type[MqttEntity] | None, entity_class: type[MqttEntity] | None,
@ -257,27 +255,36 @@ async def async_setup_entity_entry_helper(
mqtt_data = hass.data[DATA_MQTT] mqtt_data = hass.data[DATA_MQTT]
@callback @callback
def async_setup_from_discovery( def _async_setup_entity_entry_from_discovery(
discovery_payload: MQTTDiscoveryPayload, discovery_payload: MQTTDiscoveryPayload,
) -> None: ) -> None:
"""Set up an MQTT entity from discovery.""" """Set up an MQTT entity from discovery."""
nonlocal entity_class nonlocal entity_class
config: DiscoveryInfoType = discovery_schema(discovery_payload) if not _verify_mqtt_config_entry_enabled_for_discovery(
if schema_class_mapping is not None: hass, domain, discovery_payload
entity_class = schema_class_mapping[config[CONF_SCHEMA]] ):
if TYPE_CHECKING: return
assert entity_class is not None try:
async_add_entities( config: DiscoveryInfoType = discovery_schema(discovery_payload)
[entity_class(hass, config, entry, discovery_payload.discovery_data)] 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( mqtt_data.reload_dispatchers.append(
async_dispatcher_connect( async_dispatcher_connect(
hass, hass,
MQTT_DISCOVERY_NEW.format(domain, "mqtt"), MQTT_DISCOVERY_NEW.format(domain, "mqtt"),
functools.partial( _async_setup_entity_entry_from_discovery,
_async_discover, hass, domain, async_setup_from_discovery, None
),
) )
) )

View file

@ -40,7 +40,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT notify through YAML and through MQTT discovery.""" """Set up MQTT notify through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttNotify, MqttNotify,

View file

@ -110,7 +110,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT number through YAML and through MQTT discovery.""" """Set up MQTT number through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttNumber, MqttNumber,

View file

@ -44,7 +44,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT scene through YAML and through MQTT discovery.""" """Set up MQTT scene through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttScene, MqttScene,

View file

@ -61,7 +61,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT select through YAML and through MQTT discovery.""" """Set up MQTT select through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttSelect, MqttSelect,

View file

@ -110,7 +110,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT sensor through YAML and through MQTT discovery.""" """Set up MQTT sensor through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttSensor, MqttSensor,

View file

@ -114,7 +114,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT siren through YAML and through MQTT discovery.""" """Set up MQTT siren through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttSiren, MqttSiren,

View file

@ -60,7 +60,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT switch through YAML and through MQTT discovery.""" """Set up MQTT switch through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttSwitch, MqttSwitch,

View file

@ -57,7 +57,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> N
"""Set up MQTT tag scanner dynamically through MQTT discovery.""" """Set up MQTT tag scanner dynamically through MQTT discovery."""
setup = functools.partial(_async_setup_tag, hass, config_entry=config_entry) 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( async def _async_setup_tag(

View file

@ -96,7 +96,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT text through YAML and through MQTT discovery.""" """Set up MQTT text through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttTextEntity, MqttTextEntity,

View file

@ -80,7 +80,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT update entity through YAML and through MQTT discovery.""" """Set up MQTT update entity through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttUpdate, MqttUpdate,

View file

@ -236,7 +236,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT vacuum through YAML and through MQTT discovery.""" """Set up MQTT vacuum through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttStateVacuum, MqttStateVacuum,

View file

@ -140,7 +140,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT valve through YAML and through MQTT discovery.""" """Set up MQTT valve through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttValve, MqttValve,

View file

@ -167,7 +167,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT water heater device through YAML and through MQTT discovery.""" """Set up MQTT water heater device through YAML and through MQTT discovery."""
await async_setup_entity_entry_helper( async_setup_entity_entry_helper(
hass, hass,
config_entry, config_entry,
MqttWaterHeater, MqttWaterHeater,