From d092861926a090350c8d3208c62f598388ddfe94 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Thu, 26 May 2022 22:02:39 +0200 Subject: [PATCH] Move manual configuration of MQTT device_tracker to the integration key (#72493) --- homeassistant/components/mqtt/__init__.py | 4 +- .../mqtt/device_tracker/__init__.py | 10 ++- .../mqtt/device_tracker/schema_discovery.py | 26 +++++-- tests/components/mqtt/test_device_tracker.py | 69 +++++++++++++------ 4 files changed, 82 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index df5d52c443a..e8847375584 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -159,6 +159,7 @@ PLATFORMS = [ Platform.BUTTON, Platform.CAMERA, Platform.CLIMATE, + Platform.DEVICE_TRACKER, Platform.COVER, Platform.FAN, Platform.HUMIDIFIER, @@ -196,17 +197,18 @@ PLATFORM_CONFIG_SCHEMA_BASE = vol.Schema( vol.Optional(Platform.CAMERA.value): cv.ensure_list, vol.Optional(Platform.CLIMATE.value): cv.ensure_list, vol.Optional(Platform.COVER.value): cv.ensure_list, + vol.Optional(Platform.DEVICE_TRACKER.value): cv.ensure_list, vol.Optional(Platform.FAN.value): cv.ensure_list, vol.Optional(Platform.HUMIDIFIER.value): cv.ensure_list, vol.Optional(Platform.LIGHT.value): cv.ensure_list, vol.Optional(Platform.LOCK.value): cv.ensure_list, + vol.Optional(Platform.NUMBER.value): cv.ensure_list, vol.Optional(Platform.SCENE.value): cv.ensure_list, vol.Optional(Platform.SELECT.value): cv.ensure_list, vol.Optional(Platform.SIREN.value): cv.ensure_list, vol.Optional(Platform.SENSOR.value): cv.ensure_list, vol.Optional(Platform.SWITCH.value): cv.ensure_list, vol.Optional(Platform.VACUUM.value): cv.ensure_list, - vol.Optional(Platform.NUMBER.value): cv.ensure_list, } ) diff --git a/homeassistant/components/mqtt/device_tracker/__init__.py b/homeassistant/components/mqtt/device_tracker/__init__.py index 03574e6554b..bcd5bbd4ee1 100644 --- a/homeassistant/components/mqtt/device_tracker/__init__.py +++ b/homeassistant/components/mqtt/device_tracker/__init__.py @@ -1,7 +1,15 @@ """Support for tracking MQTT enabled devices.""" +import voluptuous as vol + +from homeassistant.components import device_tracker + +from ..mixins import warn_for_legacy_schema from .schema_discovery import async_setup_entry_from_discovery from .schema_yaml import PLATFORM_SCHEMA_YAML, async_setup_scanner_from_yaml -PLATFORM_SCHEMA = PLATFORM_SCHEMA_YAML +# Configuring MQTT Device Trackers under the device_tracker platform key is deprecated in HA Core 2022.6 +PLATFORM_SCHEMA = vol.All( + PLATFORM_SCHEMA_YAML, warn_for_legacy_schema(device_tracker.DOMAIN) +) async_setup_scanner = async_setup_scanner_from_yaml async_setup_entry = async_setup_entry_from_discovery diff --git a/homeassistant/components/mqtt/device_tracker/schema_discovery.py b/homeassistant/components/mqtt/device_tracker/schema_discovery.py index a7b597d0689..aa7506bd5e3 100644 --- a/homeassistant/components/mqtt/device_tracker/schema_discovery.py +++ b/homeassistant/components/mqtt/device_tracker/schema_discovery.py @@ -1,4 +1,5 @@ -"""Support for tracking MQTT enabled devices identified through discovery.""" +"""Support for tracking MQTT enabled devices.""" +import asyncio import functools import voluptuous as vol @@ -22,13 +23,18 @@ from .. import MqttValueTemplate, subscription from ... import mqtt from ..const import CONF_QOS, CONF_STATE_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_get_platform_config_from_yaml, + async_setup_entry_helper, +) CONF_PAYLOAD_HOME = "payload_home" CONF_PAYLOAD_NOT_HOME = "payload_not_home" CONF_SOURCE_TYPE = "source_type" -PLATFORM_SCHEMA_DISCOVERY = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend( +PLATFORM_SCHEMA_MODERN = mqtt.MQTT_RO_SCHEMA.extend( { vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_PAYLOAD_HOME, default=STATE_HOME): cv.string, @@ -37,11 +43,21 @@ PLATFORM_SCHEMA_DISCOVERY = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend( } ).extend(MQTT_ENTITY_COMMON_SCHEMA.schema) -DISCOVERY_SCHEMA = PLATFORM_SCHEMA_DISCOVERY.extend({}, extra=vol.REMOVE_EXTRA) +DISCOVERY_SCHEMA = PLATFORM_SCHEMA_MODERN.extend({}, extra=vol.REMOVE_EXTRA) async def async_setup_entry_from_discovery(hass, config_entry, async_add_entities): - """Set up MQTT device tracker dynamically through MQTT discovery.""" + """Set up MQTT device tracker configuration.yaml and dynamically through MQTT discovery.""" + # load and initialize platform config from configuration.yaml + await asyncio.gather( + *( + _async_setup_entity(hass, async_add_entities, config, config_entry) + for config in await async_get_platform_config_from_yaml( + hass, device_tracker.DOMAIN, PLATFORM_SCHEMA_MODERN + ) + ) + ) + # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/tests/components/mqtt/test_device_tracker.py b/tests/components/mqtt/test_device_tracker.py index c85fcef7dc4..020fbad6166 100644 --- a/tests/components/mqtt/test_device_tracker.py +++ b/tests/components/mqtt/test_device_tracker.py @@ -1,22 +1,17 @@ -"""The tests for the MQTT device tracker platform.""" +"""The tests for the MQTT device tracker platform using configuration.yaml.""" from unittest.mock import patch -import pytest - from homeassistant.components.device_tracker.const import DOMAIN, SOURCE_TYPE_BLUETOOTH from homeassistant.const import CONF_PLATFORM, STATE_HOME, STATE_NOT_HOME from homeassistant.setup import async_setup_component +from .test_common import help_test_setup_manual_entity_from_yaml + from tests.common import async_fire_mqtt_message -@pytest.fixture(autouse=True) -def setup_comp(hass, mqtt_mock): - """Set up mqtt component.""" - pass - - -async def test_ensure_device_tracker_platform_validation(hass): +# Deprecated in HA Core 2022.6 +async def test_legacy_ensure_device_tracker_platform_validation(hass, mqtt_mock): """Test if platform validation was done.""" async def mock_setup_scanner(hass, config, see, discovery_info=None): @@ -37,7 +32,8 @@ async def test_ensure_device_tracker_platform_validation(hass): assert mock_sp.call_count == 1 -async def test_new_message(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_new_message(hass, mock_device_tracker_conf, mqtt_mock): """Test new message.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -53,7 +49,10 @@ async def test_new_message(hass, mock_device_tracker_conf): assert hass.states.get(entity_id).state == location -async def test_single_level_wildcard_topic(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_single_level_wildcard_topic( + hass, mock_device_tracker_conf, mqtt_mock +): """Test single level wildcard topic.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -72,7 +71,10 @@ async def test_single_level_wildcard_topic(hass, mock_device_tracker_conf): assert hass.states.get(entity_id).state == location -async def test_multi_level_wildcard_topic(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_multi_level_wildcard_topic( + hass, mock_device_tracker_conf, mqtt_mock +): """Test multi level wildcard topic.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -91,7 +93,10 @@ async def test_multi_level_wildcard_topic(hass, mock_device_tracker_conf): assert hass.states.get(entity_id).state == location -async def test_single_level_wildcard_topic_not_matching(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_single_level_wildcard_topic_not_matching( + hass, mock_device_tracker_conf, mqtt_mock +): """Test not matching single level wildcard topic.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -110,7 +115,10 @@ async def test_single_level_wildcard_topic_not_matching(hass, mock_device_tracke assert hass.states.get(entity_id) is None -async def test_multi_level_wildcard_topic_not_matching(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_multi_level_wildcard_topic_not_matching( + hass, mock_device_tracker_conf, mqtt_mock +): """Test not matching multi level wildcard topic.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -129,8 +137,9 @@ async def test_multi_level_wildcard_topic_not_matching(hass, mock_device_tracker assert hass.states.get(entity_id) is None -async def test_matching_custom_payload_for_home_and_not_home( - hass, mock_device_tracker_conf +# Deprecated in HA Core 2022.6 +async def test_legacy_matching_custom_payload_for_home_and_not_home( + hass, mock_device_tracker_conf, mqtt_mock ): """Test custom payload_home sets state to home and custom payload_not_home sets state to not_home.""" dev_id = "paulus" @@ -161,8 +170,9 @@ async def test_matching_custom_payload_for_home_and_not_home( assert hass.states.get(entity_id).state == STATE_NOT_HOME -async def test_not_matching_custom_payload_for_home_and_not_home( - hass, mock_device_tracker_conf +# Deprecated in HA Core 2022.6 +async def test_legacy_not_matching_custom_payload_for_home_and_not_home( + hass, mock_device_tracker_conf, mqtt_mock ): """Test not matching payload does not set state to home or not_home.""" dev_id = "paulus" @@ -191,7 +201,8 @@ async def test_not_matching_custom_payload_for_home_and_not_home( assert hass.states.get(entity_id).state != STATE_NOT_HOME -async def test_matching_source_type(hass, mock_device_tracker_conf): +# Deprecated in HA Core 2022.6 +async def test_legacy_matching_source_type(hass, mock_device_tracker_conf, mqtt_mock): """Test setting source type.""" dev_id = "paulus" entity_id = f"{DOMAIN}.{dev_id}" @@ -215,3 +226,21 @@ async def test_matching_source_type(hass, mock_device_tracker_conf): async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() assert hass.states.get(entity_id).attributes["source_type"] == SOURCE_TYPE_BLUETOOTH + + +async def test_setup_with_modern_schema( + hass, caplog, tmp_path, mock_device_tracker_conf +): + """Test setup using the modern schema.""" + dev_id = "jan" + entity_id = f"{DOMAIN}.{dev_id}" + topic = "/location/jan" + + hass.config.components = {"zone"} + config = {"name": dev_id, "state_topic": topic} + + await help_test_setup_manual_entity_from_yaml( + hass, caplog, tmp_path, DOMAIN, config + ) + + assert hass.states.get(entity_id) is not None