101 lines
3.7 KiB
Python
101 lines
3.7 KiB
Python
"""
|
|
Support for iCloud connected devices.
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
https://home-assistant.io/components/device_tracker.icloud/
|
|
"""
|
|
import logging
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.const import (CONF_PASSWORD, CONF_USERNAME,
|
|
EVENT_HOMEASSISTANT_START)
|
|
from homeassistant.helpers.event import track_utc_time_change
|
|
from homeassistant.util import slugify
|
|
from homeassistant.components.device_tracker import (ENTITY_ID_FORMAT,
|
|
PLATFORM_SCHEMA)
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
REQUIREMENTS = ['pyicloud==0.9.1']
|
|
|
|
CONF_INTERVAL = 'interval'
|
|
KEEPALIVE_INTERVAL = 4
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
vol.Required(CONF_USERNAME): vol.Coerce(str),
|
|
vol.Required(CONF_PASSWORD): vol.Coerce(str),
|
|
vol.Optional(CONF_INTERVAL, default=8): vol.All(vol.Coerce(int),
|
|
vol.Range(min=1))
|
|
})
|
|
|
|
|
|
def setup_scanner(hass, config, see):
|
|
"""Setup the iCloud Scanner."""
|
|
from pyicloud import PyiCloudService
|
|
from pyicloud.exceptions import PyiCloudFailedLoginException
|
|
from pyicloud.exceptions import PyiCloudNoDevicesException
|
|
logging.getLogger("pyicloud.base").setLevel(logging.WARNING)
|
|
|
|
username = config[CONF_USERNAME]
|
|
password = config[CONF_PASSWORD]
|
|
|
|
try:
|
|
_LOGGER.info('Logging into iCloud Account')
|
|
# Attempt the login to iCloud
|
|
api = PyiCloudService(username, password, verify=True)
|
|
except PyiCloudFailedLoginException as error:
|
|
_LOGGER.exception('Error logging into iCloud Service: %s', error)
|
|
return False
|
|
|
|
def keep_alive(now):
|
|
"""Keep authenticating iCloud connection.
|
|
|
|
The session timeouts if we are not using it so we
|
|
have to re-authenticate & this will send an email.
|
|
"""
|
|
api.authenticate()
|
|
_LOGGER.info("Authenticate against iCloud")
|
|
|
|
seen_devices = {}
|
|
|
|
def update_icloud(now):
|
|
"""Authenticate against iCloud and scan for devices."""
|
|
try:
|
|
keep_alive(None)
|
|
# Loop through every device registered with the iCloud account
|
|
for device in api.devices:
|
|
status = device.status()
|
|
dev_id = slugify(status['name'].replace(' ', '', 99))
|
|
|
|
# An entity will not be created by see() when track=false in
|
|
# 'known_devices.yaml', but we need to see() it at least once
|
|
entity = hass.states.get(ENTITY_ID_FORMAT.format(dev_id))
|
|
if entity is None and dev_id in seen_devices:
|
|
continue
|
|
seen_devices[dev_id] = True
|
|
|
|
location = device.location()
|
|
# If the device has a location add it. If not do nothing
|
|
if location:
|
|
see(
|
|
dev_id=dev_id,
|
|
host_name=status['name'],
|
|
gps=(location['latitude'], location['longitude']),
|
|
battery=status['batteryLevel']*100,
|
|
gps_accuracy=location['horizontalAccuracy']
|
|
)
|
|
except PyiCloudNoDevicesException:
|
|
_LOGGER.info('No iCloud Devices found!')
|
|
|
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, update_icloud)
|
|
|
|
update_minutes = list(range(0, 60, config[CONF_INTERVAL]))
|
|
# Schedule keepalives between the updates
|
|
keepalive_minutes = list(x for x in range(0, 60, KEEPALIVE_INTERVAL)
|
|
if x not in update_minutes)
|
|
|
|
track_utc_time_change(hass, update_icloud, second=0, minute=update_minutes)
|
|
track_utc_time_change(hass, keep_alive, second=0, minute=keepalive_minutes)
|
|
|
|
return True
|