Improving icloud device tracker (#14078)
* Improving icloud device tracker * Adding config validations for new values * Adding config validations for new values * Moving icloud specific setup to platform schema. Setting default in platform schema.
This commit is contained in:
parent
10505d542a
commit
9c7523d7b0
1 changed files with 38 additions and 25 deletions
|
@ -24,8 +24,9 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
REQUIREMENTS = ['pyicloud==0.9.1']
|
||||
|
||||
CONF_IGNORED_DEVICES = 'ignored_devices'
|
||||
CONF_ACCOUNTNAME = 'account_name'
|
||||
CONF_MAX_INTERVAL = 'max_interval'
|
||||
CONF_GPS_ACCURACY_THRESHOLD = 'gps_accuracy_threshold'
|
||||
|
||||
# entity attributes
|
||||
ATTR_ACCOUNTNAME = 'account_name'
|
||||
|
@ -64,13 +65,15 @@ DEVICESTATUSCODES = {
|
|||
SERVICE_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_ACCOUNTNAME): vol.All(cv.ensure_list, [cv.slugify]),
|
||||
vol.Optional(ATTR_DEVICENAME): cv.slugify,
|
||||
vol.Optional(ATTR_INTERVAL): cv.positive_int,
|
||||
vol.Optional(ATTR_INTERVAL): cv.positive_int
|
||||
})
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(ATTR_ACCOUNTNAME): cv.slugify,
|
||||
vol.Optional(CONF_MAX_INTERVAL, default=30): cv.positive_int,
|
||||
vol.Optional(CONF_GPS_ACCURACY_THRESHOLD, default=1000): cv.positive_int
|
||||
})
|
||||
|
||||
|
||||
|
@ -79,8 +82,11 @@ def setup_scanner(hass, config: dict, see, discovery_info=None):
|
|||
username = config.get(CONF_USERNAME)
|
||||
password = config.get(CONF_PASSWORD)
|
||||
account = config.get(CONF_ACCOUNTNAME, slugify(username.partition('@')[0]))
|
||||
max_interval = config.get(CONF_MAX_INTERVAL)
|
||||
gps_accuracy_threshold = config.get(CONF_GPS_ACCURACY_THRESHOLD)
|
||||
|
||||
icloudaccount = Icloud(hass, username, password, account, see)
|
||||
icloudaccount = Icloud(hass, username, password, account, max_interval,
|
||||
gps_accuracy_threshold, see)
|
||||
|
||||
if icloudaccount.api is not None:
|
||||
ICLOUDTRACKERS[account] = icloudaccount
|
||||
|
@ -96,6 +102,7 @@ def setup_scanner(hass, config: dict, see, discovery_info=None):
|
|||
for account in accounts:
|
||||
if account in ICLOUDTRACKERS:
|
||||
ICLOUDTRACKERS[account].lost_iphone(devicename)
|
||||
|
||||
hass.services.register(DOMAIN, 'icloud_lost_iphone', lost_iphone,
|
||||
schema=SERVICE_SCHEMA)
|
||||
|
||||
|
@ -106,6 +113,7 @@ def setup_scanner(hass, config: dict, see, discovery_info=None):
|
|||
for account in accounts:
|
||||
if account in ICLOUDTRACKERS:
|
||||
ICLOUDTRACKERS[account].update_icloud(devicename)
|
||||
|
||||
hass.services.register(DOMAIN, 'icloud_update', update_icloud,
|
||||
schema=SERVICE_SCHEMA)
|
||||
|
||||
|
@ -115,6 +123,7 @@ def setup_scanner(hass, config: dict, see, discovery_info=None):
|
|||
for account in accounts:
|
||||
if account in ICLOUDTRACKERS:
|
||||
ICLOUDTRACKERS[account].reset_account_icloud()
|
||||
|
||||
hass.services.register(DOMAIN, 'icloud_reset_account',
|
||||
reset_account_icloud, schema=SERVICE_SCHEMA)
|
||||
|
||||
|
@ -137,7 +146,8 @@ def setup_scanner(hass, config: dict, see, discovery_info=None):
|
|||
class Icloud(DeviceScanner):
|
||||
"""Representation of an iCloud account."""
|
||||
|
||||
def __init__(self, hass, username, password, name, see):
|
||||
def __init__(self, hass, username, password, name, max_interval,
|
||||
gps_accuracy_threshold, see):
|
||||
"""Initialize an iCloud account."""
|
||||
self.hass = hass
|
||||
self.username = username
|
||||
|
@ -148,6 +158,8 @@ class Icloud(DeviceScanner):
|
|||
self.seen_devices = {}
|
||||
self._overridestates = {}
|
||||
self._intervals = {}
|
||||
self._max_interval = max_interval
|
||||
self._gps_accuracy_threshold = gps_accuracy_threshold
|
||||
self.see = see
|
||||
|
||||
self._trusted_device = None
|
||||
|
@ -348,7 +360,7 @@ class Icloud(DeviceScanner):
|
|||
self._overridestates[devicename] = None
|
||||
|
||||
if currentzone is not None:
|
||||
self._intervals[devicename] = 30
|
||||
self._intervals[devicename] = self._max_interval
|
||||
return
|
||||
|
||||
if mindistance is None:
|
||||
|
@ -363,7 +375,6 @@ class Icloud(DeviceScanner):
|
|||
|
||||
if interval > 180:
|
||||
# Three hour drive? This is far enough that they might be flying
|
||||
# home - check every half hour
|
||||
interval = 30
|
||||
|
||||
if battery is not None and battery <= 33 and mindistance > 3:
|
||||
|
@ -403,22 +414,24 @@ class Icloud(DeviceScanner):
|
|||
status = device.status(DEVICESTATUSSET)
|
||||
battery = status.get('batteryLevel', 0) * 100
|
||||
location = status['location']
|
||||
if location:
|
||||
self.determine_interval(
|
||||
devicename, location['latitude'],
|
||||
location['longitude'], battery)
|
||||
interval = self._intervals.get(devicename, 1)
|
||||
attrs[ATTR_INTERVAL] = interval
|
||||
accuracy = location['horizontalAccuracy']
|
||||
kwargs['dev_id'] = dev_id
|
||||
kwargs['host_name'] = status['name']
|
||||
kwargs['gps'] = (location['latitude'],
|
||||
location['longitude'])
|
||||
kwargs['battery'] = battery
|
||||
kwargs['gps_accuracy'] = accuracy
|
||||
kwargs[ATTR_ATTRIBUTES] = attrs
|
||||
self.see(**kwargs)
|
||||
self.seen_devices[devicename] = True
|
||||
if location and location['horizontalAccuracy']:
|
||||
horizontal_accuracy = int(location['horizontalAccuracy'])
|
||||
if horizontal_accuracy < self._gps_accuracy_threshold:
|
||||
self.determine_interval(
|
||||
devicename, location['latitude'],
|
||||
location['longitude'], battery)
|
||||
interval = self._intervals.get(devicename, 1)
|
||||
attrs[ATTR_INTERVAL] = interval
|
||||
accuracy = location['horizontalAccuracy']
|
||||
kwargs['dev_id'] = dev_id
|
||||
kwargs['host_name'] = status['name']
|
||||
kwargs['gps'] = (location['latitude'],
|
||||
location['longitude'])
|
||||
kwargs['battery'] = battery
|
||||
kwargs['gps_accuracy'] = accuracy
|
||||
kwargs[ATTR_ATTRIBUTES] = attrs
|
||||
self.see(**kwargs)
|
||||
self.seen_devices[devicename] = True
|
||||
except PyiCloudNoDevicesException:
|
||||
_LOGGER.error("No iCloud Devices found")
|
||||
|
||||
|
@ -434,7 +447,7 @@ class Icloud(DeviceScanner):
|
|||
device.play_sound()
|
||||
|
||||
def update_icloud(self, devicename=None):
|
||||
"""Authenticate against iCloud and scan for devices."""
|
||||
"""Request device information from iCloud and update device_tracker."""
|
||||
from pyicloud.exceptions import PyiCloudNoDevicesException
|
||||
|
||||
if self.api is None:
|
||||
|
@ -443,13 +456,13 @@ class Icloud(DeviceScanner):
|
|||
try:
|
||||
if devicename is not None:
|
||||
if devicename in self.devices:
|
||||
self.devices[devicename].location()
|
||||
self.update_device(devicename)
|
||||
else:
|
||||
_LOGGER.error("devicename %s unknown for account %s",
|
||||
devicename, self._attrs[ATTR_ACCOUNTNAME])
|
||||
else:
|
||||
for device in self.devices:
|
||||
self.devices[device].location()
|
||||
self.update_device(device)
|
||||
except PyiCloudNoDevicesException:
|
||||
_LOGGER.error("No iCloud Devices found")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue