Drop MQTT import flow (#66160)

* Drop MQTT import flow

* Reload manually configured MQTT entities when config entry is setup

* Address review comments

* Actually remove the import flow
This commit is contained in:
Erik Montnemery 2022-02-10 21:09:57 +01:00 committed by GitHub
parent dc7ab40acd
commit fe38e6ba87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 494 additions and 155 deletions

View file

@ -21,7 +21,6 @@ import certifi
import jinja2
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import websocket_api
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
@ -37,6 +36,7 @@ from homeassistant.const import (
CONF_VALUE_TEMPLATE,
EVENT_HOMEASSISTANT_STARTED,
EVENT_HOMEASSISTANT_STOP,
SERVICE_RELOAD,
Platform,
)
from homeassistant.core import (
@ -76,6 +76,7 @@ from .const import (
CONF_TOPIC,
CONF_WILL_MESSAGE,
DATA_MQTT_CONFIG,
DATA_MQTT_RELOAD_NEEDED,
DEFAULT_BIRTH,
DEFAULT_DISCOVERY,
DEFAULT_ENCODING,
@ -580,22 +581,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
websocket_api.async_register_command(hass, websocket_mqtt_info)
debug_info.initialize(hass)
if conf is None:
# If we have a config entry, setup is done by that config entry.
# If there is no config entry, this should fail.
return bool(hass.config_entries.async_entries(DOMAIN))
conf = dict(conf)
hass.data[DATA_MQTT_CONFIG] = conf
# Only import if we haven't before.
if not hass.config_entries.async_entries(DOMAIN):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={}
)
)
if conf:
conf = dict(conf)
hass.data[DATA_MQTT_CONFIG] = conf
return True
@ -609,12 +597,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Load a config entry."""
conf = hass.data.get(DATA_MQTT_CONFIG)
# Config entry was created because user had configuration.yaml entry
# They removed that, so remove entry.
if conf is None and entry.source == config_entries.SOURCE_IMPORT:
hass.async_create_task(hass.config_entries.async_remove(entry.entry_id))
return False
# If user didn't have configuration.yaml config, generate defaults
if conf is None:
conf = CONFIG_SCHEMA({DOMAIN: dict(entry.data)})[DOMAIN]
@ -735,6 +717,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if conf.get(CONF_DISCOVERY):
await _async_setup_discovery(hass, conf, entry)
if DATA_MQTT_RELOAD_NEEDED in hass.data:
hass.data.pop(DATA_MQTT_RELOAD_NEEDED)
await hass.services.async_call(
DOMAIN,
SERVICE_RELOAD,
{},
blocking=False,
)
return True

View file

@ -35,10 +35,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -47,10 +46,14 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -124,8 +127,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT alarm control panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, alarm.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -28,20 +28,20 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.helpers.event as evt
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from . import PLATFORMS, MqttValueTemplate, subscription
from . import MqttValueTemplate, subscription
from .. import mqtt
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN, PAYLOAD_NONE
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, PAYLOAD_NONE
from .debug_info import log_messages
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttAvailability,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -75,8 +75,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT binary sensor through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, binary_sensor.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -12,10 +12,9 @@ from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate
from . import MqttCommandTemplate
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -23,9 +22,13 @@ from .const import (
CONF_ENCODING,
CONF_QOS,
CONF_RETAIN,
DOMAIN,
)
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
CONF_PAYLOAD_PRESS = "payload_press"
DEFAULT_NAME = "MQTT Button"
@ -52,8 +55,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT button through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, button.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -12,14 +12,18 @@ from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, subscription
from . import subscription
from .. import mqtt
from .const import CONF_QOS, CONF_TOPIC, DOMAIN
from .const import CONF_QOS, CONF_TOPIC
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
DEFAULT_NAME = "MQTT Camera"
@ -49,8 +53,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT camera through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, camera.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -53,20 +53,23 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import (
MQTT_BASE_PLATFORM_SCHEMA,
PLATFORMS,
MqttCommandTemplate,
MqttValueTemplate,
subscription,
)
from .. import mqtt
from .const import CONF_ENCODING, CONF_QOS, CONF_RETAIN, DOMAIN, PAYLOAD_NONE
from .const import CONF_ENCODING, CONF_QOS, CONF_RETAIN, PAYLOAD_NONE
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -303,8 +306,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT climate device through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, climate.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -84,17 +84,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
step_id="broker", data_schema=vol.Schema(fields), errors=errors
)
async def async_step_import(self, user_input):
"""Import a config entry.
Special type of import, we're not actually going to store any data.
Instead, we're going to rely on the values that are in config file.
"""
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
return self.async_create_entry(title="configuration.yaml", data={})
async def async_step_hassio(self, discovery_info: HassioServiceInfo) -> FlowResult:
"""Receive a Hass.io discovery."""
await self._async_handle_discovery_without_unique_id()

View file

@ -23,6 +23,7 @@ CONF_TOPIC = "topic"
CONF_WILL_MESSAGE = "will_message"
DATA_MQTT_CONFIG = "mqtt_config"
DATA_MQTT_RELOAD_NEEDED = "mqtt_reload_needed"
DEFAULT_PREFIX = "homeassistant"
DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status"

View file

@ -37,10 +37,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TOPIC,
@ -48,10 +47,14 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -217,8 +220,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT cover through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, cover.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -32,7 +32,6 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util.percentage import (
int_states_in_range,
@ -40,7 +39,7 @@ from homeassistant.util.percentage import (
ranged_value_to_percentage,
)
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -50,11 +49,15 @@ from .const import (
CONF_RETAIN,
CONF_STATE_TOPIC,
CONF_STATE_VALUE_TEMPLATE,
DOMAIN,
PAYLOAD_NONE,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
CONF_PERCENTAGE_STATE_TOPIC = "percentage_state_topic"
CONF_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"
@ -213,8 +216,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT fan through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, fan.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -27,10 +27,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -40,11 +39,15 @@ from .const import (
CONF_RETAIN,
CONF_STATE_TOPIC,
CONF_STATE_VALUE_TEMPLATE,
DOMAIN,
PAYLOAD_NONE,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
CONF_AVAILABLE_MODES_LIST = "modes"
CONF_DEVICE_CLASS = "device_class"
@ -157,8 +160,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT humidifier through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, humidifier.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -8,11 +8,9 @@ import voluptuous as vol
from homeassistant.components import light
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .. import DOMAIN, PLATFORMS
from ..mixins import async_setup_entry_helper
from ..mixins import async_setup_entry_helper, async_setup_platform_helper
from .schema import CONF_SCHEMA, MQTT_LIGHT_SCHEMA_SCHEMA
from .schema_basic import (
DISCOVERY_SCHEMA_BASIC,
@ -69,8 +67,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT light through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, light.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(hass, config_entry, async_add_entities):

View file

@ -12,10 +12,9 @@ from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttValueTemplate, subscription
from . import MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TOPIC,
@ -23,10 +22,14 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
CONF_PAYLOAD_LOCK = "payload_lock"
CONF_PAYLOAD_UNLOCK = "payload_unlock"
@ -73,8 +76,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT lock panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, lock.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -5,9 +5,11 @@ from abc import abstractmethod
from collections.abc import Callable
import json
import logging
from typing import Any, Protocol
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_CONFIGURATION_URL,
ATTR_MANUFACTURER,
@ -23,7 +25,7 @@ from homeassistant.const import (
CONF_UNIQUE_ID,
CONF_VALUE_TEMPLATE,
)
from homeassistant.core import callback
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import (
config_validation as cv,
device_registry as dr,
@ -40,9 +42,18 @@ from homeassistant.helpers.entity import (
async_generate_entity_id,
validate_entity_category,
)
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType
from . import DATA_MQTT, MqttValueTemplate, async_publish, debug_info, subscription
from . import (
DATA_MQTT,
PLATFORMS,
MqttValueTemplate,
async_publish,
debug_info,
subscription,
)
from .const import (
ATTR_DISCOVERY_HASH,
ATTR_DISCOVERY_PAYLOAD,
@ -51,6 +62,7 @@ from .const import (
CONF_ENCODING,
CONF_QOS,
CONF_TOPIC,
DATA_MQTT_RELOAD_NEEDED,
DEFAULT_ENCODING,
DEFAULT_PAYLOAD_AVAILABLE,
DEFAULT_PAYLOAD_NOT_AVAILABLE,
@ -210,6 +222,20 @@ MQTT_ENTITY_COMMON_SCHEMA = MQTT_AVAILABILITY_SCHEMA.extend(
)
class SetupEntity(Protocol):
"""Protocol type for async_setup_entities."""
async def __call__(
self,
hass: HomeAssistant,
async_add_entities: AddEntitiesCallback,
config: ConfigType,
config_entry: ConfigEntry | None = None,
discovery_data: dict[str, Any] | None = None,
) -> None:
"""Define setup_entities type."""
async def async_setup_entry_helper(hass, domain, async_setup, schema):
"""Set up entity, automation or tag creation dynamically through MQTT discovery."""
@ -232,6 +258,26 @@ async def async_setup_entry_helper(hass, domain, async_setup, schema):
)
async def async_setup_platform_helper(
hass: HomeAssistant,
platform_domain: str,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
async_setup_entities: SetupEntity,
) -> None:
"""Return true if platform setup should be aborted."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
if not bool(hass.config_entries.async_entries(DOMAIN)):
hass.data[DATA_MQTT_RELOAD_NEEDED] = None
_LOGGER.warning(
"MQTT integration is not setup, skipping setup of manually configured "
"MQTT %s",
platform_domain,
)
return
await async_setup_entities(hass, async_add_entities, config)
def init_entity_id_from_config(hass, entity, config, entity_id_format):
"""Set entity_id from object_id if defined in config."""
if CONF_OBJECT_ID in config:

View file

@ -23,11 +23,10 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -36,10 +35,14 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -103,8 +106,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT number through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, number.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -12,18 +12,17 @@ from homeassistant.const import CONF_ICON, CONF_NAME, CONF_PAYLOAD_ON, CONF_UNIQ
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS
from .. import mqtt
from .const import CONF_COMMAND_TOPIC, CONF_ENCODING, CONF_QOS, CONF_RETAIN, DOMAIN
from .const import CONF_COMMAND_TOPIC, CONF_ENCODING, CONF_QOS, CONF_RETAIN
from .mixins import (
CONF_OBJECT_ID,
MQTT_AVAILABILITY_SCHEMA,
MqttAvailability,
MqttDiscoveryUpdate,
async_setup_entry_helper,
async_setup_platform_helper,
init_entity_id_from_config,
)
@ -52,8 +51,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT scene through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, scene.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -13,11 +13,10 @@ from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -26,10 +25,14 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -67,8 +70,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT select through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, select.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -30,20 +30,20 @@ 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.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from . import PLATFORMS, MqttValueTemplate, subscription
from . import MqttValueTemplate, subscription
from .. import mqtt
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC, DOMAIN
from .const import CONF_ENCODING, CONF_QOS, CONF_STATE_TOPIC
from .debug_info import log_messages
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttAvailability,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
_LOGGER = logging.getLogger(__name__)
@ -120,8 +120,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT sensors through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, sensor.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -36,10 +36,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttCommandTemplate, MqttValueTemplate, subscription
from . import MqttCommandTemplate, MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TEMPLATE,
@ -49,12 +48,16 @@ from .const import (
CONF_RETAIN,
CONF_STATE_TOPIC,
CONF_STATE_VALUE_TEMPLATE,
DOMAIN,
PAYLOAD_EMPTY_JSON,
PAYLOAD_NONE,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
DEFAULT_NAME = "MQTT Siren"
DEFAULT_PAYLOAD_ON = "ON"
@ -118,8 +121,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT siren through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, siren.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -20,11 +20,10 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import PLATFORMS, MqttValueTemplate, subscription
from . import MqttValueTemplate, subscription
from .. import mqtt
from .const import (
CONF_COMMAND_TOPIC,
@ -32,11 +31,15 @@ from .const import (
CONF_QOS,
CONF_RETAIN,
CONF_STATE_TOPIC,
DOMAIN,
PAYLOAD_NONE,
)
from .debug_info import log_messages
from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper
from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entry_helper,
async_setup_platform_helper,
)
MQTT_SWITCH_ATTRIBUTES_BLOCKED = frozenset(
{
@ -75,8 +78,9 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up MQTT switch through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, switch.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(

View file

@ -3,11 +3,9 @@ import functools
import voluptuous as vol
from homeassistant.components.vacuum import DOMAIN
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.components import vacuum
from .. import DOMAIN as MQTT_DOMAIN, PLATFORMS
from ..mixins import async_setup_entry_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,
@ -44,8 +42,9 @@ PLATFORM_SCHEMA = vol.All(
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up MQTT vacuum through configuration.yaml."""
await async_setup_reload_service(hass, MQTT_DOMAIN, PLATFORMS)
await _async_setup_entity(hass, async_add_entities, config)
await async_setup_platform_helper(
hass, vacuum.DOMAIN, config, async_add_entities, _async_setup_entity
)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -53,7 +52,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, DOMAIN, setup, DISCOVERY_SCHEMA)
await async_setup_entry_helper(hass, vacuum.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(

View file

@ -53,6 +53,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -840,3 +841,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = alarm_control_panel.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = alarm_control_panel.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -38,6 +38,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_reload_with_config,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_unique_id,
@ -879,6 +880,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = binary_sensor.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
async def test_cleanup_triggers_and_restoring_state(
hass, mqtt_mock, caplog, tmp_path, freezer
):

View file

@ -26,6 +26,7 @@ from .test_common import (
help_test_entity_id_update_discovery_update,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -405,3 +406,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = button.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = button.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -27,6 +27,7 @@ from .test_common import (
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -252,3 +253,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = camera.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = camera.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -58,6 +58,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -1422,3 +1423,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = CLIMATE_DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = CLIMATE_DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -21,7 +21,7 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.setup import async_setup_component
from tests.common import async_fire_mqtt_message, mock_registry
from tests.common import MockConfigEntry, async_fire_mqtt_message, mock_registry
DEFAULT_CONFIG_DEVICE_INFO_ID = {
"identifiers": ["helloworld"],
@ -1619,7 +1619,61 @@ async def help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config
assert hass.states.get(f"{domain}.test_old_2")
assert len(hass.states.async_all(domain)) == 2
# Create temporary fixture for configuration.yaml based on the supplied config and test a reload with this new config
# Create temporary fixture for configuration.yaml based on the supplied config and
# test a reload with this new config
new_config_1 = copy.deepcopy(config)
new_config_1["name"] = "test_new_1"
new_config_2 = copy.deepcopy(config)
new_config_2["name"] = "test_new_2"
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]
)
assert len(hass.states.async_all(domain)) == 3
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")
async def help_test_reloadable_late(hass, caplog, tmp_path, domain, config):
"""Test reloading an MQTT platform when config entry is setup late."""
# Create and test an old config of 2 entities based on the config supplied
old_config_1 = copy.deepcopy(config)
old_config_1["name"] = "test_old_1"
old_config_2 = copy.deepcopy(config)
old_config_2["name"] = "test_old_2"
old_yaml_config_file = tmp_path / "configuration.yaml"
old_yaml_config = yaml.dump({domain: [old_config_1, old_config_2]})
old_yaml_config_file.write_text(old_yaml_config)
assert old_yaml_config_file.read_text() == old_yaml_config
assert await async_setup_component(
hass, domain, {domain: [old_config_1, old_config_2]}
)
await hass.async_block_till_done()
# No MQTT config entry, there should be a warning and no entities
assert (
"MQTT integration is not setup, skipping setup of manually "
f"configured MQTT {domain}"
) in caplog.text
assert len(hass.states.async_all(domain)) == 0
# User sets up a config entry, should succeed and entities will setup
entry = MockConfigEntry(domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"})
entry.add_to_hass(hass)
with patch.object(hass_config, "YAML_CONFIG_FILE", old_yaml_config_file):
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert len(hass.states.async_all(domain)) == 2
# Create temporary fixture for configuration.yaml based on the supplied config and
# test a reload with this new config
new_config_1 = copy.deepcopy(config)
new_config_1["name"] = "test_new_1"
new_config_2 = copy.deepcopy(config)

View file

@ -82,17 +82,34 @@ async def test_user_connection_fails(hass, mock_try_connection, mock_finish_setu
async def test_manual_config_set(
hass, mock_try_connection, mock_finish_setup, mqtt_client_mock
):
"""Test we ignore entry if manual config available."""
"""Test manual config does not create an entry, and entry can be setup late."""
# MQTT config present in yaml config
assert await async_setup_component(hass, "mqtt", {"mqtt": {"broker": "bla"}})
await hass.async_block_till_done()
assert len(mock_finish_setup.mock_calls) == 1
assert len(mock_finish_setup.mock_calls) == 0
mock_try_connection.return_value = True
# Start config flow
result = await hass.config_entries.flow.async_init(
"mqtt", context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "abort"
assert result["type"] == "form"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"broker": "127.0.0.1"}
)
assert result["type"] == "create_entry"
assert result["result"].data == {
"broker": "127.0.0.1",
"port": 1883,
"discovery": True,
}
# Check we tried the connection, with precedence for config entry settings
mock_try_connection.assert_called_once_with("127.0.0.1", 1883, None, None)
# Check config entry got setup
assert len(mock_finish_setup.mock_calls) == 1
async def test_user_single_instance(hass):

View file

@ -64,6 +64,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -3173,6 +3174,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = cover.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -51,6 +51,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -1803,3 +1804,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = fan.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = fan.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -52,6 +52,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -1174,3 +1175,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = humidifier.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = humidifier.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -1134,6 +1134,8 @@ async def test_setup_without_tls_config_uses_tlsv1_under_python36(hass):
mqtt.CONF_BIRTH_MESSAGE: {
mqtt.ATTR_TOPIC: "birth",
mqtt.ATTR_PAYLOAD: "birth",
mqtt.ATTR_QOS: 0,
mqtt.ATTR_RETAIN: False,
},
}
],
@ -1162,6 +1164,8 @@ async def test_custom_birth_message(hass, mqtt_client_mock, mqtt_mock):
mqtt.CONF_BIRTH_MESSAGE: {
mqtt.ATTR_TOPIC: "homeassistant/status",
mqtt.ATTR_PAYLOAD: "online",
mqtt.ATTR_QOS: 0,
mqtt.ATTR_RETAIN: False,
},
}
],
@ -1205,6 +1209,8 @@ async def test_no_birth_message(hass, mqtt_client_mock, mqtt_mock):
mqtt.CONF_BIRTH_MESSAGE: {
mqtt.ATTR_TOPIC: "homeassistant/status",
mqtt.ATTR_PAYLOAD: "online",
mqtt.ATTR_QOS: 0,
mqtt.ATTR_RETAIN: False,
},
}
],
@ -1214,17 +1220,16 @@ async def test_delayed_birth_message(hass, mqtt_client_mock, mqtt_config):
hass.state = CoreState.starting
birth = asyncio.Event()
result = await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: mqtt_config})
assert result
await hass.async_block_till_done()
# Workaround: asynctest==0.13 fails on @functools.lru_cache
spec = dir(hass.data["mqtt"])
spec.remove("_matching_subscriptions")
entry = MockConfigEntry(domain=mqtt.DOMAIN, data=mqtt_config)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
mqtt_component_mock = MagicMock(
return_value=hass.data["mqtt"],
spec_set=spec,
spec_set=hass.data["mqtt"],
wraps=hass.data["mqtt"],
)
mqtt_component_mock._mqttc = mqtt_client_mock
@ -1261,6 +1266,8 @@ async def test_delayed_birth_message(hass, mqtt_client_mock, mqtt_config):
mqtt.CONF_WILL_MESSAGE: {
mqtt.ATTR_TOPIC: "death",
mqtt.ATTR_PAYLOAD: "death",
mqtt.ATTR_QOS: 0,
mqtt.ATTR_RETAIN: False,
},
}
],
@ -1317,9 +1324,28 @@ async def test_mqtt_subscribes_topics_on_connect(hass, mqtt_client_mock, mqtt_mo
assert calls == expected
async def test_setup_fails_without_config(hass):
"""Test if the MQTT component fails to load with no config."""
assert not await async_setup_component(hass, mqtt.DOMAIN, {})
async def test_setup_entry_with_config_override(hass, device_reg, mqtt_client_mock):
"""Test if the MQTT component loads with no config and config entry can be setup."""
data = (
'{ "device":{"identifiers":["0AFFD2"]},'
' "state_topic": "foobar/sensor",'
' "unique_id": "unique" }'
)
# mqtt present in yaml config
assert await async_setup_component(hass, mqtt.DOMAIN, {})
# User sets up a config entry
entry = MockConfigEntry(domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"})
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
# Discover a device to verify the entry was setup correctly
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
await hass.async_block_till_done()
device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")})
assert device_entry is not None
@pytest.mark.no_fail_on_log_exception

View file

@ -51,6 +51,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -840,6 +841,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = vacuum.DOMAIN
config = DEFAULT_CONFIG
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -202,6 +202,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -3496,6 +3497,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = light.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value,init_payload",
[

View file

@ -127,6 +127,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -1991,6 +1992,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = light.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value,init_payload",
[

View file

@ -65,6 +65,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -1181,6 +1182,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = light.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value,init_payload",
[

View file

@ -40,6 +40,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -646,6 +647,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = LOCK_DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -46,6 +46,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -699,6 +700,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = number.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -19,6 +19,7 @@ from .test_common import (
help_test_discovery_update,
help_test_discovery_update_unchanged,
help_test_reloadable,
help_test_reloadable_late,
help_test_unique_id,
)
@ -183,3 +184,10 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
domain = scene.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = scene.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)

View file

@ -37,6 +37,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -578,6 +579,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = select.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -45,6 +45,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_reload_with_config,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -972,6 +973,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = sensor.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
async def test_cleanup_triggers_and_restoring_state(
hass, mqtt_mock, caplog, tmp_path, freezer
):

View file

@ -38,6 +38,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -866,6 +867,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = siren.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -54,6 +54,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -607,6 +608,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = vacuum.DOMAIN
config = DEFAULT_CONFIG
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -36,6 +36,7 @@ from .test_common import (
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
help_test_reloadable,
help_test_reloadable_late,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
help_test_setting_blocked_attribute_via_mqtt_json_message,
@ -557,6 +558,13 @@ async def test_reloadable(hass, mqtt_mock, caplog, tmp_path):
await help_test_reloadable(hass, mqtt_mock, caplog, tmp_path, domain, config)
async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path):
"""Test reloading the MQTT platform with late entry setup."""
domain = switch.DOMAIN
config = DEFAULT_CONFIG[domain]
await help_test_reloadable_late(hass, caplog, tmp_path, domain, config)
@pytest.mark.parametrize(
"topic,value,attribute,attribute_value",
[

View file

@ -38,6 +38,7 @@ pytest.register_assert_rewrite("tests.common")
from tests.common import ( # noqa: E402, isort:skip
CLIENT_ID,
INSTANCES,
MockConfigEntry,
MockUser,
async_fire_mqtt_message,
async_test_home_assistant,
@ -590,17 +591,22 @@ async def mqtt_mock(hass, mqtt_client_mock, mqtt_config):
if mqtt_config is None:
mqtt_config = {mqtt.CONF_BROKER: "mock-broker", mqtt.CONF_BIRTH_MESSAGE: {}}
result = await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: mqtt_config})
assert result
await hass.async_block_till_done()
# Workaround: asynctest==0.13 fails on @functools.lru_cache
spec = dir(hass.data["mqtt"])
spec.remove("_matching_subscriptions")
entry = MockConfigEntry(
data=mqtt_config,
domain=mqtt.DOMAIN,
title="Tasmota",
)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
mqtt_component_mock = MagicMock(
return_value=hass.data["mqtt"],
spec_set=spec,
spec_set=hass.data["mqtt"],
wraps=hass.data["mqtt"],
)
mqtt_component_mock._mqttc = mqtt_client_mock