mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Person: Ignore unavailable states (#21058)
* Ignore unavailable states * Revert validation
This commit is contained in:
parent
4d3790e2d4
commit
81d2ec9618
@ -15,7 +15,7 @@ from homeassistant.components.device_tracker import (
|
||||
DOMAIN as DEVICE_TRACKER_DOMAIN)
|
||||
from homeassistant.const import (
|
||||
ATTR_ID, ATTR_LATITUDE, ATTR_LONGITUDE, CONF_ID, CONF_NAME,
|
||||
EVENT_HOMEASSISTANT_START)
|
||||
EVENT_HOMEASSISTANT_START, STATE_UNKNOWN, STATE_UNAVAILABLE)
|
||||
from homeassistant.core import callback, Event
|
||||
from homeassistant.auth import EVENT_USER_REMOVED
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
@ -25,7 +25,6 @@ from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -38,6 +37,8 @@ DOMAIN = 'person'
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
SAVE_DELAY = 10
|
||||
# Device tracker states to ignore
|
||||
IGNORE_STATES = (STATE_UNKNOWN, STATE_UNAVAILABLE)
|
||||
|
||||
PERSON_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ID): cv.string,
|
||||
@ -350,30 +351,31 @@ class Person(RestoreEntity):
|
||||
trackers = self._config.get(CONF_DEVICE_TRACKERS)
|
||||
|
||||
if trackers:
|
||||
def sort_key(state):
|
||||
if state:
|
||||
return state.last_updated
|
||||
return dt_util.utc_from_timestamp(0)
|
||||
|
||||
latest = max(
|
||||
[self.hass.states.get(entity_id) for entity_id in trackers],
|
||||
key=sort_key
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_handle_tracker_update(entity, old_state, new_state):
|
||||
"""Handle the device tracker state changes."""
|
||||
self._parse_source_state(new_state)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
_LOGGER.debug(
|
||||
"Subscribe to device trackers for %s", self.entity_id)
|
||||
|
||||
self._unsub_track_device = async_track_state_change(
|
||||
self.hass, trackers, async_handle_tracker_update)
|
||||
self.hass, trackers, self._async_handle_tracker_update)
|
||||
|
||||
else:
|
||||
latest = None
|
||||
self._update_state()
|
||||
|
||||
@callback
|
||||
def _async_handle_tracker_update(self, entity, old_state, new_state):
|
||||
"""Handle the device tracker state changes."""
|
||||
self._update_state()
|
||||
|
||||
@callback
|
||||
def _update_state(self):
|
||||
"""Update the state."""
|
||||
latest = None
|
||||
for entity_id in self._config.get(CONF_DEVICE_TRACKERS, []):
|
||||
state = self.hass.states.get(entity_id)
|
||||
|
||||
if not state or state.state in IGNORE_STATES:
|
||||
continue
|
||||
|
||||
if latest is None or state.last_updated > latest.last_updated:
|
||||
latest = state
|
||||
|
||||
if latest:
|
||||
self._parse_source_state(latest)
|
||||
|
@ -29,7 +29,7 @@ def storage_setup(hass, hass_storage, hass_admin_user):
|
||||
'id': '1234',
|
||||
'name': 'tracked person',
|
||||
'user_id': hass_admin_user.id,
|
||||
'device_trackers': DEVICE_TRACKER
|
||||
'device_trackers': [DEVICE_TRACKER]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -189,6 +189,43 @@ async def test_setup_two_trackers(hass, hass_admin_user):
|
||||
assert state.attributes.get(ATTR_USER_ID) == user_id
|
||||
|
||||
|
||||
async def test_ignore_unavailable_states(hass, hass_admin_user):
|
||||
"""Test set up person with two device trackers, one unavailable."""
|
||||
user_id = hass_admin_user.id
|
||||
config = {DOMAIN: {
|
||||
'id': '1234', 'name': 'tracked person', 'user_id': user_id,
|
||||
'device_trackers': [DEVICE_TRACKER, DEVICE_TRACKER_2]}}
|
||||
assert await async_setup_component(hass, DOMAIN, config)
|
||||
|
||||
state = hass.states.get('person.tracked_person')
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
||||
await hass.async_block_till_done()
|
||||
hass.states.async_set(DEVICE_TRACKER, 'home')
|
||||
await hass.async_block_till_done()
|
||||
hass.states.async_set(DEVICE_TRACKER, 'unavailable')
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Unknown, as only 1 device tracker has a state, but we ignore that one
|
||||
state = hass.states.get('person.tracked_person')
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
hass.states.async_set(DEVICE_TRACKER_2, 'not_home')
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Take state of tracker 2
|
||||
state = hass.states.get('person.tracked_person')
|
||||
assert state.state == 'not_home'
|
||||
|
||||
# state 1 is newer but ignored, keep tracker 2 state
|
||||
hass.states.async_set(DEVICE_TRACKER, 'unknown')
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get('person.tracked_person')
|
||||
assert state.state == 'not_home'
|
||||
|
||||
|
||||
async def test_restore_home_state(hass, hass_admin_user):
|
||||
"""Test that the state is restored for a person on startup."""
|
||||
user_id = hass_admin_user.id
|
||||
|
Loading…
x
Reference in New Issue
Block a user