core/homeassistant/components/google_maps/device_tracker.py

115 lines
3.8 KiB
Python
Raw Normal View History

"""Support for Google Maps location sharing."""
from datetime import timedelta
import logging
from locationsharinglib import Service
from locationsharinglib.locationsharinglibexceptions import InvalidCookies
import voluptuous as vol
2019-07-31 19:25:30 +00:00
from homeassistant.components.device_tracker import PLATFORM_SCHEMA, SOURCE_TYPE_GPS
from homeassistant.const import (
2019-07-31 19:25:30 +00:00
ATTR_BATTERY_CHARGING,
ATTR_BATTERY_LEVEL,
ATTR_ID,
CONF_SCAN_INTERVAL,
CONF_USERNAME,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_time_interval
from homeassistant.helpers.typing import ConfigType
from homeassistant.util import dt as dt_util, slugify
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
ATTR_ADDRESS = "address"
ATTR_FULL_NAME = "full_name"
ATTR_LAST_SEEN = "last_seen"
ATTR_NICKNAME = "nickname"
2019-07-31 19:25:30 +00:00
CONF_MAX_GPS_ACCURACY = "max_gps_accuracy"
2019-07-31 19:25:30 +00:00
CREDENTIALS_FILE = ".google_maps_location_sharing.cookies"
2019-07-31 19:25:30 +00:00
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_MAX_GPS_ACCURACY, default=100000): vol.Coerce(float),
}
)
def setup_scanner(hass, config: ConfigType, see, discovery_info=None):
"""Set up the Google Maps Location sharing scanner."""
scanner = GoogleMapsScanner(hass, config, see)
return scanner.success_init
class GoogleMapsScanner:
"""Representation of an Google Maps location sharing account."""
def __init__(self, hass, config: ConfigType, see) -> None:
"""Initialize the scanner."""
self.see = see
self.username = config[CONF_USERNAME]
self.max_gps_accuracy = config[CONF_MAX_GPS_ACCURACY]
self.scan_interval = config.get(CONF_SCAN_INTERVAL) or timedelta(seconds=60)
2019-07-31 19:25:30 +00:00
credfile = "{}.{}".format(
hass.config.path(CREDENTIALS_FILE), slugify(self.username)
)
try:
self.service = Service(credfile, self.username)
self._update_info()
2019-07-31 19:25:30 +00:00
track_time_interval(hass, self._update_info, self.scan_interval)
self.success_init = True
except InvalidCookies:
2019-07-31 19:25:30 +00:00
_LOGGER.error(
"You have specified invalid login credentials. "
"Please make sure you have saved your credentials"
" in the following file: %s",
credfile,
)
self.success_init = False
def _update_info(self, now=None):
for person in self.service.get_all_people():
try:
2019-07-31 19:25:30 +00:00
dev_id = "google_maps_{0}".format(slugify(person.id))
except TypeError:
_LOGGER.warning("No location(s) shared with this account")
return
2019-07-31 19:25:30 +00:00
if (
self.max_gps_accuracy is not None
and person.accuracy > self.max_gps_accuracy
):
_LOGGER.info(
"Ignoring %s update because expected GPS "
"accuracy %s is not met: %s",
person.nickname,
self.max_gps_accuracy,
person.accuracy,
)
continue
attrs = {
ATTR_ADDRESS: person.address,
ATTR_FULL_NAME: person.full_name,
ATTR_ID: person.id,
ATTR_LAST_SEEN: dt_util.as_utc(person.datetime),
ATTR_NICKNAME: person.nickname,
ATTR_BATTERY_CHARGING: person.charging,
2019-07-31 19:25:30 +00:00
ATTR_BATTERY_LEVEL: person.battery_level,
}
self.see(
dev_id=dev_id,
gps=(person.latitude, person.longitude),
picture=person.picture_url,
source_type=SOURCE_TYPE_GPS,
gps_accuracy=person.accuracy,
attributes=attrs,
)