Compare commits

...

1 Commits

Author SHA1 Message Date
Erik 37f5905245 Remove location_name property from mobile_app device tracker 2026-05-04 17:00:57 +02:00
2 changed files with 95 additions and 40 deletions
@@ -13,10 +13,7 @@ from homeassistant.components.device_tracker import (
ATTR_LOCATION_NAME,
TrackerEntity,
)
from homeassistant.components.zone import (
ENTITY_ID_FORMAT as ZONE_ENTITY_ID_FORMAT,
HOME_ZONE,
)
from homeassistant.components.zone import ENTITY_ID_FORMAT as ZONE_ENTITY_ID_FORMAT
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_BATTERY_LEVEL,
@@ -24,9 +21,8 @@ from homeassistant.const import (
ATTR_GPS_ACCURACY,
ATTR_LATITUDE,
ATTR_LONGITUDE,
STATE_HOME,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@@ -97,6 +93,15 @@ async def async_setup_entry(
async_add_entities([entity])
def _zone_state(hass: HomeAssistant, data: dict[str, Any]) -> State | None:
"""Return the state of the zone matching the location name in data, if any."""
if not (location_name := data.get(ATTR_LOCATION_NAME)):
return None
# If a location name is set, set the location to the center of the zone
# to allow the `in_zones` attribute to be populated by the base class.
return hass.states.get(ZONE_ENTITY_ID_FORMAT.format(location_name))
class MobileAppEntity(TrackerEntity, RestoreEntity):
"""Represent a tracked device."""
@@ -129,13 +134,17 @@ class MobileAppEntity(TrackerEntity, RestoreEntity):
@property
def location_accuracy(self) -> float:
"""Return the gps accuracy of the device."""
if ATTR_GPS not in self._data:
return 0
return self._data.get(ATTR_GPS_ACCURACY, 0)
@property
def latitude(self) -> float | None:
"""Return latitude value of the device."""
if (gps := self._data.get(ATTR_GPS)) is None:
return None
if not (zone_state := _zone_state(self.hass, self._data)):
return None
return zone_state.attributes.get(ATTR_LATITUDE)
return gps[0]
@@ -143,23 +152,12 @@ class MobileAppEntity(TrackerEntity, RestoreEntity):
def longitude(self) -> float | None:
"""Return longitude value of the device."""
if (gps := self._data.get(ATTR_GPS)) is None:
return None
if not (zone_state := _zone_state(self.hass, self._data)):
return None
return zone_state.attributes.get(ATTR_LONGITUDE)
return gps[1]
@property
def location_name(self) -> str | None:
"""Return a location name for the current location of the device."""
if location_name := self._data.get(ATTR_LOCATION_NAME):
if location_name == HOME_ZONE:
return STATE_HOME
if zone_state := self.hass.states.get(
ZONE_ENTITY_ID_FORMAT.format(location_name)
):
return zone_state.name
return location_name
return None
@property
def name(self) -> str:
"""Return the name of the device."""
@@ -55,9 +55,9 @@ async def setup_zone(hass: HomeAssistant) -> None:
@pytest.mark.parametrize(
("extra_webhook_data", "expected_attributes", "expected_state"),
[
# Send coordinates + location_name: Location name has precedence
# Send coordinates + location_name: Coordinates have precedence
(
{"gps": [10, 20], "location_name": "home"},
{"gps": [10, 20], "gps_accuracy": 30, "location_name": "home"},
{
"latitude": 10,
"longitude": 20,
@@ -67,7 +67,7 @@ async def setup_zone(hass: HomeAssistant) -> None:
"home",
),
(
{"gps": [20, 30], "location_name": "office"},
{"gps": [20, 30], "gps_accuracy": 30, "location_name": "office"},
{
"latitude": 20,
"longitude": 30,
@@ -77,7 +77,7 @@ async def setup_zone(hass: HomeAssistant) -> None:
"Office",
),
(
{"gps": [30, 40], "location_name": "school"},
{"gps": [30, 40], "gps_accuracy": 30, "location_name": "school"},
{
"latitude": 30,
"longitude": 40,
@@ -86,30 +86,88 @@ async def setup_zone(hass: HomeAssistant) -> None:
},
"School",
),
# Send wrong coordinates + location_name: Location name has precedence
# Send wrong coordinates + location_name: Coordinates have precedence
(
{"gps": [10, 10], "location_name": "home"},
{"gps": [10, 10], "gps_accuracy": 30, "location_name": "home"},
{"latitude": 10, "longitude": 10, "gps_accuracy": 30, "in_zones": []},
"not_home",
),
(
{"gps": [10, 10], "gps_accuracy": 30, "location_name": "office"},
{"latitude": 10, "longitude": 10, "gps_accuracy": 30, "in_zones": []},
"not_home",
),
(
{"gps": [10, 10], "gps_accuracy": 30, "location_name": "school"},
{"latitude": 10, "longitude": 10, "gps_accuracy": 30, "in_zones": []},
"not_home",
),
# Send location_name only
(
{"location_name": "home"},
{
"latitude": 10,
"longitude": 20,
"gps_accuracy": 0,
"in_zones": ["zone.home"],
},
"home",
),
(
{"gps": [10, 10], "location_name": "office"},
{"latitude": 10, "longitude": 10, "gps_accuracy": 30, "in_zones": []},
{"location_name": "office"},
{
"latitude": 20,
"longitude": 30,
"gps_accuracy": 0,
"in_zones": ["zone.office"],
},
"Office",
),
(
{"gps": [10, 10], "location_name": "school"},
{"latitude": 10, "longitude": 10, "gps_accuracy": 30, "in_zones": []},
{"location_name": "school"},
{
"latitude": 30,
"longitude": 40,
"gps_accuracy": 0,
"in_zones": ["zone.school"],
},
"School",
),
({"location_name": "no_such_zone"}, {"in_zones": []}, "unknown"),
# Send location_name and accuracy
(
{"location_name": "home", "gps_accuracy": 30},
{
"latitude": 10,
"longitude": 20,
"gps_accuracy": 0,
"in_zones": ["zone.home"],
},
"home",
),
(
{"location_name": "office", "gps_accuracy": 30},
{
"latitude": 20,
"longitude": 30,
"gps_accuracy": 0,
"in_zones": ["zone.office"],
},
"Office",
),
(
{"location_name": "school", "gps_accuracy": 30},
{
"latitude": 30,
"longitude": 40,
"gps_accuracy": 0,
"in_zones": ["zone.school"],
},
"School",
),
# Send location_name only
({"location_name": "home"}, {"in_zones": []}, "home"),
({"location_name": "office"}, {"in_zones": []}, "Office"),
({"location_name": "school"}, {"in_zones": []}, "School"),
({"location_name": "no_such_zone"}, {"in_zones": []}, "no_such_zone"),
# Send coordinates only - location is determined by coordinates
(
{"gps": [10, 20]},
{"gps": [10, 20], "gps_accuracy": 30},
{
"latitude": 10,
"longitude": 20,
@@ -119,7 +177,7 @@ async def setup_zone(hass: HomeAssistant) -> None:
"home",
),
(
{"gps": [20, 30]},
{"gps": [20, 30], "gps_accuracy": 30},
{
"latitude": 20,
"longitude": 30,
@@ -129,7 +187,7 @@ async def setup_zone(hass: HomeAssistant) -> None:
"Office",
),
(
{"gps": [30, 40]},
{"gps": [30, 40], "gps_accuracy": 30},
{
"latitude": 30,
"longitude": 40,
@@ -154,7 +212,6 @@ async def test_sending_location(
json={
"type": "update_location",
"data": {
"gps_accuracy": 30,
"battery": 40,
"altitude": 50,
"course": 60,