From 7feaf71b9e601cc56c2fbd719e03d4def3ae0e2f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 27 May 2026 11:27:34 +0200 Subject: [PATCH] Make TrackerEntity in_zones win over lat/long (#172313) --- .../components/device_tracker/entity.py | 16 ++++++++------ .../components/device_tracker/test_entity.py | 22 ++++++++++++++++--- .../mobile_app/test_device_tracker.py | 6 ++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/device_tracker/entity.py b/homeassistant/components/device_tracker/entity.py index 86c87b4653a4..1b88346e4e0c 100644 --- a/homeassistant/components/device_tracker/entity.py +++ b/homeassistant/components/device_tracker/entity.py @@ -221,8 +221,8 @@ class TrackerEntity( """Return the entity_id of zones the device is currently in. The list may be in any order; the base class sorts it by zone radius - and discards zones which do not exist. Ignored if latitude and - longitude are both set. + and discards zones which do not exist. Takes precedence over latitude + and longitude when set (including when set to an empty list). """ return self._attr_in_zones @@ -252,11 +252,7 @@ class TrackerEntity( @callback def _async_write_ha_state(self) -> None: """Calculate active zones.""" - if self.available and self.latitude is not None and self.longitude is not None: - self.__active_zone, self.__in_zones = zone.async_in_zones( - self.hass, self.latitude, self.longitude, self.location_accuracy - ) - elif (zones := self.in_zones) is not None: + if (zones := self.in_zones) is not None: zone_states = sorted( ( zone_state @@ -270,6 +266,12 @@ class TrackerEntity( None, ) self.__in_zones = [z.entity_id for z in zone_states] + elif ( + self.available and self.latitude is not None and self.longitude is not None + ): + self.__active_zone, self.__in_zones = zone.async_in_zones( + self.hass, self.latitude, self.longitude, self.location_accuracy + ) else: self.__active_zone = None self.__in_zones = None diff --git a/tests/components/device_tracker/test_entity.py b/tests/components/device_tracker/test_entity.py index 0f136a3470fb..690e19f30122 100644 --- a/tests/components/device_tracker/test_entity.py +++ b/tests/components/device_tracker/test_entity.py @@ -683,15 +683,31 @@ async def test_load_unload_entry_tracker( None, 1.0, 2.0, + STATE_HOME, + { + ATTR_SOURCE_TYPE: SourceType.GPS, + ATTR_GPS_ACCURACY: 0, + ATTR_IN_ZONES: ["zone.home"], + ATTR_LATITUDE: 1.0, + ATTR_LONGITUDE: 2.0, + }, + id="in_zones_wins_over_lat_long", + ), + pytest.param( + None, + [], + None, + 50.0, + 60.0, STATE_NOT_HOME, { ATTR_SOURCE_TYPE: SourceType.GPS, ATTR_GPS_ACCURACY: 0, ATTR_IN_ZONES: [], - ATTR_LATITUDE: 1.0, - ATTR_LONGITUDE: 2.0, + ATTR_LATITUDE: 50.0, + ATTR_LONGITUDE: 60.0, }, - id="in_zones_ignored_when_lat_long_set", + id="empty_in_zones_wins_over_lat_long", ), pytest.param( None, diff --git a/tests/components/mobile_app/test_device_tracker.py b/tests/components/mobile_app/test_device_tracker.py index 4f72791f8e02..01a9961fa0bb 100644 --- a/tests/components/mobile_app/test_device_tracker.py +++ b/tests/components/mobile_app/test_device_tracker.py @@ -172,16 +172,16 @@ async def setup_zone(hass: HomeAssistant) -> None: {"in_zones": []}, "not_home", ), - # in_zones + gps: gps wins, in_zones recomputed from coordinates + # in_zones + gps: in_zones wins, gps coordinates still reported as attributes ( {"gps": [10, 20], "in_zones": ["zone.school"]}, { "latitude": 10, "longitude": 20, "gps_accuracy": 30, - "in_zones": ["zone.home"], + "in_zones": ["zone.school"], }, - "home", + "School", ), ], )