mirror of
https://github.com/home-assistant/core.git
synced 2026-05-12 08:14:29 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37f5905245 |
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user