Tado device tracker support (#5046)

* Added tado device tracker

* Added tado device tracker to .converagerc

* Updated docs

* Code formatting and removed unused import

* Code formatting and removed unused import

* Respected the lint line length

* Respect pydocstyle rules

* Respect the lint line limit length

* Fixed reviewer feedback

* Changed the tracker to support async

* Respect the New line end of file rule

* Update .coveragerc
This commit is contained in:
Job Vermeulen 2017-01-17 08:15:11 +01:00 committed by Paulus Schoutsen
parent e4a45fa857
commit 40ba4fd872
2 changed files with 131 additions and 0 deletions

View File

@ -168,6 +168,7 @@ omit =
homeassistant/components/device_tracker/swisscom.py
homeassistant/components/device_tracker/thomson.py
homeassistant/components/device_tracker/tomato.py
homeassistant/components/device_tracker/tado.py
homeassistant/components/device_tracker/tplink.py
homeassistant/components/device_tracker/trackr.py
homeassistant/components/device_tracker/ubus.py

View File

@ -0,0 +1,130 @@
"""
Support for Tado Smart Thermostat.
Device tracker platform that supports presence detection.
The detection is based on geofencing enabled devices used with Tado.
"""
import logging
from datetime import timedelta
from collections import namedtuple
import asyncio
import aiohttp
import async_timeout
import voluptuous as vol
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
from homeassistant.components.device_tracker import \
DOMAIN, PLATFORM_SCHEMA, DeviceScanner
from homeassistant.helpers.aiohttp_client import async_create_clientsession
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string
})
def get_scanner(hass, config):
"""Return a Tado scanner."""
scanner = TadoDeviceScanner(hass, config[DOMAIN])
return scanner if scanner.success_init else None
Device = namedtuple("Device", ["mac", "name"])
class TadoDeviceScanner(DeviceScanner):
"""This class gets geofenced devices from Tado."""
def __init__(self, hass, config):
"""Initialize the scanner."""
self.last_results = []
self.username = config[CONF_USERNAME]
self.password = config[CONF_PASSWORD]
self.tadoapiurl = 'https://my.tado.com/api/v2/me' \
'?username={}&password={}'
self.websession = async_create_clientsession(
hass, cookie_jar=aiohttp.CookieJar(unsafe=True, loop=hass.loop))
self.success_init = self._update_info()
_LOGGER.info("Tado scanner initialized")
@asyncio.coroutine
def async_scan_devices(self):
"""Scan for devices and return a list containing found device ids."""
yield from self._update_info()
return [device.mac for device in self.last_results]
@asyncio.coroutine
def async_get_device_name(self, mac):
"""Return the name of the given device or None if we don't know."""
filter_named = [device.name for device in self.last_results
if device.mac == mac]
if filter_named:
return filter_named[0]
else:
return None
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self):
"""
Query Tado for device marked as at home.
Returns boolean if scanning successful.
"""
_LOGGER.debug("Requesting Tado")
last_results = []
response = None
tadojson = None
try:
# get first token
with async_timeout.timeout(10, loop=self.hass.loop):
url = self.tadoapiurl.format(self.username, self.password)
response = yield from self.websession.get(
url
)
# error on Tado webservice
if response.status != 200:
_LOGGER.warning(
"Error %d on %s.", response.status, self.tadoapiurl)
self.token = None
return
tadojson = yield from response.json()
except (asyncio.TimeoutError, aiohttp.errors.ClientError):
_LOGGER.error("Can not load Tado data")
return False
finally:
if response is not None:
yield from response.release()
# Find devices that have geofencing enabled, and are currently at home
for mobiledevice in tadojson['mobileDevices']:
if 'location' in mobiledevice:
if mobiledevice['location']['atHome']:
deviceid = mobiledevice['id']
devicename = mobiledevice['name']
last_results.append(Device(deviceid, devicename))
self.last_results = last_results
_LOGGER.info("Tado presence query successful")
return True