mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
[device_tracker] Use home zone GPS coordinates for router based devices. (#4852)
This commit is contained in:
parent
ca4a857532
commit
41ef6228be
@ -70,6 +70,10 @@ ATTR_LOCATION_NAME = 'location_name'
|
||||
ATTR_GPS = 'gps'
|
||||
ATTR_BATTERY = 'battery'
|
||||
ATTR_ATTRIBUTES = 'attributes'
|
||||
ATTR_SOURCE_TYPE = 'source_type'
|
||||
|
||||
SOURCE_TYPE_GPS = 'gps'
|
||||
SOURCE_TYPE_ROUTER = 'router'
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_SCAN_INTERVAL): cv.time_period,
|
||||
@ -234,17 +238,19 @@ class DeviceTracker(object):
|
||||
|
||||
def see(self, mac: str=None, dev_id: str=None, host_name: str=None,
|
||||
location_name: str=None, gps: GPSType=None, gps_accuracy=None,
|
||||
battery: str=None, attributes: dict=None):
|
||||
battery: str=None, attributes: dict=None,
|
||||
source_type: str=SOURCE_TYPE_GPS):
|
||||
"""Notify the device tracker that you see a device."""
|
||||
self.hass.add_job(
|
||||
self.async_see(mac, dev_id, host_name, location_name, gps,
|
||||
gps_accuracy, battery, attributes)
|
||||
gps_accuracy, battery, attributes, source_type)
|
||||
)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_see(self, mac: str=None, dev_id: str=None, host_name: str=None,
|
||||
location_name: str=None, gps: GPSType=None,
|
||||
gps_accuracy=None, battery: str=None, attributes: dict=None):
|
||||
gps_accuracy=None, battery: str=None, attributes: dict=None,
|
||||
source_type: str=SOURCE_TYPE_GPS):
|
||||
"""Notify the device tracker that you see a device.
|
||||
|
||||
This method is a coroutine.
|
||||
@ -262,7 +268,8 @@ class DeviceTracker(object):
|
||||
|
||||
if device:
|
||||
yield from device.async_seen(host_name, location_name, gps,
|
||||
gps_accuracy, battery, attributes)
|
||||
gps_accuracy, battery, attributes,
|
||||
source_type)
|
||||
if device.track:
|
||||
yield from device.async_update_ha_state()
|
||||
return
|
||||
@ -277,7 +284,8 @@ class DeviceTracker(object):
|
||||
self.mac_to_dev[mac] = device
|
||||
|
||||
yield from device.async_seen(host_name, location_name, gps,
|
||||
gps_accuracy, battery, attributes)
|
||||
gps_accuracy, battery, attributes,
|
||||
source_type)
|
||||
|
||||
if device.track:
|
||||
yield from device.async_update_ha_state()
|
||||
@ -381,6 +389,9 @@ class Device(Entity):
|
||||
|
||||
self.away_hide = hide_if_away
|
||||
self.vendor = vendor
|
||||
|
||||
self.source_type = None
|
||||
|
||||
self._attributes = {}
|
||||
|
||||
@property
|
||||
@ -401,7 +412,9 @@ class Device(Entity):
|
||||
@property
|
||||
def state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
attr = {}
|
||||
attr = {
|
||||
ATTR_SOURCE_TYPE: self.source_type
|
||||
}
|
||||
|
||||
if self.gps:
|
||||
attr[ATTR_LATITUDE] = self.gps[0]
|
||||
@ -426,12 +439,13 @@ class Device(Entity):
|
||||
@asyncio.coroutine
|
||||
def async_seen(self, host_name: str=None, location_name: str=None,
|
||||
gps: GPSType=None, gps_accuracy=0, battery: str=None,
|
||||
attributes: dict=None):
|
||||
attributes: dict=None, source_type: str=SOURCE_TYPE_GPS):
|
||||
"""Mark the device as seen."""
|
||||
self.source_type = source_type
|
||||
self.last_seen = dt_util.utcnow()
|
||||
self.host_name = host_name
|
||||
self.location_name = location_name
|
||||
self.gps_accuracy = gps_accuracy or 0
|
||||
|
||||
if battery:
|
||||
self.battery = battery
|
||||
if attributes:
|
||||
@ -442,7 +456,10 @@ class Device(Entity):
|
||||
if gps is not None:
|
||||
try:
|
||||
self.gps = float(gps[0]), float(gps[1])
|
||||
self.gps_accuracy = gps_accuracy or 0
|
||||
except (ValueError, TypeError, IndexError):
|
||||
self.gps = None
|
||||
self.gps_accuracy = 0
|
||||
_LOGGER.warning('Could not parse gps value for %s: %s',
|
||||
self.dev_id, gps)
|
||||
|
||||
@ -467,7 +484,7 @@ class Device(Entity):
|
||||
return
|
||||
elif self.location_name:
|
||||
self._state = self.location_name
|
||||
elif self.gps is not None:
|
||||
elif self.gps is not None and self.source_type == SOURCE_TYPE_GPS:
|
||||
zone_state = zone.async_active_zone(
|
||||
self.hass, self.gps[0], self.gps[1], self.gps_accuracy)
|
||||
if zone_state is None:
|
||||
@ -476,9 +493,9 @@ class Device(Entity):
|
||||
self._state = STATE_HOME
|
||||
else:
|
||||
self._state = zone_state.name
|
||||
|
||||
elif self.stale():
|
||||
self._state = STATE_NOT_HOME
|
||||
self.gps = None
|
||||
self.last_update_home = False
|
||||
else:
|
||||
self._state = STATE_HOME
|
||||
@ -637,7 +654,20 @@ def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
else:
|
||||
host_name = yield from scanner.async_get_device_name(mac)
|
||||
seen.add(mac)
|
||||
hass.async_add_job(async_see_device(mac=mac, host_name=host_name))
|
||||
|
||||
kwargs = {
|
||||
'mac': mac,
|
||||
'host_name': host_name,
|
||||
'source_type': SOURCE_TYPE_ROUTER
|
||||
}
|
||||
|
||||
zone_home = hass.states.get(zone.ENTITY_ID_HOME)
|
||||
if zone_home:
|
||||
kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE],
|
||||
zone_home.attributes[ATTR_LONGITUDE]]
|
||||
kwargs['gps_accuracy'] = 0
|
||||
|
||||
hass.async_add_job(async_see_device(**kwargs))
|
||||
|
||||
async_track_time_interval(hass, async_device_tracker_scan, interval)
|
||||
hass.async_add_job(async_device_tracker_scan, None)
|
||||
|
@ -8,6 +8,7 @@ from unittest.mock import call, patch
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
|
||||
from homeassistant.components import zone
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.loader import get_component
|
||||
@ -541,8 +542,71 @@ class TestComponentsDeviceTracker(unittest.TestCase):
|
||||
self.assertEqual(attrs['longitude'], 0.8)
|
||||
self.assertEqual(attrs['test'], 'test')
|
||||
self.assertEqual(attrs['gps_accuracy'], 1)
|
||||
self.assertEqual(attrs['source_type'], 'gps')
|
||||
self.assertEqual(attrs['number'], 1)
|
||||
|
||||
def test_see_passive_zone_state(self):
|
||||
"""Test that the device tracker sets gps for passive trackers."""
|
||||
register_time = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC)
|
||||
scan_time = datetime(2015, 9, 15, 23, 1, tzinfo=dt_util.UTC)
|
||||
|
||||
with assert_setup_component(1, zone.DOMAIN):
|
||||
zone_info = {
|
||||
'name': 'Home',
|
||||
'latitude': 1,
|
||||
'longitude': 2,
|
||||
'radius': 250,
|
||||
'passive': False
|
||||
}
|
||||
|
||||
setup_component(self.hass, zone.DOMAIN, {
|
||||
'zone': zone_info
|
||||
})
|
||||
|
||||
scanner = get_component('device_tracker.test').SCANNER
|
||||
scanner.reset()
|
||||
scanner.come_home('dev1')
|
||||
|
||||
with patch('homeassistant.components.device_tracker.dt_util.utcnow',
|
||||
return_value=register_time):
|
||||
with assert_setup_component(1, device_tracker.DOMAIN):
|
||||
assert setup_component(self.hass, device_tracker.DOMAIN, {
|
||||
device_tracker.DOMAIN: {
|
||||
CONF_PLATFORM: 'test',
|
||||
device_tracker.CONF_CONSIDER_HOME: 59,
|
||||
}})
|
||||
|
||||
state = self.hass.states.get('device_tracker.dev1')
|
||||
attrs = state.attributes
|
||||
self.assertEqual(STATE_HOME, state.state)
|
||||
self.assertEqual(state.object_id, 'dev1')
|
||||
self.assertEqual(state.name, 'dev1')
|
||||
self.assertEqual(attrs.get('friendly_name'), 'dev1')
|
||||
self.assertEqual(attrs.get('latitude'), 1)
|
||||
self.assertEqual(attrs.get('longitude'), 2)
|
||||
self.assertEqual(attrs.get('gps_accuracy'), 0)
|
||||
self.assertEqual(attrs.get('source_type'),
|
||||
device_tracker.SOURCE_TYPE_ROUTER)
|
||||
|
||||
scanner.leave_home('dev1')
|
||||
|
||||
with patch('homeassistant.components.device_tracker.dt_util.utcnow',
|
||||
return_value=scan_time):
|
||||
fire_time_changed(self.hass, scan_time)
|
||||
self.hass.block_till_done()
|
||||
|
||||
state = self.hass.states.get('device_tracker.dev1')
|
||||
attrs = state.attributes
|
||||
self.assertEqual(STATE_NOT_HOME, state.state)
|
||||
self.assertEqual(state.object_id, 'dev1')
|
||||
self.assertEqual(state.name, 'dev1')
|
||||
self.assertEqual(attrs.get('friendly_name'), 'dev1')
|
||||
self.assertEqual(attrs.get('latitude'), None)
|
||||
self.assertEqual(attrs.get('longitude'), None)
|
||||
self.assertEqual(attrs.get('gps_accuracy'), None)
|
||||
self.assertEqual(attrs.get('source_type'),
|
||||
device_tracker.SOURCE_TYPE_ROUTER)
|
||||
|
||||
@patch('homeassistant.components.device_tracker._LOGGER.warning')
|
||||
def test_see_failures(self, mock_warning):
|
||||
"""Test that the device tracker see failures."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user