mirror of
https://github.com/home-assistant/core.git
synced 2025-09-10 23:31:37 +02:00
Person: Use the home zone lat/lon coordinates when detected home by a stationary tracker (#134075)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
@@ -15,6 +15,7 @@ from homeassistant.components.device_tracker import (
|
||||
DOMAIN as DEVICE_TRACKER_DOMAIN,
|
||||
SourceType,
|
||||
)
|
||||
from homeassistant.components.zone import ENTITY_ID_HOME
|
||||
from homeassistant.const import (
|
||||
ATTR_EDITABLE,
|
||||
ATTR_GPS_ACCURACY,
|
||||
@@ -464,7 +465,7 @@ class Person(
|
||||
"""Register device trackers."""
|
||||
await super().async_added_to_hass()
|
||||
if state := await self.async_get_last_state():
|
||||
self._parse_source_state(state)
|
||||
self._parse_source_state(state, state)
|
||||
|
||||
if self.hass.is_running:
|
||||
# Update person now if hass is already running.
|
||||
@@ -514,7 +515,7 @@ class Person(
|
||||
@callback
|
||||
def _update_state(self) -> None:
|
||||
"""Update the state."""
|
||||
latest_non_gps_home = latest_not_home = latest_gps = latest = None
|
||||
latest_non_gps_home = latest_not_home = latest_gps = latest = coordinates = None
|
||||
for entity_id in self._config[CONF_DEVICE_TRACKERS]:
|
||||
state = self.hass.states.get(entity_id)
|
||||
|
||||
@@ -530,13 +531,23 @@ class Person(
|
||||
|
||||
if latest_non_gps_home:
|
||||
latest = latest_non_gps_home
|
||||
if (
|
||||
latest_non_gps_home.attributes.get(ATTR_LATITUDE) is None
|
||||
and latest_non_gps_home.attributes.get(ATTR_LONGITUDE) is None
|
||||
and (home_zone := self.hass.states.get(ENTITY_ID_HOME))
|
||||
):
|
||||
coordinates = home_zone
|
||||
else:
|
||||
coordinates = latest_non_gps_home
|
||||
elif latest_gps:
|
||||
latest = latest_gps
|
||||
coordinates = latest_gps
|
||||
else:
|
||||
latest = latest_not_home
|
||||
coordinates = latest_not_home
|
||||
|
||||
if latest:
|
||||
self._parse_source_state(latest)
|
||||
if latest and coordinates:
|
||||
self._parse_source_state(latest, coordinates)
|
||||
else:
|
||||
self._attr_state = None
|
||||
self._source = None
|
||||
@@ -548,15 +559,15 @@ class Person(
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def _parse_source_state(self, state: State) -> None:
|
||||
def _parse_source_state(self, state: State, coordinates: State) -> None:
|
||||
"""Parse source state and set person attributes.
|
||||
|
||||
This is a device tracker state or the restored person state.
|
||||
"""
|
||||
self._attr_state = state.state
|
||||
self._source = state.entity_id
|
||||
self._latitude = state.attributes.get(ATTR_LATITUDE)
|
||||
self._longitude = state.attributes.get(ATTR_LONGITUDE)
|
||||
self._latitude = coordinates.attributes.get(ATTR_LATITUDE)
|
||||
self._longitude = coordinates.attributes.get(ATTR_LONGITUDE)
|
||||
self._gps_accuracy = state.attributes.get(ATTR_GPS_ACCURACY)
|
||||
|
||||
@callback
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"domain": "person",
|
||||
"name": "Person",
|
||||
"codeowners": [],
|
||||
"dependencies": ["image_upload", "http"],
|
||||
"dependencies": ["image_upload", "http", "zone"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/person",
|
||||
"integration_type": "system",
|
||||
"iot_class": "calculated",
|
||||
|
@@ -14,7 +14,9 @@ from homeassistant.components.person import (
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_EDITABLE,
|
||||
ATTR_ENTITY_PICTURE,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_GPS_ACCURACY,
|
||||
ATTR_ID,
|
||||
ATTR_LATITUDE,
|
||||
@@ -112,14 +114,19 @@ async def test_setup_tracker(hass: HomeAssistant, hass_admin_user: MockUser) ->
|
||||
}
|
||||
assert await async_setup_component(hass, DOMAIN, config)
|
||||
|
||||
expected_attributes = {
|
||||
ATTR_DEVICE_TRACKERS: [DEVICE_TRACKER],
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FRIENDLY_NAME: "tracked person",
|
||||
ATTR_ID: "1234",
|
||||
ATTR_USER_ID: user_id,
|
||||
}
|
||||
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
assert state.attributes.get(ATTR_ID) == "1234"
|
||||
assert state.attributes.get(ATTR_LATITUDE) is None
|
||||
assert state.attributes.get(ATTR_LONGITUDE) is None
|
||||
assert state.attributes.get(ATTR_SOURCE) is None
|
||||
assert state.attributes.get(ATTR_USER_ID) == user_id
|
||||
assert state.attributes == expected_attributes
|
||||
|
||||
# Test home without coordinates
|
||||
hass.states.async_set(DEVICE_TRACKER, "home")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
@@ -131,13 +138,41 @@ async def test_setup_tracker(hass: HomeAssistant, hass_admin_user: MockUser) ->
|
||||
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "home"
|
||||
assert state.attributes.get(ATTR_ID) == "1234"
|
||||
assert state.attributes.get(ATTR_LATITUDE) is None
|
||||
assert state.attributes.get(ATTR_LONGITUDE) is None
|
||||
assert state.attributes.get(ATTR_SOURCE) == DEVICE_TRACKER
|
||||
assert state.attributes.get(ATTR_USER_ID) == user_id
|
||||
assert state.attributes.get(ATTR_DEVICE_TRACKERS) == [DEVICE_TRACKER]
|
||||
assert state.attributes == expected_attributes | {
|
||||
ATTR_LATITUDE: 32.87336,
|
||||
ATTR_LONGITUDE: -117.22743,
|
||||
ATTR_SOURCE: DEVICE_TRACKER,
|
||||
}
|
||||
|
||||
# Test home with coordinates
|
||||
hass.states.async_set(
|
||||
DEVICE_TRACKER,
|
||||
"home",
|
||||
{ATTR_LATITUDE: 10.123456, ATTR_LONGITUDE: 11.123456, ATTR_GPS_ACCURACY: 10},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "home"
|
||||
assert state.attributes == expected_attributes | {
|
||||
ATTR_GPS_ACCURACY: 10,
|
||||
ATTR_LATITUDE: 10.123456,
|
||||
ATTR_LONGITUDE: 11.123456,
|
||||
ATTR_SOURCE: DEVICE_TRACKER,
|
||||
}
|
||||
|
||||
# Test not_home without coordinates
|
||||
hass.states.async_set(
|
||||
DEVICE_TRACKER,
|
||||
"not_home",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "not_home"
|
||||
assert state.attributes == expected_attributes | {ATTR_SOURCE: DEVICE_TRACKER}
|
||||
|
||||
# Test not_home with coordinates
|
||||
hass.states.async_set(
|
||||
DEVICE_TRACKER,
|
||||
"not_home",
|
||||
@@ -147,13 +182,12 @@ async def test_setup_tracker(hass: HomeAssistant, hass_admin_user: MockUser) ->
|
||||
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "not_home"
|
||||
assert state.attributes.get(ATTR_ID) == "1234"
|
||||
assert state.attributes.get(ATTR_LATITUDE) == 10.123456
|
||||
assert state.attributes.get(ATTR_LONGITUDE) == 11.123456
|
||||
assert state.attributes.get(ATTR_GPS_ACCURACY) == 10
|
||||
assert state.attributes.get(ATTR_SOURCE) == DEVICE_TRACKER
|
||||
assert state.attributes.get(ATTR_USER_ID) == user_id
|
||||
assert state.attributes.get(ATTR_DEVICE_TRACKERS) == [DEVICE_TRACKER]
|
||||
assert state.attributes == expected_attributes | {
|
||||
ATTR_GPS_ACCURACY: 10,
|
||||
ATTR_LATITUDE: 10.123456,
|
||||
ATTR_LONGITUDE: 11.123456,
|
||||
ATTR_SOURCE: DEVICE_TRACKER,
|
||||
}
|
||||
|
||||
|
||||
async def test_setup_two_trackers(
|
||||
@@ -188,8 +222,8 @@ async def test_setup_two_trackers(
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "home"
|
||||
assert state.attributes.get(ATTR_ID) == "1234"
|
||||
assert state.attributes.get(ATTR_LATITUDE) is None
|
||||
assert state.attributes.get(ATTR_LONGITUDE) is None
|
||||
assert state.attributes.get(ATTR_LATITUDE) == 32.87336
|
||||
assert state.attributes.get(ATTR_LONGITUDE) == -117.22743
|
||||
assert state.attributes.get(ATTR_GPS_ACCURACY) is None
|
||||
assert state.attributes.get(ATTR_SOURCE) == DEVICE_TRACKER
|
||||
assert state.attributes.get(ATTR_USER_ID) == user_id
|
||||
@@ -453,8 +487,8 @@ async def test_load_person_storage(
|
||||
state = hass.states.get("person.tracked_person")
|
||||
assert state.state == "home"
|
||||
assert state.attributes.get(ATTR_ID) == "1234"
|
||||
assert state.attributes.get(ATTR_LATITUDE) is None
|
||||
assert state.attributes.get(ATTR_LONGITUDE) is None
|
||||
assert state.attributes.get(ATTR_LATITUDE) == 32.87336
|
||||
assert state.attributes.get(ATTR_LONGITUDE) == -117.22743
|
||||
assert state.attributes.get(ATTR_SOURCE) == DEVICE_TRACKER
|
||||
assert state.attributes.get(ATTR_USER_ID) == hass_admin_user.id
|
||||
|
||||
@@ -817,7 +851,7 @@ async def test_reload(hass: HomeAssistant, hass_admin_user: MockUser) -> None:
|
||||
},
|
||||
)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
assert len(hass.states.async_entity_ids()) == 3 # Person1, Person2, zone.home
|
||||
|
||||
state_1 = hass.states.get("person.person_1")
|
||||
state_2 = hass.states.get("person.person_2")
|
||||
@@ -847,7 +881,7 @@ async def test_reload(hass: HomeAssistant, hass_admin_user: MockUser) -> None:
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
assert len(hass.states.async_entity_ids()) == 3 # Person1, Person2, zone.home
|
||||
|
||||
state_1 = hass.states.get("person.person_1")
|
||||
state_2 = hass.states.get("person.person_2")
|
||||
|
Reference in New Issue
Block a user