From 4e9be6d48e158342c401a994ec8acfee895eac1a Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 16 Apr 2026 21:00:00 +0200 Subject: [PATCH] Deprecate legacy device tracker --- .../components/device_tracker/legacy.py | 28 ++++++++ .../components/device_tracker/test_legacy.py | 64 ++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/legacy.py b/homeassistant/components/device_tracker/legacy.py index 5923aa2ed45..b91f85955e2 100644 --- a/homeassistant/components/device_tracker/legacy.py +++ b/homeassistant/components/device_tracker/legacy.py @@ -6,6 +6,7 @@ import asyncio from collections.abc import Callable, Coroutine, Sequence from datetime import datetime, timedelta import hashlib +import logging from types import ModuleType from typing import Any, Final, Protocol, final @@ -82,6 +83,8 @@ from .const import ( SourceType, ) +_LOGGER = logging.getLogger(__name__) + SERVICE_SEE: Final = "see" SOURCE_TYPES = [cls.value for cls in SourceType] @@ -128,6 +131,8 @@ SERVICE_SEE_PAYLOAD_SCHEMA: Final[vol.Schema] = vol.Schema( YAML_DEVICES: Final = "known_devices.yaml" EVENT_NEW_DEVICE: Final = "device_tracker_new_device" +DATA_LEGACY_TRACKERS: Final = "device_tracker.legacy_trackers" + class SeeCallback(Protocol): """Protocol type for DeviceTracker.see callback.""" @@ -243,8 +248,19 @@ async def _async_setup_integration( tracker = await get_tracker(hass, config) tracker_future.set_result(tracker) + warned_called_see = False + async def async_see_service(call: ServiceCall) -> None: """Service to see a device.""" + nonlocal warned_called_see + if not warned_called_see: + _LOGGER.warning( + "The %s.%s action is deprecated and will be removed in " + "Home Assistant Core 2027.5", + DOMAIN, + SERVICE_SEE, + ) + warned_called_see = True # Temp workaround for iOS, introduced in 0.65 data = dict(call.data) data.pop("hostname", None) @@ -327,6 +343,18 @@ class DeviceTrackerPlatform: try: scanner = None setup: bool | None = None + + legacy_trackers = hass.data.setdefault(DATA_LEGACY_TRACKERS, set()) + if full_name not in legacy_trackers: + legacy_trackers.add(full_name) + _LOGGER.warning( + "The legacy device tracker platform %s is being set up; legacy " + "device trackers are deprecated and will be removed in Home " + "Assistant Core 2027.5, please migrate to an integration which " + "uses a modern config entry based device tracker", + full_name, + ) + if hasattr(self.platform, "async_get_scanner"): scanner = await self.platform.async_get_scanner( hass, {DOMAIN: self.config} diff --git a/tests/components/device_tracker/test_legacy.py b/tests/components/device_tracker/test_legacy.py index c2df3a74770..e6dd04792bd 100644 --- a/tests/components/device_tracker/test_legacy.py +++ b/tests/components/device_tracker/test_legacy.py @@ -2,11 +2,20 @@ from unittest.mock import mock_open, patch +import pytest + +from homeassistant.components import device_tracker from homeassistant.components.device_tracker import legacy +from homeassistant.const import CONF_PLATFORM from homeassistant.core import HomeAssistant +from homeassistant.setup import async_setup_component from homeassistant.util.yaml import dump -from tests.common import patch_yaml_files +from .common import MockScanner, mock_legacy_device_tracker_setup + +from tests.common import assert_setup_component, patch_yaml_files + +TEST_PLATFORM = {device_tracker.DOMAIN: {CONF_PLATFORM: "test"}} def test_remove_device_from_config(hass: HomeAssistant) -> None: @@ -44,3 +53,56 @@ def test_remove_device_from_config(hass: HomeAssistant) -> None: " picture: /local/test2.png\n" " track: true\n" ) + + +async def test_see_service_deprecation_warning( + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test deprecation warning when calling device_tracker.see.""" + mock_legacy_device_tracker_setup(hass, MockScanner()) + with assert_setup_component(1, device_tracker.DOMAIN): + assert await async_setup_component(hass, device_tracker.DOMAIN, TEST_PLATFORM) + await hass.async_block_till_done() + + await hass.services.async_call( + device_tracker.DOMAIN, + legacy.SERVICE_SEE, + {"dev_id": "test_device", "location_name": "Work"}, + blocking=True, + ) + + assert ( + "The device_tracker.see action is deprecated and will be removed in " + "Home Assistant Core 2027.5" + ) in caplog.text + + caplog.clear() + + # Second call should not produce another warning + await hass.services.async_call( + device_tracker.DOMAIN, + legacy.SERVICE_SEE, + {"dev_id": "test_device", "location_name": "Work"}, + blocking=True, + ) + + assert "deprecated" not in caplog.text + + +async def test_legacy_platform_setup_deprecation_warning( + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test deprecation warning when setting up a legacy device tracker platform.""" + mock_legacy_device_tracker_setup(hass, MockScanner()) + with assert_setup_component(1, device_tracker.DOMAIN): + assert await async_setup_component(hass, device_tracker.DOMAIN, TEST_PLATFORM) + await hass.async_block_till_done() + + assert ( + "The legacy device tracker platform test.device_tracker is being set up; " + "legacy device trackers are deprecated and will be removed in Home " + "Assistant Core 2027.5, please migrate to an integration which " + "uses a modern config entry based device tracker" + ) in caplog.text