From 90007a04d384e9004a42d529f92e553b9ffa76c7 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Thu, 12 Nov 2015 23:37:15 -0700 Subject: [PATCH 001/146] Adding iCloud device_tracker component. Allow to track devices registered with iCloud --- .../components/device_tracker/icloud.py | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 homeassistant/components/device_tracker/icloud.py diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py new file mode 100644 index 00000000000..f193e68bc22 --- /dev/null +++ b/homeassistant/components/device_tracker/icloud.py @@ -0,0 +1,131 @@ +""" +homeassistant.components.device_tracker.icloud +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Device tracker platform that supports scanning a iCloud devices. + +It does require that your device has registered with Find My iPhone. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/device_tracker.icloud/ +""" +import logging +from datetime import timedelta +import threading + +from homeassistant.const import CONF_USERNAME, CONF_PASSWORD +from homeassistant.helpers import validate_config +from homeassistant.util import Throttle +from homeassistant.components.device_tracker import DOMAIN + +import re + +# Return cached results if last scan was less then this time ago +MIN_TIME_BETWEEN_SCANS = timedelta(seconds=60) + +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['https://github.com/picklepete/pyicloud/archive/' + '80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip' + '#pyicloud==0.8.0', + 'certifi'] + + +#pylint: disable=unused-argument +def get_scanner(hass, config): + """ Validates config and returns a iPhone Scanner. """ + if not validate_config(config, + {DOMAIN: [CONF_USERNAME, CONF_PASSWORD]}, + _LOGGER): + return None + + scanner = ICloudDeviceScanner(config[DOMAIN]) + + return scanner if scanner.success_init else None + + +class ICloudDeviceScanner(object): + """ + This class looks up devices from your iCloud account + and can report on their lat and long if registered. + """ + + def __init__(self, config): + from pyicloud import PyiCloudService + from pyicloud.exceptions import PyiCloudFailedLoginException + from pyicloud.exceptions import PyiCloudNoDevicesException + + self.username = config[CONF_USERNAME] + self.password = config[CONF_PASSWORD] + + self.lock = threading.Lock() + + self.last_results = {} + + # Get the data from iCloud + try: + _LOGGER.info('Logging into iCloud Services') + self._api = PyiCloudService(self.username, self.password, verify=True) + except PyiCloudFailedLoginException: + _LOGGER.exception("Failed login to iCloud Service." + + "Verify Username and Password") + return + + try: + devices = self.get_devices() + except PyiCloudNoDevicesException: + _LOGGER.exception("No iCloud Devices found.") + return + + self.success_init = devices is not None + + if self.success_init: + self.last_results = devices + else: + _LOGGER.error('Issues getting iCloud results') + + def scan_devices(self): + """ + Scans for new devices and return a list containing found devices id's + """ + + self._update_info() + + return [device for device in self.last_results] + + def get_device_name(self, mac): + """ Returns the name of the given device or None if we don't know """ + try: + return next(device for device in self.last_results + if device == mac) + except StopIteration: + return None + + @Throttle(MIN_TIME_BETWEEN_SCANS) + def _update_info(self): + """ Retrieve the latest information from iCloud + Returns a bool if scanning is successful + """ + + if not self.success_init: + return + + with self.lock: + _LOGGER.info('Scanning iCloud Devices') + + self.last_results = self.get_devices() or {} + + def get_devices(self): + devices = {} + for device in self._api.devices: + try: + devices[device.status()['name']] = { + 'device_id': re.sub(r'(\s*|\W*)', device.status()['name'], ''), + 'host_name': device.status()['name'], + 'gps': (device.location()['latitude'], + device.location()['longitude']), + 'battery': device.status()['batteryLevel']*100 + } + except TypeError: + # Device is not tracked. + continue + return devices \ No newline at end of file From c60bb35d4ae7a277117b490ad37e7f000479ca67 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Thu, 12 Nov 2015 23:40:30 -0700 Subject: [PATCH 002/146] Fixed lint errors --- homeassistant/components/device_tracker/icloud.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index f193e68bc22..f4b3998ab40 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -30,7 +30,6 @@ REQUIREMENTS = ['https://github.com/picklepete/pyicloud/archive/' 'certifi'] -#pylint: disable=unused-argument def get_scanner(hass, config): """ Validates config and returns a iPhone Scanner. """ if not validate_config(config, @@ -64,7 +63,9 @@ class ICloudDeviceScanner(object): # Get the data from iCloud try: _LOGGER.info('Logging into iCloud Services') - self._api = PyiCloudService(self.username, self.password, verify=True) + self._api = PyiCloudService(self.username, + self.password, + verify=True) except PyiCloudFailedLoginException: _LOGGER.exception("Failed login to iCloud Service." + "Verify Username and Password") @@ -119,7 +120,9 @@ class ICloudDeviceScanner(object): for device in self._api.devices: try: devices[device.status()['name']] = { - 'device_id': re.sub(r'(\s*|\W*)', device.status()['name'], ''), + 'device_id': re.sub(r'(\s*|\W*)', + device.status()['name'], + ''), 'host_name': device.status()['name'], 'gps': (device.location()['latitude'], device.location()['longitude']), @@ -128,4 +131,4 @@ class ICloudDeviceScanner(object): except TypeError: # Device is not tracked. continue - return devices \ No newline at end of file + return devices From fff6b24449d8ea77aefb66eb603b9f5ad5309061 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Sat, 21 Nov 2015 21:04:28 -0700 Subject: [PATCH 003/146] Switching to new device scanner setup. --- .../components/device_tracker/icloud.py | 163 ++++++------------ 1 file changed, 54 insertions(+), 109 deletions(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index f4b3998ab40..e99d5fc0e30 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -1,134 +1,79 @@ """ homeassistant.components.device_tracker.icloud ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Device tracker platform that supports scanning a iCloud devices. +Device tracker platform that supports scanning iCloud devices. -It does require that your device has registered with Find My iPhone. +It does require that your device has beend registered with Find My iPhone. + +Note: that this may cause battery drainage as it wakes up your device to +get the current location. + +Note: You may receive an email from Apple stating that someone has logged +into your account. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.icloud/ """ import logging -from datetime import timedelta -import threading from homeassistant.const import CONF_USERNAME, CONF_PASSWORD -from homeassistant.helpers import validate_config -from homeassistant.util import Throttle -from homeassistant.components.device_tracker import DOMAIN - +from homeassistant.helpers.event import track_utc_time_change +from pyicloud import PyiCloudService +from pyicloud.exceptions import PyiCloudFailedLoginException +from pyicloud.exceptions import PyiCloudNoDevicesException import re -# Return cached results if last scan was less then this time ago -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=60) +SCAN_INTERVAL = 60 _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['https://github.com/picklepete/pyicloud/archive/' '80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip' - '#pyicloud==0.8.0', - 'certifi'] + '#pyicloud==0.8.0'] -def get_scanner(hass, config): - """ Validates config and returns a iPhone Scanner. """ - if not validate_config(config, - {DOMAIN: [CONF_USERNAME, CONF_PASSWORD]}, - _LOGGER): - return None +def setup_scanner(hass, config, see): - scanner = ICloudDeviceScanner(config[DOMAIN]) + # Get the username and password from the configuration + username = config[CONF_USERNAME] + password = config[CONF_PASSWORD] - return scanner if scanner.success_init else None + try: + _LOGGER.info('Logging into iCloud Account') + # Attempt the login to iCloud + api = PyiCloudService(username, + password, + verify=True) + except PyiCloudFailedLoginException as e: + _LOGGER.exception('Error logging into iCloud Service: {0}'.format(str(e))) - -class ICloudDeviceScanner(object): - """ - This class looks up devices from your iCloud account - and can report on their lat and long if registered. - """ - - def __init__(self, config): - from pyicloud import PyiCloudService - from pyicloud.exceptions import PyiCloudFailedLoginException - from pyicloud.exceptions import PyiCloudNoDevicesException - - self.username = config[CONF_USERNAME] - self.password = config[CONF_PASSWORD] - - self.lock = threading.Lock() - - self.last_results = {} - - # Get the data from iCloud + def update_icloud(now): try: - _LOGGER.info('Logging into iCloud Services') - self._api = PyiCloudService(self.username, - self.password, - verify=True) - except PyiCloudFailedLoginException: - _LOGGER.exception("Failed login to iCloud Service." + - "Verify Username and Password") - return + # The session timeouts if we are not using it so we have to re-authenticate. This will send an email. + api.authenticate() + # Loop through every device registered with the iCloud account + for device in api.devices: + status = device.status() + location = device.location() + # If the device has a location add it. If not do nothing + if location: + see( + dev_id=re.sub(r"(\s|\W|')", + '', + status['name']), + host_name=status['name'], + gps=(location['latitude'], location['longitude']), + battery=status['batteryLevel']*100, + gps_accuracy=location['horizontalAccuracy'] + ) + else: + # No location found for the device so continue + continue + except PyiCloudNoDevicesException as e: + _LOGGER.exception('No iCloud Devices found!') - try: - devices = self.get_devices() - except PyiCloudNoDevicesException: - _LOGGER.exception("No iCloud Devices found.") - return - - self.success_init = devices is not None - - if self.success_init: - self.last_results = devices - else: - _LOGGER.error('Issues getting iCloud results') - - def scan_devices(self): - """ - Scans for new devices and return a list containing found devices id's - """ - - self._update_info() - - return [device for device in self.last_results] - - def get_device_name(self, mac): - """ Returns the name of the given device or None if we don't know """ - try: - return next(device for device in self.last_results - if device == mac) - except StopIteration: - return None - - @Throttle(MIN_TIME_BETWEEN_SCANS) - def _update_info(self): - """ Retrieve the latest information from iCloud - Returns a bool if scanning is successful - """ - - if not self.success_init: - return - - with self.lock: - _LOGGER.info('Scanning iCloud Devices') - - self.last_results = self.get_devices() or {} - - def get_devices(self): - devices = {} - for device in self._api.devices: - try: - devices[device.status()['name']] = { - 'device_id': re.sub(r'(\s*|\W*)', - device.status()['name'], - ''), - 'host_name': device.status()['name'], - 'gps': (device.location()['latitude'], - device.location()['longitude']), - 'battery': device.status()['batteryLevel']*100 - } - except TypeError: - # Device is not tracked. - continue - return devices + track_utc_time_change( + hass, + update_icloud, + second=range(0, 60, SCAN_INTERVAL) + ) \ No newline at end of file From 807485473163e659a35d5bd16622d8d86db19a13 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Sat, 21 Nov 2015 21:12:41 -0700 Subject: [PATCH 004/146] Fixing formatting --- .../components/device_tracker/icloud.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index e99d5fc0e30..5968d7d8ac8 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -33,6 +33,9 @@ REQUIREMENTS = ['https://github.com/picklepete/pyicloud/archive/' def setup_scanner(hass, config, see): + """ + Set up the iCloud Scanner + """ # Get the username and password from the configuration username = config[CONF_USERNAME] @@ -45,11 +48,17 @@ def setup_scanner(hass, config, see): password, verify=True) except PyiCloudFailedLoginException as e: - _LOGGER.exception('Error logging into iCloud Service: {0}'.format(str(e))) + _LOGGER.exception( + 'Error logging into iCloud Service: {0}'.format(str(e)) + ) def update_icloud(now): + """ + Authenticate against iCloud and scan for devices. + """ try: - # The session timeouts if we are not using it so we have to re-authenticate. This will send an email. + # The session timeouts if we are not using it so we + # have to re-authenticate. This will send an email. api.authenticate() # Loop through every device registered with the iCloud account for device in api.devices: @@ -69,11 +78,11 @@ def setup_scanner(hass, config, see): else: # No location found for the device so continue continue - except PyiCloudNoDevicesException as e: + except PyiCloudNoDevicesException: _LOGGER.exception('No iCloud Devices found!') track_utc_time_change( hass, update_icloud, second=range(0, 60, SCAN_INTERVAL) - ) \ No newline at end of file + ) From e3d4e3ad4db6ad32ee6ff16a08e8be656343e1e4 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Fri, 4 Dec 2015 09:08:46 -0700 Subject: [PATCH 005/146] Increasing scan interval. Moved imports. --- homeassistant/components/device_tracker/icloud.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index 5968d7d8ac8..2986bbec595 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -18,12 +18,9 @@ import logging from homeassistant.const import CONF_USERNAME, CONF_PASSWORD from homeassistant.helpers.event import track_utc_time_change -from pyicloud import PyiCloudService -from pyicloud.exceptions import PyiCloudFailedLoginException -from pyicloud.exceptions import PyiCloudNoDevicesException import re -SCAN_INTERVAL = 60 +SCAN_INTERVAL = 1800 _LOGGER = logging.getLogger(__name__) @@ -36,6 +33,9 @@ def setup_scanner(hass, config, see): """ Set up the iCloud Scanner """ + from pyicloud import PyiCloudService + from pyicloud.exceptions import PyiCloudFailedLoginException + from pyicloud.exceptions import PyiCloudNoDevicesException # Get the username and password from the configuration username = config[CONF_USERNAME] @@ -47,10 +47,11 @@ def setup_scanner(hass, config, see): api = PyiCloudService(username, password, verify=True) - except PyiCloudFailedLoginException as e: + except PyiCloudFailedLoginException as error: _LOGGER.exception( - 'Error logging into iCloud Service: {0}'.format(str(e)) + 'Error logging into iCloud Service: {0}'.format(error) ) + return def update_icloud(now): """ @@ -79,7 +80,7 @@ def setup_scanner(hass, config, see): # No location found for the device so continue continue except PyiCloudNoDevicesException: - _LOGGER.exception('No iCloud Devices found!') + _LOGGER.info('No iCloud Devices found!') track_utc_time_change( hass, From 9ecc08c0c8c97d655610f80f3c9090b68704401f Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Fri, 4 Dec 2015 09:19:16 -0700 Subject: [PATCH 006/146] Adding in pyicloud to requirements_all.txt --- homeassistant/components/device_tracker/icloud.py | 4 ++-- requirements_all.txt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index 2986bbec595..d196cc40107 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -16,9 +16,9 @@ https://home-assistant.io/components/device_tracker.icloud/ """ import logging +import re from homeassistant.const import CONF_USERNAME, CONF_PASSWORD from homeassistant.helpers.event import track_utc_time_change -import re SCAN_INTERVAL = 1800 @@ -49,7 +49,7 @@ def setup_scanner(hass, config, see): verify=True) except PyiCloudFailedLoginException as error: _LOGGER.exception( - 'Error logging into iCloud Service: {0}'.format(error) + 'Error logging into iCloud Service: {}'.format(error) ) return diff --git a/requirements_all.txt b/requirements_all.txt index 2715ca3288d..2f5d27d0b7d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -170,3 +170,6 @@ https://github.com/persandstrom/python-verisure/archive/9873c4527f01b1ba1f72ae60 # homeassistant.components.zwave pydispatcher==2.0.5 + +# homeassistant.sensor.icloud +https://github.com/picklepete/pyicloud/archive/80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip#pyicloud==0.8.0 From 254889e3fd6655b312f9f6fd95d0cfe6eed31d9d Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Fri, 4 Dec 2015 09:23:05 -0700 Subject: [PATCH 007/146] Fixing logging for pylint --- homeassistant/components/device_tracker/icloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index d196cc40107..a4adaa547bc 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -49,7 +49,7 @@ def setup_scanner(hass, config, see): verify=True) except PyiCloudFailedLoginException as error: _LOGGER.exception( - 'Error logging into iCloud Service: {}'.format(error) + 'Error logging into iCloud Service: %s' % error ) return From aff82da61166453b955c3ac70ecc977232c94650 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 6 Dec 2015 21:19:20 -0800 Subject: [PATCH 008/146] Version bump to 0.10.0.dev0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 3810edb30c5..9a17622a7dd 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """ Constants used by Home Assistant components. """ -__version__ = "0.9.1" +__version__ = "0.10.0.dev0" # Can be used to specify a catch all when registering state or event listeners. MATCH_ALL = '*' From e60dce97125addeb2a9b0213350b16719f4148f0 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 7 Dec 2015 07:33:07 +0100 Subject: [PATCH 009/146] Update docstrings (influx -> influxdb) --- homeassistant/components/influxdb.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/influxdb.py b/homeassistant/components/influxdb.py index a65126f8102..5569a300652 100644 --- a/homeassistant/components/influxdb.py +++ b/homeassistant/components/influxdb.py @@ -1,19 +1,10 @@ """ -homeassistant.components.influx -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +homeassistant.components.influxdb +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ InfluxDB component which allows you to send data to an Influx database. For more details about this component, please refer to the documentation at -https://home-assistant.io/components/influx/ - -Configuration: - -influx: - host: localhost - port: 8086 - dbname: home_assistant - dbuser: DB_USER - dbuser_password: DB_USER_PASSWORD +https://home-assistant.io/components/influxdb/ """ import logging @@ -43,7 +34,7 @@ CONF_PASSWORD = 'password' def setup(hass, config): - """ Setup the Influx component. """ + """ Setup the InfluxDB component. """ from influxdb import InfluxDBClient, exceptions From 0d4f681a4e497e7bb1d9fa18271e8ab01034806c Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 7 Dec 2015 14:28:24 +0100 Subject: [PATCH 010/146] Fix initialization error and update var name --- homeassistant/components/influxdb.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/influxdb.py b/homeassistant/components/influxdb.py index 5569a300652..2286dd2d659 100644 --- a/homeassistant/components/influxdb.py +++ b/homeassistant/components/influxdb.py @@ -17,7 +17,7 @@ from homeassistant.components.sun import (STATE_ABOVE_HORIZON, _LOGGER = logging.getLogger(__name__) -DOMAIN = "influx" +DOMAIN = "influxdb" DEPENDENCIES = [] DEFAULT_HOST = 'localhost' @@ -45,21 +45,21 @@ def setup(hass, config): host = conf[CONF_HOST] port = util.convert(conf.get(CONF_PORT), int, DEFAULT_PORT) - dbname = util.convert(conf.get(CONF_DB_NAME), str, DEFAULT_DATABASE) + database = util.convert(conf.get(CONF_DB_NAME), str, DEFAULT_DATABASE) username = util.convert(conf.get(CONF_USERNAME), str) password = util.convert(conf.get(CONF_PASSWORD), str) try: influx = InfluxDBClient(host=host, port=port, username=username, - password=password, database=dbname) + password=password, database=database) databases = [i['name'] for i in influx.get_list_database()] except exceptions.InfluxDBClientError: _LOGGER.error("Database host is not accessible. " "Please check your entries in the configuration file.") return False - if dbname not in databases: - _LOGGER.error("Database %s doesn't exist", dbname) + if database not in databases: + _LOGGER.error("Database %s doesn't exist", database) return False def influx_event_listener(event): @@ -97,7 +97,7 @@ def setup(hass, config): try: influx.write_points(json_body) except exceptions.InfluxDBClientError: - _LOGGER.exception('Error saving event to Influx') + _LOGGER.exception('Error saving event to InfluxDB') hass.bus.listen(EVENT_STATE_CHANGED, influx_event_listener) From e1990e07c70fbeefc2fd3330ccf4727bcfc9f1e8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 7 Dec 2015 20:12:07 -0800 Subject: [PATCH 011/146] Conditionally load webcomponents polyfill --- .../components/frontend/index.html.template | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/frontend/index.html.template b/homeassistant/components/frontend/index.html.template index 87c5f6638a7..c0631c9d9db 100644 --- a/homeassistant/components/frontend/index.html.template +++ b/homeassistant/components/frontend/index.html.template @@ -1,5 +1,5 @@ - + Home Assistant @@ -31,11 +31,21 @@ margin-bottom: 123px; } +
- - + From fe485cc27df7c24c7d279c9d9f706e77db4d69dd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 7 Dec 2015 23:43:28 -0800 Subject: [PATCH 012/146] Initial service worker support --- homeassistant/components/frontend/__init__.py | 16 +++++++++++++--- homeassistant/components/frontend/version.py | 2 +- .../frontend/www_static/frontend.html | 18 +++++++++--------- .../frontend/www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 5 +++++ script/build_frontend | 1 + 6 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 homeassistant/components/frontend/www_static/service_worker.js diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index dac2041fa56..5c97d855713 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -22,8 +22,7 @@ _LOGGER = logging.getLogger(__name__) FRONTEND_URLS = [ URL_ROOT, '/logbook', '/history', '/map', '/devService', '/devState', - '/devEvent', '/devInfo'] -STATES_URL = re.compile(r'/states(/([a-zA-Z\._\-0-9/]+)|)') + '/devEvent', '/devInfo', '/states'] _FINGERPRINT = re.compile(r'^(\w+)-[a-z0-9]{32}\.(\w+)$', re.IGNORECASE) @@ -37,7 +36,8 @@ def setup(hass, config): for url in FRONTEND_URLS: hass.http.register_path('GET', url, _handle_get_root, False) - hass.http.register_path('GET', STATES_URL, _handle_get_root, False) + hass.http.register_path('GET', '/service_worker.js', + _handle_get_service_worker, False) # Static files hass.http.register_path( @@ -78,6 +78,16 @@ def _handle_get_root(handler, path_match, data): handler.wfile.write(template_html.encode("UTF-8")) +def _handle_get_service_worker(handler, path_match, data): + if handler.server.development: + sw_path = "home-assistant-polymer/build/service_worker.js" + else: + sw_path = "service_worker.js" + + handler.write_file(os.path.join(os.path.dirname(__file__), 'www_static', + sw_path)) + + def _handle_get_static(handler, path_match, data): """ Returns a static file for the frontend. """ req_file = util.sanitize_path(path_match.group('file')) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index e291ca5bee6..83383baf11d 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,2 +1,2 @@ """ DO NOT MODIFY. Auto-generated by build_frontend script """ -VERSION = "d07b7ed1734ae3f2472f9ae88e0c3dea" +VERSION = "aac488c33cd4291cd0924e60a55bd309" diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 376307744b8..907722b09ee 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -6080,12 +6080,12 @@ case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return font-weight: 300; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; - } \ No newline at end of file + } \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 044a6d9810b..2bc0f827b24 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 044a6d9810b6aa662b82af0f67deb662725ad4cb +Subproject commit 2bc0f827b2477e0f338f67b24e7107243581493f diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js new file mode 100644 index 00000000000..b60f00119e8 --- /dev/null +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -0,0 +1,5 @@ +!function(e){function t(r){if(n[r])return n[r].exports;var s=n[r]={exports:{},id:r,loaded:!1};return e[r].call(s.exports,s,s.exports,t),s.loaded=!0,s.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([/*!*************************************!*\ + !*** ./src/service-worker/index.js ***! + \*************************************/ +function(e,t,n){"use strict";var r="0.10",s="/",c=["/","/logbook","/history","/map","/devService","/devState","/devEvent","/devInfo","/states"],i=["/static/favicon-192x192.png"];self.addEventListener("install",function(e){e.waitUntil(caches.open(r).then(function(e){return e.addAll(i.concat(s))}))}),self.addEventListener("activate",function(e){}),self.addEventListener("message",function(e){}),self.addEventListener("fetch",function(e){var t=e.request.url.substr(e.request.url.indexOf("/",7));i.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(e.request)})),c.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(s).then(function(n){var r=fetch(e.request).then(function(e){return t.put(s,e.clone()),e});return n||r})}))})}]); +//# sourceMappingURL=service_worker.js.map \ No newline at end of file diff --git a/script/build_frontend b/script/build_frontend index 70eacdb6baf..5920026486e 100755 --- a/script/build_frontend +++ b/script/build_frontend @@ -7,6 +7,7 @@ npm run frontend_prod cp bower_components/webcomponentsjs/webcomponents-lite.min.js .. cp build/frontend.html .. +cp build/service_worker.js .. # Generate the MD5 hash of the new frontend cd ../.. From 9f396b44f77ac3341df463a85459003662ff71b1 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 8 Dec 2015 10:10:32 +0100 Subject: [PATCH 013/146] Return numerical value --- homeassistant/components/sensor/forecast.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index c024c19b5f7..42fbe26b9cf 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -147,17 +147,8 @@ class ForeCastSensor(Entity): self._state = data.nearestStormBearing elif self.type == 'precip_intensity': self._state = data.precipIntensity - if data.precipIntensity == 0: - self._state = 'None' - self._unit_of_measurement = '' - else: - self._state = data.precipIntensity elif self.type == 'precip_type': - if data.precipType is None: - self._state = 'None' - self._unit_of_measurement = '' - else: - self._state = data.precipType + self._state = data.precipType elif self.type == 'precip_probability': self._state = round(data.precipProbability * 100, 1) elif self.type == 'dew_point': From 9e41c495fc43c0071c9e24629ba338fa538399d7 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 8 Dec 2015 09:10:06 -0800 Subject: [PATCH 014/146] Update SW: Fix caching bug --- .../components/frontend/www_static/home-assistant-polymer | 2 +- homeassistant/components/frontend/www_static/service_worker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 2bc0f827b24..e51b8add369 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 2bc0f827b2477e0f338f67b24e7107243581493f +Subproject commit e51b8add369f9e81d22b25b4be2400675361afdb diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index b60f00119e8..eb9c41c3abc 100644 --- a/homeassistant/components/frontend/www_static/service_worker.js +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -1,5 +1,5 @@ !function(e){function t(r){if(n[r])return n[r].exports;var s=n[r]={exports:{},id:r,loaded:!1};return e[r].call(s.exports,s,s.exports,t),s.loaded=!0,s.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([/*!*************************************!*\ !*** ./src/service-worker/index.js ***! \*************************************/ -function(e,t,n){"use strict";var r="0.10",s="/",c=["/","/logbook","/history","/map","/devService","/devState","/devEvent","/devInfo","/states"],i=["/static/favicon-192x192.png"];self.addEventListener("install",function(e){e.waitUntil(caches.open(r).then(function(e){return e.addAll(i.concat(s))}))}),self.addEventListener("activate",function(e){}),self.addEventListener("message",function(e){}),self.addEventListener("fetch",function(e){var t=e.request.url.substr(e.request.url.indexOf("/",7));i.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(e.request)})),c.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(s).then(function(n){var r=fetch(e.request).then(function(e){return t.put(s,e.clone()),e});return n||r})}))})}]); +function(e,t,n){"use strict";var r="0.10",s="/",c=["/","/logbook","/history","/map","/devService","/devState","/devEvent","/devInfo","/states"],i=["/static/favicon-192x192.png"];self.addEventListener("install",function(e){e.waitUntil(caches.open(r).then(function(e){return e.addAll(i.concat(s))}))}),self.addEventListener("activate",function(e){}),self.addEventListener("message",function(e){}),self.addEventListener("fetch",function(e){var t=e.request.url.substr(e.request.url.indexOf("/",8));i.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(e.request)})),c.includes(t)&&e.respondWith(caches.open(r).then(function(t){return t.match(s).then(function(n){var r=fetch(e.request).then(function(e){return t.put(s,e.clone()),e});return n||r})}))})}]); //# sourceMappingURL=service_worker.js.map \ No newline at end of file From d84bea3621e55fbb76b5b89ffa0c22f527ed2434 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Tue, 8 Dec 2015 16:15:19 -0700 Subject: [PATCH 015/146] Allow decimal place to be used without corr factor --- homeassistant/components/sensor/arest.py | 15 ++++++--------- .../components/sensor/command_sensor.py | 14 +++++++------- homeassistant/components/sensor/rest.py | 17 +++++------------ 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/sensor/arest.py b/homeassistant/components/sensor/arest.py index f1faa7cc932..0af804a4580 100644 --- a/homeassistant/components/sensor/arest.py +++ b/homeassistant/components/sensor/arest.py @@ -127,15 +127,12 @@ class ArestSensor(Entity): if 'error' in values: return values['error'] elif 'value' in values: - if self._corr_factor is not None \ - and self._decimal_places is not None: - return round((float(values['value']) * - float(self._corr_factor)), self._decimal_places) - elif self._corr_factor is not None \ - and self._decimal_places is None: - return round(float(values['value']) * float(self._corr_factor)) - else: - return values['value'] + value = values['value'] + if self._corr_factor is not None: + value = float(value) * float(self._corr_factor) + if self._decimal_places is not None: + value = round(value, self._decimal_places) + return value else: return values.get(self._variable, 'n/a') diff --git a/homeassistant/components/sensor/command_sensor.py b/homeassistant/components/sensor/command_sensor.py index b5beaab13d0..9dc6ad8c426 100644 --- a/homeassistant/components/sensor/command_sensor.py +++ b/homeassistant/components/sensor/command_sensor.py @@ -35,8 +35,8 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): data, config.get('name', DEFAULT_NAME), config.get('unit_of_measurement'), - config.get('correction_factor', 1.0), - config.get('decimal_places', 0) + config.get('correction_factor', None), + config.get('decimal_places', None) )]) @@ -49,7 +49,7 @@ class CommandSensor(Entity): self._name = name self._state = False self._unit_of_measurement = unit_of_measurement - self._corr_factor = float(corr_factor) + self._corr_factor = corr_factor self._decimal_places = decimal_places self.update() @@ -76,10 +76,10 @@ class CommandSensor(Entity): try: if value is not None: if self._corr_factor is not None: - self._state = round((float(value) * self._corr_factor), - self._decimal_places) - else: - self._state = value + value = float(value) * float(self._corr_factor) + if self._decimal_places is not None: + value = round(value, self._decimal_places) + self._state = value except ValueError: self._state = value diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index 53609dbb237..abe46d03b95 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -136,18 +136,11 @@ class RestSensor(Entity): try: if value is not None: value = RestSensor.extract_value(value, self._variable) - if self._corr_factor is not None \ - and self._decimal_places is not None: - self._state = round( - (float(value) * - float(self._corr_factor)), - self._decimal_places) - elif self._corr_factor is not None \ - and self._decimal_places is None: - self._state = round(float(value) * - float(self._corr_factor)) - else: - self._state = value + if self._corr_factor is not None: + value = float(value) * float(self._corr_factor) + if self._decimal_places is not None: + value = round(value, self._decimal_places) + self._state = value except ValueError: self._state = RestSensor.extract_value(value, self._variable) From 48593c6a683f49d2f1012cf7631de79f7b615abc Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 9 Dec 2015 08:24:12 +0100 Subject: [PATCH 016/146] Add docstrings --- homeassistant/components/frontend/__init__.py | 1 + homeassistant/components/rollershutter/demo.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 5c97d855713..fc955e30d44 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -79,6 +79,7 @@ def _handle_get_root(handler, path_match, data): def _handle_get_service_worker(handler, path_match, data): + """ Returns service worker for the frontend. """ if handler.server.development: sw_path = "home-assistant-polymer/build/service_worker.js" else: diff --git a/homeassistant/components/rollershutter/demo.py b/homeassistant/components/rollershutter/demo.py index a57bf4ddeec..4ffeb6be6dd 100644 --- a/homeassistant/components/rollershutter/demo.py +++ b/homeassistant/components/rollershutter/demo.py @@ -1,7 +1,7 @@ """ homeassistant.components.rollershutter.demo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Demo platform for rollorshutter component. +Demo platform for the rollorshutter component. """ from homeassistant.const import EVENT_TIME_CHANGED from homeassistant.helpers.event import track_utc_time_change @@ -9,7 +9,7 @@ from homeassistant.components.rollershutter import RollershutterDevice def setup_platform(hass, config, add_devices, discovery_info=None): - """ Sets up the Demo binary sensors. """ + """ Sets up the Demo rollershutters. """ add_devices([ DemoRollershutter(hass, 'Kitchen Window', 0), DemoRollershutter(hass, 'Living Room Window', 100), @@ -17,7 +17,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class DemoRollershutter(RollershutterDevice): - """ Represents a rollershutter within Home Assistant. """ + """ Represents a rollershutter.. """ # pylint: disable=no-self-use def __init__(self, hass, name, position): @@ -29,14 +29,17 @@ class DemoRollershutter(RollershutterDevice): @property def name(self): + """ Returns the name of the rollershutter. """ return self._name @property def should_poll(self): + """ No polling needed for a demo rollershutter. """ return False @property def current_position(self): + """ Returns the current position of the rollershutter. """ return self._position def move_up(self, **kwargs): @@ -62,11 +65,13 @@ class DemoRollershutter(RollershutterDevice): self._listener = None def _listen(self): + """ Listens for changes. """ if self._listener is None: self._listener = track_utc_time_change(self.hass, self._time_changed) def _time_changed(self, now): + """ Track time changes. """ if self._moving_up: self._position -= 10 else: From 3938b9f3f6b967e07c8df0b6147cb0e29a1f5c2b Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Wed, 9 Dec 2015 15:16:42 -0700 Subject: [PATCH 017/146] If decimal_places is 0, cast to int after rounding --- homeassistant/components/sensor/arest.py | 2 ++ homeassistant/components/sensor/command_sensor.py | 2 ++ homeassistant/components/sensor/rest.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/homeassistant/components/sensor/arest.py b/homeassistant/components/sensor/arest.py index 0af804a4580..3a0ce01719b 100644 --- a/homeassistant/components/sensor/arest.py +++ b/homeassistant/components/sensor/arest.py @@ -132,6 +132,8 @@ class ArestSensor(Entity): value = float(value) * float(self._corr_factor) if self._decimal_places is not None: value = round(value, self._decimal_places) + if self._decimal_places == 0: + value = int(value) return value else: return values.get(self._variable, 'n/a') diff --git a/homeassistant/components/sensor/command_sensor.py b/homeassistant/components/sensor/command_sensor.py index 9dc6ad8c426..e60723f6bfa 100644 --- a/homeassistant/components/sensor/command_sensor.py +++ b/homeassistant/components/sensor/command_sensor.py @@ -79,6 +79,8 @@ class CommandSensor(Entity): value = float(value) * float(self._corr_factor) if self._decimal_places is not None: value = round(value, self._decimal_places) + if self._decimal_places == 0: + value = int(value) self._state = value except ValueError: self._state = value diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index abe46d03b95..f50113350da 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -140,6 +140,8 @@ class RestSensor(Entity): value = float(value) * float(self._corr_factor) if self._decimal_places is not None: value = round(value, self._decimal_places) + if self._decimal_places == 0: + value = int(value) self._state = value except ValueError: self._state = RestSensor.extract_value(value, self._variable) From 5ff6eb8b9c0287a55357018a0eba9bcd2bdae63f Mon Sep 17 00:00:00 2001 From: MartinHjelmare Date: Thu, 10 Dec 2015 02:56:05 +0100 Subject: [PATCH 018/146] Fix logging lowest level * Set lowest logging level to NOTSET in enable_logging(), bootstrap.py, to enable setting a lower logging level than INFO in the logger component. --- homeassistant/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 41377aadebf..a7507fd12b8 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -275,7 +275,7 @@ def enable_logging(hass, verbose=False, daemon=False, log_rotate_days=None): datefmt='%y-%m-%d %H:%M:%S')) logger = logging.getLogger('') logger.addHandler(err_handler) - logger.setLevel(logging.INFO) # this sets the minimum log level + logger.setLevel(logging.NOTSET) # this sets the minimum log level else: _LOGGER.error( From d3a21bee82bef1c11c926c28298590cba7df82c9 Mon Sep 17 00:00:00 2001 From: happyleaves Date: Thu, 10 Dec 2015 20:52:36 -0500 Subject: [PATCH 019/146] twitch media player --- .../components/media_player/twitch.py | 87 +++++++++++++++++++ requirements_all.txt | 3 + 2 files changed, 90 insertions(+) create mode 100644 homeassistant/components/media_player/twitch.py diff --git a/homeassistant/components/media_player/twitch.py b/homeassistant/components/media_player/twitch.py new file mode 100644 index 00000000000..4b6705c58fd --- /dev/null +++ b/homeassistant/components/media_player/twitch.py @@ -0,0 +1,87 @@ +""" +homeassistant.components.media_player.twitch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Twitch stream status. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.twitch/ +""" + +from homeassistant.const import STATE_PLAYING, STATE_OFF + +from homeassistant.components.media_player import ( + MediaPlayerDevice, MEDIA_TYPE_CHANNEL) + +REQUIREMENTS = ['python-twitch==1.2.0'] +DOMAIN = 'twitch' + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the Twitch platform. """ + add_devices( + [TwitchDevice(channel) for channel in config.get('channels', [])]) + + +class TwitchDevice(MediaPlayerDevice): + """ Represents an Twitch channel. """ + + # pylint: disable=abstract-method + def __init__(self, channel): + self._channel = channel + self._state = STATE_OFF + self._preview = None + self._game = None + self._title = None + + @property + def should_poll(self): + """ Device should be polled. """ + return True + + @property + def state(self): + """ State of the player. """ + return self._state + + # pylint: disable=no-member + def update(self): + """ Update device state. """ + from twitch.api import v3 as twitch + stream = twitch.streams.by_channel(self._channel).get('stream') + if stream: + self._game = stream.get('channel').get('game') + self._title = stream.get('channel').get('status') + self._preview = stream.get('preview').get('small') + self._state = STATE_PLAYING + else: + self._state = STATE_OFF + + @property + def name(self): + """ Channel name. """ + return self._channel + + @property + def media_title(self): + """ Channel title. """ + return self._title + + @property + def app_name(self): + """ Game name. """ + return self._game + + @property + def media_image_url(self): + """ Image preview url of the live stream. """ + return self._preview + + @property + def media_content_type(self): + """ Media type (channel). """ + return MEDIA_TYPE_CHANNEL + + def media_pause(self): + """ Must implement because UI can pause. """ + pass diff --git a/requirements_all.txt b/requirements_all.txt index 15bdeb60a3c..b57e27e8fbd 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -76,6 +76,9 @@ plexapi==1.1.0 # homeassistant.components.media_player.sonos SoCo==0.11.1 +# homeassistant.components.media_player.twitch +python-twitch==1.2.0 + # homeassistant.components.modbus https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b612661.zip#pymodbus==1.2.0 From 452348a7f9c449543623da9e6724da60a46b6882 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 18:13:06 -0800 Subject: [PATCH 020/146] Update default MySensor persistence file path --- homeassistant/components/sensor/mysensors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/mysensors.py b/homeassistant/components/sensor/mysensors.py index 7c8fbc47e2a..fb61173d8ee 100644 --- a/homeassistant/components/sensor/mysensors.py +++ b/homeassistant/components/sensor/mysensors.py @@ -76,7 +76,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False persistence = config.get(CONF_PERSISTENCE, True) - persistence_file = config.get(CONF_PERSISTENCE_FILE, 'mysensors.pickle') + persistence_file = config.get(CONF_PERSISTENCE_FILE, + hass.config.path('mysensors.pickle')) version = config.get(CONF_VERSION, '1.4') gateway = mysensors.SerialGateway(port, sensor_update, From fc8c26005ca11ecc9055642fd20fc8ffc6c80dfa Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 18:16:49 -0800 Subject: [PATCH 021/146] Change Travis caching to be less invasive --- .travis.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index f12d318b5d4..c0edf5976a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,9 @@ sudo: false language: python -cache: - directories: - - $HOME/virtualenv/python$TRAVIS_PYTHON_VERSION/ +cache: pip python: - - 3.4.2 - - 3.5.0 + - 3.4 + - 3.5 install: - script/bootstrap_server script: From de68d3355ad6a294e6a3551940adedf47109066d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Dec 2015 16:20:09 -0800 Subject: [PATCH 022/146] Add template support --- homeassistant/util/template.py | 58 ++++++++++++++++++++++++++++++++++ tests/util/test_template.py | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 homeassistant/util/template.py create mode 100644 tests/util/test_template.py diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py new file mode 100644 index 00000000000..5ab3f149174 --- /dev/null +++ b/homeassistant/util/template.py @@ -0,0 +1,58 @@ +""" +homeassistant.util.template +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Template utility methods for rendering strings with HA data. +""" +# pylint: disable=too-few-public-methods +from jinja2.sandbox import SandboxedEnvironment + +ENV = SandboxedEnvironment() + + +def forgiving_round(value, precision): + """ Rounding method that accepts strings. """ + try: + return round(float(value), precision) + except ValueError: + # If value can't be converted to float + return value + + +ENV.filters['round'] = forgiving_round + + +def render(hass, template): + """ Render given template. """ + return ENV.from_string(template).render( + states=AllStates(hass)) + + +class AllStates(object): + """ Class to expose all HA states as attributes. """ + def __init__(self, hass): + self._hass = hass + + def __getattr__(self, name): + return DomainStates(self._hass, name) + + def __iter__(self): + return iter(sorted(self._hass.states.all(), + key=lambda state: state.entity_id)) + + +class DomainStates(object): + """ Class to expose a specific HA domain as attributes. """ + + def __init__(self, hass, domain): + self._hass = hass + self._domain = domain + + def __getattr__(self, name): + return self._hass.states.get('{}.{}'.format(self._domain, name)) + + def __iter__(self): + return iter(sorted( + (state for state in self._hass.states.all() + if state.domain == self._domain), + key=lambda state: state.entity_id)) diff --git a/tests/util/test_template.py b/tests/util/test_template.py new file mode 100644 index 00000000000..081a93ff867 --- /dev/null +++ b/tests/util/test_template.py @@ -0,0 +1,57 @@ +""" +tests.test_util +~~~~~~~~~~~~~~~~~ + +Tests Home Assistant util methods. +""" +# pylint: disable=too-many-public-methods +import unittest +import homeassistant.core as ha + +from homeassistant.util import template + + +class TestUtilTemplate(unittest.TestCase): + + def setUp(self): # pylint: disable=invalid-name + self.hass = ha.HomeAssistant() + + def tearDown(self): # pylint: disable=invalid-name + """ Stop down stuff we started. """ + self.hass.stop() + + def test_referring_states_by_entity_id(self): + self.hass.states.set('test.object', 'happy') + self.assertEqual( + 'happy', + template.render(self.hass, '{{ states.test.object.state }}')) + + def test_iterating_all_states(self): + self.hass.states.set('test.object', 'happy') + self.hass.states.set('sensor.temperature', 10) + + self.assertEqual( + '10happy', + template.render( + self.hass, + '{% for state in states %}{{ state.state }}{% endfor %}')) + + def test_iterating_domain_states(self): + self.hass.states.set('test.object', 'happy') + self.hass.states.set('sensor.back_door', 'open') + self.hass.states.set('sensor.temperature', 10) + + self.assertEqual( + 'open10', + template.render( + self.hass, + '{% for state in states.sensor %}{{ state.state }}{% endfor %}')) + + def test_rounding_value(self): + self.hass.states.set('sensor.temperature', 12.34) + + self.assertEqual( + '12.3', + template.render( + self.hass, + '{{ states.sensor.temperature.state | round(1) }}')) From b440c260e6e7ecf321039607d94ff1fee8f523a8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Dec 2015 16:36:24 -0800 Subject: [PATCH 023/146] Add jinja2 to dependencies. --- requirements_all.txt | 1 + setup.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index 15bdeb60a3c..9587ba55d27 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -4,6 +4,7 @@ pyyaml>=3.11,<4 pytz>=2015.4 pip>=7.0.0 vincenty==0.1.3 +jinja2>=2.8 # homeassistant.components.arduino PyMata==2.07a diff --git a/setup.py b/setup.py index 945138cd34b..2508b44e2fd 100755 --- a/setup.py +++ b/setup.py @@ -14,7 +14,8 @@ REQUIRES = [ 'pyyaml>=3.11,<4', 'pytz>=2015.4', 'pip>=7.0.0', - 'vincenty==0.1.3' + 'vincenty==0.1.3', + 'jinja2>=2.8' ] setup( From af09a305cf90efdd98229315fab47884bf2baafc Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Dec 2015 16:36:47 -0800 Subject: [PATCH 024/146] Add multiply template filter --- homeassistant/util/template.py | 13 +++++++++++-- tests/util/test_template.py | 9 +++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index 5ab3f149174..9fbbcff13b9 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -10,16 +10,25 @@ from jinja2.sandbox import SandboxedEnvironment ENV = SandboxedEnvironment() -def forgiving_round(value, precision): +def forgiving_round(value, precision=0): """ Rounding method that accepts strings. """ try: - return round(float(value), precision) + return int(value) if precision == 0 else round(float(value), precision) except ValueError: # If value can't be converted to float return value +def multiply(value, amount): + """ Converts to float and multiplies value. """ + try: + return float(value) * amount + except ValueError: + # If value can't be converted to float + return value + ENV.filters['round'] = forgiving_round +ENV.filters['multiply'] = multiply def render(hass, template): diff --git a/tests/util/test_template.py b/tests/util/test_template.py index 081a93ff867..4592e4549d4 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -55,3 +55,12 @@ class TestUtilTemplate(unittest.TestCase): template.render( self.hass, '{{ states.sensor.temperature.state | round(1) }}')) + + def test_rounding_value2(self): + self.hass.states.set('sensor.temperature', 12.34) + + self.assertEqual( + '123', + template.render( + self.hass, + '{{ states.sensor.temperature.state | multiply(10) | round }}')) From d1383ac94d1eced5ae811f14639f2a315611e161 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Dec 2015 23:46:50 -0800 Subject: [PATCH 025/146] Add template parsing to notify --- homeassistant/components/notify/__init__.py | 16 ++++++-- tests/components/notify/__init__.py | 0 tests/components/notify/test_demo.py | 41 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/components/notify/__init__.py create mode 100644 tests/components/notify/test_demo.py diff --git a/homeassistant/components/notify/__init__.py b/homeassistant/components/notify/__init__.py index 9182f1dbf3a..245b9c6fde3 100644 --- a/homeassistant/components/notify/__init__.py +++ b/homeassistant/components/notify/__init__.py @@ -13,6 +13,7 @@ import os import homeassistant.bootstrap as bootstrap from homeassistant.config import load_yaml_config_file from homeassistant.helpers import config_per_platform +from homeassistant.util import template from homeassistant.const import CONF_NAME @@ -33,9 +34,16 @@ SERVICE_NOTIFY = "notify" _LOGGER = logging.getLogger(__name__) -def send_message(hass, message): +def send_message(hass, message, title=None): """ Send a notification message. """ - hass.services.call(DOMAIN, SERVICE_NOTIFY, {ATTR_MESSAGE: message}) + data = { + ATTR_MESSAGE: message + } + + if title is not None: + data[ATTR_TITLE] = title + + hass.services.call(DOMAIN, SERVICE_NOTIFY, data) def setup(hass, config): @@ -70,8 +78,10 @@ def setup(hass, config): if message is None: return - title = call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT) + title = template.render( + hass, call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)) target = call.data.get(ATTR_TARGET) + message = template.render(hass, message) notify_service.send_message(message, title=title, target=target) diff --git a/tests/components/notify/__init__.py b/tests/components/notify/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/components/notify/test_demo.py b/tests/components/notify/test_demo.py new file mode 100644 index 00000000000..182a2a38610 --- /dev/null +++ b/tests/components/notify/test_demo.py @@ -0,0 +1,41 @@ +""" +tests.components.notify.test_demo +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Tests notify demo component +""" +import unittest + +import homeassistant.core as ha +import homeassistant.components.notify as notify +from homeassistant.components.notify import demo + + +class TestNotifyDemo(unittest.TestCase): + """ Test the demo notify. """ + + def setUp(self): # pylint: disable=invalid-name + self.hass = ha.HomeAssistant() + self.assertTrue(notify.setup(self.hass, { + 'notify': { + 'platform': 'demo' + } + })) + self.events = [] + + def record_event(event): + self.events.append(event) + + self.hass.bus.listen(demo.EVENT_NOTIFY, record_event) + + def tearDown(self): # pylint: disable=invalid-name + """ Stop down stuff we started. """ + self.hass.stop() + + def test_sending_templated_message(self): + self.hass.states.set('sensor.temperature', 10) + notify.send_message(self.hass, '{{ states.sensor.temperature.state }}', + '{{ states.sensor.temperature.name }}') + self.hass.pool.block_till_done() + last_event = self.events[-1] + self.assertEqual(last_event.data[notify.ATTR_TITLE], 'temperature') + self.assertEqual(last_event.data[notify.ATTR_MESSAGE], '10') From 47b5fbfaf359774b71308728fe296fd32225d34c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Dec 2015 23:56:20 -0800 Subject: [PATCH 026/146] Add template API endpoint --- homeassistant/components/api.py | 20 ++++++++++++++++++-- homeassistant/const.py | 1 + tests/components/test_api.py | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/api.py b/homeassistant/components/api.py index 1e6e66baee0..6a66a2a110e 100644 --- a/homeassistant/components/api.py +++ b/homeassistant/components/api.py @@ -14,14 +14,16 @@ import json import homeassistant.core as ha from homeassistant.helpers.state import TrackStates import homeassistant.remote as rem +from homeassistant.util import template from homeassistant.bootstrap import ERROR_LOG_FILENAME from homeassistant.const import ( URL_API, URL_API_STATES, URL_API_EVENTS, URL_API_SERVICES, URL_API_STREAM, URL_API_EVENT_FORWARD, URL_API_STATES_ENTITY, URL_API_COMPONENTS, URL_API_CONFIG, URL_API_BOOTSTRAP, URL_API_ERROR_LOG, URL_API_LOG_OUT, - EVENT_TIME_CHANGED, EVENT_HOMEASSISTANT_STOP, MATCH_ALL, + URL_API_TEMPLATE, EVENT_TIME_CHANGED, EVENT_HOMEASSISTANT_STOP, MATCH_ALL, HTTP_OK, HTTP_CREATED, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, - HTTP_UNPROCESSABLE_ENTITY) + HTTP_UNPROCESSABLE_ENTITY, HTTP_HEADER_CONTENT_TYPE, + CONTENT_TYPE_TEXT_PLAIN) DOMAIN = 'api' @@ -91,6 +93,9 @@ def setup(hass, config): hass.http.register_path('POST', URL_API_LOG_OUT, _handle_post_api_log_out) + hass.http.register_path('POST', URL_API_TEMPLATE, + _handle_post_api_template) + return True @@ -359,6 +364,17 @@ def _handle_post_api_log_out(handler, path_match, data): handler.end_headers() +def _handle_post_api_template(handler, path_match, data): + """ Log user out. """ + template_string = data.get('template', '') + + handler.send_response(HTTP_OK) + handler.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN) + handler.end_headers() + handler.wfile.write( + template.render(handler.server.hass, template_string).encode('utf-8')) + + def _services_json(hass): """ Generate services data to JSONify. """ return [{"domain": key, "services": value} diff --git a/homeassistant/const.py b/homeassistant/const.py index 9a17622a7dd..cdb56e60131 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -165,6 +165,7 @@ URL_API_COMPONENTS = "/api/components" URL_API_BOOTSTRAP = "/api/bootstrap" URL_API_ERROR_LOG = "/api/error_log" URL_API_LOG_OUT = "/api/log_out" +URL_API_TEMPLATE = "/api/template" HTTP_OK = 200 HTTP_CREATED = 201 diff --git a/tests/components/test_api.py b/tests/components/test_api.py index ab76ed0e3db..cf530c1f301 100644 --- a/tests/components/test_api.py +++ b/tests/components/test_api.py @@ -326,6 +326,20 @@ class TestAPI(unittest.TestCase): self.assertEqual(1, len(test_value)) + def test_api_template(self): + """ Test template API. """ + hass.states.set('sensor.temperature', 10) + + req = requests.post( + _url(const.URL_API_TEMPLATE), + data=json.dumps({"template": + '{{ states.sensor.temperature.state }}'}), + headers=HA_HEADERS) + + hass.pool.block_till_done() + + self.assertEqual('10', req.text) + def test_api_event_forward(self): """ Test setting up event forwarding. """ From 0dcc69d800e7cec122f1bf56505eb0bd39cde5d6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 20:46:15 -0800 Subject: [PATCH 027/146] Fix template rounding --- homeassistant/util/template.py | 3 ++- tests/util/test_template.py | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index 9fbbcff13b9..7e3c1f573b0 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -13,7 +13,8 @@ ENV = SandboxedEnvironment() def forgiving_round(value, precision=0): """ Rounding method that accepts strings. """ try: - return int(value) if precision == 0 else round(float(value), precision) + return int(float(value)) if precision == 0 else round(float(value), + precision) except ValueError: # If value can't be converted to float return value diff --git a/tests/util/test_template.py b/tests/util/test_template.py index 4592e4549d4..b8752806625 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -48,19 +48,19 @@ class TestUtilTemplate(unittest.TestCase): '{% for state in states.sensor %}{{ state.state }}{% endfor %}')) def test_rounding_value(self): - self.hass.states.set('sensor.temperature', 12.34) + self.hass.states.set('sensor.temperature', 12.78) self.assertEqual( - '12.3', + '12.8', template.render( self.hass, '{{ states.sensor.temperature.state | round(1) }}')) def test_rounding_value2(self): - self.hass.states.set('sensor.temperature', 12.34) + self.hass.states.set('sensor.temperature', 12.72) self.assertEqual( - '123', + '127', template.render( self.hass, '{{ states.sensor.temperature.state | multiply(10) | round }}')) From 7acef84aadce6edca1c0fdc6def2310db161b0f7 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 21:16:05 -0800 Subject: [PATCH 028/146] Add variable support to template rendering --- homeassistant/util/template.py | 59 ++++++++++++++++++---------------- tests/util/test_template.py | 8 +++++ 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index 7e3c1f573b0..37eed7ad3f5 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -5,37 +5,17 @@ homeassistant.util.template Template utility methods for rendering strings with HA data. """ # pylint: disable=too-few-public-methods -from jinja2.sandbox import SandboxedEnvironment - -ENV = SandboxedEnvironment() +from jinja2.sandbox import ImmutableSandboxedEnvironment -def forgiving_round(value, precision=0): - """ Rounding method that accepts strings. """ - try: - return int(float(value)) if precision == 0 else round(float(value), - precision) - except ValueError: - # If value can't be converted to float - return value - - -def multiply(value, amount): - """ Converts to float and multiplies value. """ - try: - return float(value) * amount - except ValueError: - # If value can't be converted to float - return value - -ENV.filters['round'] = forgiving_round -ENV.filters['multiply'] = multiply - - -def render(hass, template): +def render(hass, template, variables=None, **kwargs): """ Render given template. """ - return ENV.from_string(template).render( - states=AllStates(hass)) + if variables is not None: + kwargs.update(variables) + + return ENV.from_string(template, { + 'states': AllStates(hass) + }).render(kwargs) class AllStates(object): @@ -66,3 +46,26 @@ class DomainStates(object): (state for state in self._hass.states.all() if state.domain == self._domain), key=lambda state: state.entity_id)) + + +def forgiving_round(value, precision=0): + """ Rounding method that accepts strings. """ + try: + return int(float(value)) if precision == 0 else round(float(value), + precision) + except ValueError: + # If value can't be converted to float + return value + + +def multiply(value, amount): + """ Converts to float and multiplies value. """ + try: + return float(value) * amount + except ValueError: + # If value can't be converted to float + return value + +ENV = ImmutableSandboxedEnvironment() +ENV.filters['round'] = forgiving_round +ENV.filters['multiply'] = multiply diff --git a/tests/util/test_template.py b/tests/util/test_template.py index b8752806625..e85ed6dbba6 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -64,3 +64,11 @@ class TestUtilTemplate(unittest.TestCase): template.render( self.hass, '{{ states.sensor.temperature.state | multiply(10) | round }}')) + + def test_passing_vars_as_keywords(self): + self.assertEqual( + '127', template.render(self.hass, '{{ hello }}', hello=127)) + + def test_passing_vars_as_vars(self): + self.assertEqual( + '127', template.render(self.hass, '{{ hello }}', {'hello': 127})) From d55fda28c235570f330b0cb1253b62aaeebd69a0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 21:38:35 -0800 Subject: [PATCH 029/146] Add value renderer helper method --- homeassistant/util/template.py | 15 +++++++++++++++ tests/util/test_template.py | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index 37eed7ad3f5..107532db776 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -5,9 +5,24 @@ homeassistant.util.template Template utility methods for rendering strings with HA data. """ # pylint: disable=too-few-public-methods +import json from jinja2.sandbox import ImmutableSandboxedEnvironment +def render_with_possible_json_value(hass, template, value): + """ Renders template with value exposed. + If valid JSON will expose value_json too. """ + variables = { + 'value': value + } + try: + variables['value_json'] = json.loads(value) + except ValueError: + pass + + return render(hass, template, variables) + + def render(hass, template, variables=None, **kwargs): """ Render given template. """ if variables is not None: diff --git a/tests/util/test_template.py b/tests/util/test_template.py index e85ed6dbba6..5c1dfff1f85 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -72,3 +72,15 @@ class TestUtilTemplate(unittest.TestCase): def test_passing_vars_as_vars(self): self.assertEqual( '127', template.render(self.hass, '{{ hello }}', {'hello': 127})) + + def test_render_with_possible_json_value_with_valid_json(self): + self.assertEqual( + 'world', + template.render_with_possible_json_value( + self.hass, '{{ value_json.hello }}', '{"hello": "world"}')) + + def test_render_with_possible_json_value_with_invalid_json(self): + self.assertEqual( + '', + template.render_with_possible_json_value( + self.hass, '{{ value_json }}', '{ I AM NOT JSON }')) From 9a9ecb59165192a88c700412e65c21f1bca7d401 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Dec 2015 21:39:01 -0800 Subject: [PATCH 030/146] Migrate MQTT from jsonpath to templates --- homeassistant/components/mqtt/__init__.py | 30 +------------------ .../components/rollershutter/mqtt.py | 16 ++++++---- homeassistant/components/sensor/mqtt.py | 12 +++++--- homeassistant/components/switch/mqtt.py | 11 ++++--- homeassistant/const.py | 2 ++ tests/components/sensor/test_mqtt.py | 3 +- tests/components/switch/test_mqtt.py | 2 +- 7 files changed, 30 insertions(+), 46 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 2c5dbf82923..37a7a63c72b 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -6,7 +6,6 @@ MQTT component, using paho-mqtt. For more details about this component, please refer to the documentation at https://home-assistant.io/components/mqtt/ """ -import json import logging import os import socket @@ -33,7 +32,7 @@ DEFAULT_RETAIN = False SERVICE_PUBLISH = 'publish' EVENT_MQTT_MESSAGE_RECEIVED = 'MQTT_MESSAGE_RECEIVED' -REQUIREMENTS = ['paho-mqtt==1.1', 'jsonpath-rw==1.4.0'] +REQUIREMENTS = ['paho-mqtt==1.1'] CONF_BROKER = 'broker' CONF_PORT = 'port' @@ -136,33 +135,6 @@ def setup(hass, config): return True -# pylint: disable=too-few-public-methods -class _JsonFmtParser(object): - """ Implements a JSON parser on xpath. """ - def __init__(self, jsonpath): - import jsonpath_rw - self._expr = jsonpath_rw.parse(jsonpath) - - def __call__(self, payload): - match = self._expr.find(json.loads(payload)) - return match[0].value if len(match) > 0 else payload - - -# pylint: disable=too-few-public-methods -class FmtParser(object): - """ Wrapper for all supported formats. """ - def __init__(self, fmt): - self._parse = lambda x: x - if fmt: - if fmt.startswith('json:'): - self._parse = _JsonFmtParser(fmt[5:]) - - def __call__(self, payload): - return self._parse(payload) - - -# This is based on one of the paho-mqtt examples: -# http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.python.git/tree/examples/sub-class.py # pylint: disable=too-many-arguments class MQTT(object): """ Implements messaging service for MQTT. """ diff --git a/homeassistant/components/rollershutter/mqtt.py b/homeassistant/components/rollershutter/mqtt.py index f5eb5652516..2951d772be0 100644 --- a/homeassistant/components/rollershutter/mqtt.py +++ b/homeassistant/components/rollershutter/mqtt.py @@ -8,7 +8,10 @@ https://home-assistant.io/components/rollershutter.mqtt/ """ import logging import homeassistant.components.mqtt as mqtt +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.components.rollershutter import RollershutterDevice +from homeassistant.util import template + _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['mqtt'] @@ -36,14 +39,14 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): config.get('payload_up', DEFAULT_PAYLOAD_UP), config.get('payload_down', DEFAULT_PAYLOAD_DOWN), config.get('payload_stop', DEFAULT_PAYLOAD_STOP), - config.get('state_format'))]) + config.get(CONF_VALUE_TEMPLATE))]) # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttRollershutter(RollershutterDevice): """ Represents a rollershutter that can be controlled using MQTT. """ def __init__(self, hass, name, state_topic, command_topic, qos, - payload_up, payload_down, payload_stop, state_format): + payload_up, payload_down, payload_stop, value_template): self._state = None self._hass = hass self._name = name @@ -53,16 +56,17 @@ class MqttRollershutter(RollershutterDevice): self._payload_up = payload_up self._payload_down = payload_down self._payload_stop = payload_stop - self._parse = mqtt.FmtParser(state_format) if self._state_topic is None: return def message_received(topic, payload, qos): """ A new MQTT message has been received. """ - value = self._parse(payload) - if value.isnumeric() and 0 <= int(value) <= 100: - self._state = int(value) + if value_template is not None: + payload = template.render_with_possible_json_value( + hass, value_template, payload) + if payload.isnumeric() and 0 <= int(payload) <= 100: + self._state = int(payload) self.update_ha_state() else: _LOGGER.warning( diff --git a/homeassistant/components/sensor/mqtt.py b/homeassistant/components/sensor/mqtt.py index 2bbed97e40c..8cf2569acd5 100644 --- a/homeassistant/components/sensor/mqtt.py +++ b/homeassistant/components/sensor/mqtt.py @@ -7,7 +7,9 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.mqtt/ """ import logging +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.helpers.entity import Entity +from homeassistant.util import template import homeassistant.components.mqtt as mqtt _LOGGER = logging.getLogger(__name__) @@ -32,25 +34,27 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): config.get('state_topic'), config.get('qos', DEFAULT_QOS), config.get('unit_of_measurement'), - config.get('state_format'))]) + config.get(CONF_VALUE_TEMPLATE))]) # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttSensor(Entity): """ Represents a sensor that can be updated using MQTT. """ def __init__(self, hass, name, state_topic, qos, unit_of_measurement, - state_format): + value_template): self._state = "-" self._hass = hass self._name = name self._state_topic = state_topic self._qos = qos self._unit_of_measurement = unit_of_measurement - self._parse = mqtt.FmtParser(state_format) def message_received(topic, payload, qos): """ A new MQTT message has been received. """ - self._state = self._parse(payload) + if value_template is not None: + payload = template.render_with_possible_json_value( + hass, value_template, payload) + self._state = payload self.update_ha_state() mqtt.subscribe(hass, self._state_topic, message_received, self._qos) diff --git a/homeassistant/components/switch/mqtt.py b/homeassistant/components/switch/mqtt.py index 7b973799eed..c27709cc522 100644 --- a/homeassistant/components/switch/mqtt.py +++ b/homeassistant/components/switch/mqtt.py @@ -8,7 +8,9 @@ https://home-assistant.io/components/switch.mqtt/ """ import logging import homeassistant.components.mqtt as mqtt +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.components.switch import SwitchDevice +from homeassistant.util import template _LOGGER = logging.getLogger(__name__) @@ -40,14 +42,14 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): config.get('payload_on', DEFAULT_PAYLOAD_ON), config.get('payload_off', DEFAULT_PAYLOAD_OFF), config.get('optimistic', DEFAULT_OPTIMISTIC), - config.get('state_format'))]) + config.get(CONF_VALUE_TEMPLATE))]) # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttSwitch(SwitchDevice): """ Represents a switch that can be toggled using MQTT. """ def __init__(self, hass, name, state_topic, command_topic, qos, retain, - payload_on, payload_off, optimistic, state_format): + payload_on, payload_off, optimistic, value_template): self._state = False self._hass = hass self._name = name @@ -58,11 +60,12 @@ class MqttSwitch(SwitchDevice): self._payload_on = payload_on self._payload_off = payload_off self._optimistic = optimistic - self._parse = mqtt.FmtParser(state_format) def message_received(topic, payload, qos): """ A new MQTT message has been received. """ - payload = self._parse(payload) + if value_template is not None: + payload = template.render_with_possible_json_value( + hass, value_template, payload) if payload == self._payload_on: self._state = True self.update_ha_state() diff --git a/homeassistant/const.py b/homeassistant/const.py index cdb56e60131..287ae7998d2 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -25,6 +25,8 @@ CONF_PASSWORD = "password" CONF_API_KEY = "api_key" CONF_ACCESS_TOKEN = "access_token" +CONF_VALUE_TEMPLATE = "value_template" + # #### EVENTS #### EVENT_HOMEASSISTANT_START = "homeassistant_start" EVENT_HOMEASSISTANT_STOP = "homeassistant_stop" diff --git a/tests/components/sensor/test_mqtt.py b/tests/components/sensor/test_mqtt.py index 0c17b95e212..ce98a9399a5 100644 --- a/tests/components/sensor/test_mqtt.py +++ b/tests/components/sensor/test_mqtt.py @@ -47,7 +47,7 @@ class TestSensorMQTT(unittest.TestCase): 'name': 'test', 'state_topic': 'test-topic', 'unit_of_measurement': 'fav unit', - 'state_format': 'json:val' + 'value_template': '{{ value_json.val }}' } })) @@ -56,4 +56,3 @@ class TestSensorMQTT(unittest.TestCase): state = self.hass.states.get('sensor.test') self.assertEqual('100', state.state) - diff --git a/tests/components/switch/test_mqtt.py b/tests/components/switch/test_mqtt.py index 2cfe29c2910..b7c20e5ff94 100644 --- a/tests/components/switch/test_mqtt.py +++ b/tests/components/switch/test_mqtt.py @@ -90,7 +90,7 @@ class TestSensorMQTT(unittest.TestCase): 'command_topic': 'command-topic', 'payload_on': 'beer on', 'payload_off': 'beer off', - 'state_format': 'json:val' + 'value_template': '{{ value_json.val }}' } })) From e19af76c703be943c51af70cd9fd3a34fcb520cd Mon Sep 17 00:00:00 2001 From: andylockran Date: Fri, 11 Dec 2015 12:45:27 +0000 Subject: [PATCH 031/146] Added heatmiser thermostat support --- .coveragerc | 1 + .../components/thermostat/heatmiser.py | 113 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 117 insertions(+) create mode 100644 homeassistant/components/thermostat/heatmiser.py diff --git a/.coveragerc b/.coveragerc index be4219e3163..993f8c9533b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -112,6 +112,7 @@ omit = homeassistant/components/thermostat/honeywell.py homeassistant/components/thermostat/nest.py homeassistant/components/thermostat/radiotherm.py + homeassistant/components/thermostat/heatmiser.py [report] diff --git a/homeassistant/components/thermostat/heatmiser.py b/homeassistant/components/thermostat/heatmiser.py new file mode 100644 index 00000000000..eaeef858172 --- /dev/null +++ b/homeassistant/components/thermostat/heatmiser.py @@ -0,0 +1,113 @@ +""" +homeassistant.components.thermostat.heatmiser +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adds support for the PRT Heatmiser themostats using the V3 protocol. + +See https://github.com/andylockran/heatmiserV3 for more info on the +heatmiserV3 module dependency. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/thermostat.heatmiser/ +""" +import logging +import heatmiserV3 +from homeassistant.components.thermostat import ThermostatDevice +from homeassistant.const import TEMP_CELCIUS + +CONF_IPADDRESS = 'ipaddress' +CONF_PORT = 'port' +CONF_TSTATS = 'tstats' + +REQUIREMENTS = ["heatmiserV3==0.9.1"] + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the heatmiser thermostat. """ + + ipaddress = str(config[CONF_IPADDRESS]) + port = str(config[CONF_PORT]) + + if ipaddress is None or port is None: + _LOGGER.error("Missing required configuration items %s or %s", + CONF_IPADDRESS, CONF_PORT) + return False + + serport = heatmiserV3.connection.connection(ipaddress, port) + serport.open() + + tstats = [] + if CONF_TSTATS in config: + tstats = config[CONF_TSTATS] + + if tstats is None: + _LOGGER.error("No thermostats configured.") + return False + + for tstat in tstats: + add_devices([ + HeatmiserV3Thermostat( + tstat.get("id"), + tstat.get("name"), + serport) + ]) + return + + +class HeatmiserV3Thermostat(ThermostatDevice): + """ Represents a HeatmiserV3 thermostat. """ + + def __init__(self, device, name, serport): + self.device = device + self.serport = serport + self._current_temperature = None + self._name = name + self._id = device + self.dcb = None + self.update() + self._target_temperature = int(self.dcb.get("roomset")) + + @property + def name(self): + """ Returns the name of the honeywell, if any. """ + return self._name + + @property + def unit_of_measurement(self): + """ Unit of measurement this thermostat uses.""" + return TEMP_CELCIUS + + @property + def current_temperature(self): + """ Returns the current temperature. """ + if self.dcb is not None: + low = self.dcb.get("floortemplow ") + high = self.dcb.get("floortemphigh") + temp = (high*256 + low)/10.0 + self._current_temperature = temp + else: + self._current_temperature = None + return self._current_temperature + + @property + def target_temperature(self): + """ Returns the temperature we try to reach. """ + return self._target_temperature + + def set_temperature(self, temperature): + """ Set new target temperature """ + temperature = int(temperature) + heatmiserV3.heatmiser.hmSendAddress( + self._id, + 18, + temperature, + 1, + self.serport) + self._target_temperature = int(temperature) + + def update(self): + self.dcb = heatmiserV3.heatmiser.hmReadAddress( + self._id, + 'prt', + self.serport) diff --git a/requirements_all.txt b/requirements_all.txt index 15bdeb60a3c..252362c7052 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -173,3 +173,6 @@ https://github.com/persandstrom/python-verisure/archive/9873c4527f01b1ba1f72ae60 # homeassistant.components.zwave pydispatcher==2.0.5 + +# homeassistant.components.heatmiser +heatmiserV3==0.9.1 From 2368e5f4ecdc53a55eb4cbb7aca221ae25c0f629 Mon Sep 17 00:00:00 2001 From: Chris Baumgartner Date: Fri, 11 Dec 2015 09:47:28 -0600 Subject: [PATCH 032/146] The target temp (shown in Thermostat card) is not correct when running in heat or cool modes. It is ok for auto mode. --- homeassistant/components/thermostat/ecobee.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/thermostat/ecobee.py b/homeassistant/components/thermostat/ecobee.py index a10d2940001..30221689274 100644 --- a/homeassistant/components/thermostat/ecobee.py +++ b/homeassistant/components/thermostat/ecobee.py @@ -87,7 +87,13 @@ class Thermostat(ThermostatDevice): @property def target_temperature(self): """ Returns the temperature we try to reach. """ - return (self.target_temperature_low + self.target_temperature_high) / 2 + if self.hvac_mode == 'heat' or self.hvac_mode == 'auxHeatOnly': + return self.target_temperature_low + elif self.hvac_mode == 'cool': + return self.target_temperature_high + else: + return (self.target_temperature_low + + self.target_temperature_high) / 2 @property def target_temperature_low(self): From 1c5411101878c886cf9cced53b9b0c9d6652e465 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Fri, 11 Dec 2015 15:19:49 -0700 Subject: [PATCH 033/146] Add template support to rest sensor --- homeassistant/components/sensor/rest.py | 74 +++++++++---------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index f50113350da..041a656a5ba 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -7,12 +7,12 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.rest/ """ from datetime import timedelta -from json import loads import logging - import requests +import jinja2.exceptions -from homeassistant.util import Throttle +from homeassistant.const import CONF_VALUE_TEMPLATE +from homeassistant.util import template, Throttle from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) @@ -59,57 +59,43 @@ def setup_platform(hass, config, add_devices, discovery_info=None): 'Please check the URL in the configuration file.') return False - try: - data = loads(response.text) - except ValueError: - _LOGGER.error('No valid JSON in the response in: %s', data) - return False - - try: - RestSensor.extract_value(data, config.get('variable')) - except KeyError: - _LOGGER.error('Variable "%s" not found in response: "%s"', - config.get('variable'), data) - return False + value_template = config.get(CONF_VALUE_TEMPLATE) + data = response.text + if value_template is not None: + try: + template.render_with_possible_json_value(hass, + value_template, + data) + except jinja2.exceptions.UndefinedError: + _LOGGER.error('Template "%s" not found in response: "%s"', + value_template, data) + return False if use_get: rest = RestDataGet(resource, verify_ssl) elif use_post: rest = RestDataPost(resource, payload, verify_ssl) - add_devices([RestSensor(rest, + add_devices([RestSensor(hass, + rest, config.get('name', DEFAULT_NAME), - config.get('variable'), config.get('unit_of_measurement'), - config.get('correction_factor', None), - config.get('decimal_places', None))]) + config.get(CONF_VALUE_TEMPLATE))]) # pylint: disable=too-many-arguments class RestSensor(Entity): """ Implements a REST sensor. """ - def __init__(self, rest, name, variable, unit_of_measurement, corr_factor, - decimal_places): + def __init__(self, hass, rest, name, unit_of_measurement, value_template): + self._hass = hass self.rest = rest self._name = name - self._variable = variable self._state = 'n/a' self._unit_of_measurement = unit_of_measurement - self._corr_factor = corr_factor - self._decimal_places = decimal_places + self._value_template = value_template self.update() - @classmethod - def extract_value(cls, data, variable): - """ Extracts the value using a key name or a path. """ - if isinstance(variable, list): - for variable_item in variable: - data = data[variable_item] - return data - else: - return data[variable] - @property def name(self): """ The name of the sensor. """ @@ -133,18 +119,10 @@ class RestSensor(Entity): if 'error' in value: self._state = value['error'] else: - try: - if value is not None: - value = RestSensor.extract_value(value, self._variable) - if self._corr_factor is not None: - value = float(value) * float(self._corr_factor) - if self._decimal_places is not None: - value = round(value, self._decimal_places) - if self._decimal_places == 0: - value = int(value) - self._state = value - except ValueError: - self._state = RestSensor.extract_value(value, self._variable) + if self._value_template is not None: + value = template.render_with_possible_json_value( + self._hass, self._value_template, value) + self._state = value # pylint: disable=too-few-public-methods @@ -164,7 +142,7 @@ class RestDataGet(object): verify=self._verify_ssl) if 'error' in self.data: del self.data['error'] - self.data = response.json() + self.data = response.text except requests.exceptions.ConnectionError: _LOGGER.error("No route to resource/endpoint.") self.data['error'] = 'N/A' @@ -188,7 +166,7 @@ class RestDataPost(object): timeout=10, verify=self._verify_ssl) if 'error' in self.data: del self.data['error'] - self.data = response.json() + self.data = response.text except requests.exceptions.ConnectionError: _LOGGER.error("No route to resource/endpoint.") self.data['error'] = 'N/A' From 0b325b2b7de2a6841d4548730ff812dc404121ac Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 11 Dec 2015 18:43:00 -0800 Subject: [PATCH 034/146] API.stream - catch more errors --- homeassistant/components/api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/api.py b/homeassistant/components/api.py index 6a66a2a110e..6d2f9e52a7a 100644 --- a/homeassistant/components/api.py +++ b/homeassistant/components/api.py @@ -126,7 +126,9 @@ def _handle_get_api_stream(handler, path_match, data): wfile.write(msg.encode("UTF-8")) wfile.flush() handler.server.sessions.extend_validation(session_id) - except IOError: + except (IOError, ValueError): + # IOError: socket errors + # ValueError: raised when 'I/O operation on closed file' block.set() def forward_events(event): From 5c63862054078224c01409fbb8b1f2df7de6ecb1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 11 Dec 2015 18:45:53 -0800 Subject: [PATCH 035/146] Fix template rounding --- homeassistant/util/template.py | 4 ++-- tests/util/test_template.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index 107532db776..bc89d053e60 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -66,8 +66,8 @@ class DomainStates(object): def forgiving_round(value, precision=0): """ Rounding method that accepts strings. """ try: - return int(float(value)) if precision == 0 else round(float(value), - precision) + value = round(float(value), precision) + return int(value) if precision == 0 else value except ValueError: # If value can't be converted to float return value diff --git a/tests/util/test_template.py b/tests/util/test_template.py index 5c1dfff1f85..bbb4de31626 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -57,10 +57,10 @@ class TestUtilTemplate(unittest.TestCase): '{{ states.sensor.temperature.state | round(1) }}')) def test_rounding_value2(self): - self.hass.states.set('sensor.temperature', 12.72) + self.hass.states.set('sensor.temperature', 12.78) self.assertEqual( - '127', + '128', template.render( self.hass, '{{ states.sensor.temperature.state | multiply(10) | round }}')) From b1bf6a609e4e187543ac72d592cb3ecdbabff532 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 11 Dec 2015 19:07:03 -0800 Subject: [PATCH 036/146] Catch exceptions when error rendering templates --- homeassistant/exceptions.py | 7 +++++++ homeassistant/util/template.py | 20 ++++++++++++++++---- tests/util/test_template.py | 6 +++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/homeassistant/exceptions.py b/homeassistant/exceptions.py index bd32d356670..510bc9b4e54 100644 --- a/homeassistant/exceptions.py +++ b/homeassistant/exceptions.py @@ -14,3 +14,10 @@ class InvalidEntityFormatError(HomeAssistantError): class NoEntitySpecifiedError(HomeAssistantError): """ When no entity is specified. """ pass + + +class TemplateError(HomeAssistantError): + """ Error during template rendering. """ + def __init__(self, exception): + super().__init__('{}: {}'.format(exception.__class__.__name__, + exception)) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index bc89d053e60..b7fc3197e08 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -6,7 +6,12 @@ Template utility methods for rendering strings with HA data. """ # pylint: disable=too-few-public-methods import json +import logging +import jinja2 from jinja2.sandbox import ImmutableSandboxedEnvironment +from homeassistant.exceptions import TemplateError + +_LOGGER = logging.getLogger(__name__) def render_with_possible_json_value(hass, template, value): @@ -20,7 +25,11 @@ def render_with_possible_json_value(hass, template, value): except ValueError: pass - return render(hass, template, variables) + try: + return render(hass, template, variables) + except TemplateError: + _LOGGER.exception('Error parsing value') + return value def render(hass, template, variables=None, **kwargs): @@ -28,9 +37,12 @@ def render(hass, template, variables=None, **kwargs): if variables is not None: kwargs.update(variables) - return ENV.from_string(template, { - 'states': AllStates(hass) - }).render(kwargs) + try: + return ENV.from_string(template, { + 'states': AllStates(hass) + }).render(kwargs) + except jinja2.TemplateError as err: + raise TemplateError(err) class AllStates(object): diff --git a/tests/util/test_template.py b/tests/util/test_template.py index bbb4de31626..16e1f8b6a04 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -7,7 +7,7 @@ Tests Home Assistant util methods. # pylint: disable=too-many-public-methods import unittest import homeassistant.core as ha - +from homeassistant.exceptions import TemplateError from homeassistant.util import template @@ -84,3 +84,7 @@ class TestUtilTemplate(unittest.TestCase): '', template.render_with_possible_json_value( self.hass, '{{ value_json }}', '{ I AM NOT JSON }')) + + def test_raise_exception_on_error(self): + with self.assertRaises(TemplateError): + template.render(self.hass, '{{ invalid_syntax') From 9eea7a6cde126dbf7c2f76d9708cb7cc93eb34df Mon Sep 17 00:00:00 2001 From: Richard Arends Date: Sat, 12 Dec 2015 16:25:56 +0100 Subject: [PATCH 037/146] Added support for MPD to start playing the current song/playlist --- homeassistant/components/media_player/mpd.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_player/mpd.py b/homeassistant/components/media_player/mpd.py index 8134ce5e743..b6c89cbfc3f 100644 --- a/homeassistant/components/media_player/mpd.py +++ b/homeassistant/components/media_player/mpd.py @@ -21,14 +21,14 @@ from homeassistant.const import ( from homeassistant.components.media_player import ( MediaPlayerDevice, SUPPORT_PAUSE, SUPPORT_VOLUME_SET, SUPPORT_TURN_OFF, - SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, + SUPPORT_TURN_ON, SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, MEDIA_TYPE_MUSIC) _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['python-mpd2==0.5.4'] SUPPORT_MPD = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_TURN_OFF | \ - SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK + SUPPORT_TURN_ON | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK # pylint: disable=unused-argument @@ -163,9 +163,13 @@ class MpdDevice(MediaPlayerDevice): return SUPPORT_MPD def turn_off(self): - """ Service to exit the running MPD. """ + """ Service to send the MPD the command to stop playing. """ self.client.stop() + def turn_on(self): + """ Service to send the MPD the command to start playing. """ + self.client.play() + def set_volume_level(self, volume): """ Sets volume """ self.client.setvol(int(volume * 100)) From 2b975c8620e0e420df30327d08b6d654ced1dbda Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 12 Dec 2015 10:35:15 -0800 Subject: [PATCH 038/146] Add flexible error value for value template parsing --- homeassistant/util/template.py | 6 ++++-- tests/util/test_template.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index b7fc3197e08..ad0fabdab53 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -12,9 +12,11 @@ from jinja2.sandbox import ImmutableSandboxedEnvironment from homeassistant.exceptions import TemplateError _LOGGER = logging.getLogger(__name__) +_SENTINEL = object() -def render_with_possible_json_value(hass, template, value): +def render_with_possible_json_value(hass, template, value, + error_value=_SENTINEL): """ Renders template with value exposed. If valid JSON will expose value_json too. """ variables = { @@ -29,7 +31,7 @@ def render_with_possible_json_value(hass, template, value): return render(hass, template, variables) except TemplateError: _LOGGER.exception('Error parsing value') - return value + return value if error_value is _SENTINEL else error_value def render(hass, template, variables=None, **kwargs): diff --git a/tests/util/test_template.py b/tests/util/test_template.py index 16e1f8b6a04..ba354f3e7be 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -85,6 +85,18 @@ class TestUtilTemplate(unittest.TestCase): template.render_with_possible_json_value( self.hass, '{{ value_json }}', '{ I AM NOT JSON }')) + def test_render_with_possible_json_value_with_template_error(self): + self.assertEqual( + 'hello', + template.render_with_possible_json_value( + self.hass, '{{ value_json', 'hello')) + + def test_render_with_possible_json_value_with_template_error_error_value(self): + self.assertEqual( + '-', + template.render_with_possible_json_value( + self.hass, '{{ value_json', 'hello', '-')) + def test_raise_exception_on_error(self): with self.assertRaises(TemplateError): template.render(self.hass, '{{ invalid_syntax') From a84ff14b00b69230d8e2ba9a115c8e621db4cc74 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Sat, 12 Dec 2015 13:34:21 -0700 Subject: [PATCH 039/146] Remove exception handling for templates It is now handled in the layers below --- homeassistant/components/sensor/rest.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index 041a656a5ba..f824f022966 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -9,7 +9,6 @@ https://home-assistant.io/components/sensor.rest/ from datetime import timedelta import logging import requests -import jinja2.exceptions from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.util import template, Throttle @@ -59,18 +58,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): 'Please check the URL in the configuration file.') return False - value_template = config.get(CONF_VALUE_TEMPLATE) - data = response.text - if value_template is not None: - try: - template.render_with_possible_json_value(hass, - value_template, - data) - except jinja2.exceptions.UndefinedError: - _LOGGER.error('Template "%s" not found in response: "%s"', - value_template, data) - return False - if use_get: rest = RestDataGet(resource, verify_ssl) elif use_post: @@ -121,7 +108,7 @@ class RestSensor(Entity): else: if self._value_template is not None: value = template.render_with_possible_json_value( - self._hass, self._value_template, value) + self._hass, self._value_template, value, 'N/A') self._state = value From 27e3e72211805fd44a3af2d255c10a75aa7bc60b Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Sat, 12 Dec 2015 14:19:00 -0700 Subject: [PATCH 040/146] Change description of rest sensor --- homeassistant/components/sensor/rest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index f824f022966..4dcd036df5e 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -1,7 +1,7 @@ """ homeassistant.components.sensor.rest ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The rest sensor will consume JSON responses sent by an exposed REST API. +The rest sensor will consume responses sent by an exposed REST API. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.rest/ From f45848477043d933119180e1229b841372b86240 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Dec 2015 11:11:35 +0100 Subject: [PATCH 041/146] Add sensor for Dweet.io --- homeassistant/components/sensor/dweet.py | 119 +++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 homeassistant/components/sensor/dweet.py diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py new file mode 100644 index 00000000000..346ecaf6457 --- /dev/null +++ b/homeassistant/components/sensor/dweet.py @@ -0,0 +1,119 @@ +""" +homeassistant.components.sensor.dweet +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Displays values from Dweet.io.. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.dweet/ +""" +from datetime import timedelta +import logging + +import homeassistant.util as util +from homeassistant.util import Throttle +from homeassistant.helpers.entity import Entity +from homeassistant.const import STATE_UNKNOWN + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'Dweet.io Sensor' +CONF_DEVICE = 'device' + +# Return cached results if last scan was less then this time ago +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + + +# pylint: disable=unused-variable +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Setup the Dweet sensor. """ + + import dweepy + + device = config.get('device') + + if device is None: + _LOGGER.error('Not all required config keys present: %s', + ', '.join(CONF_DEVICE)) + return False + + try: + dweepy.get_latest_dweet_for(device) + except dweepy.DweepyError: + _LOGGER.error("Device/thing '%s' could not be found", device) + return False + + dweet = DweetData(device) + + add_devices([DweetSensor(dweet, + config.get('name', DEFAULT_NAME), + config.get('variable'), + config.get('unit_of_measurement'), + config.get('correction_factor', None), + config.get('decimal_places', None))]) + + +class DweetSensor(Entity): + """ Implements a Dweet sensor. """ + + def __init__(self, dweet, name, variable, unit_of_measurement, corr_factor, + decimal_places): + self.dweet = dweet + self._name = name + self._variable = variable + self._state = STATE_UNKNOWN + self._unit_of_measurement = unit_of_measurement + self._corr_factor = corr_factor + self._decimal_places = decimal_places + self.update() + + @property + def name(self): + """ The name of the sensor. """ + return self._name + + @property + def unit_of_measurement(self): + """ Unit the value is expressed in. """ + return self._unit_of_measurement + + @property + def state(self): + """ Returns the state. """ + values = self.dweet.data + + if values is not None: + value = util.extract_value_json(values[0]['content'], + self._variable) + if self._corr_factor is not None: + value = float(value) * float(self._corr_factor) + if self._decimal_places is not None: + value = round(value, self._decimal_places) + if self._decimal_places == 0: + value = int(value) + return value + else: + return STATE_UNKNOWN + + def update(self): + """ Gets the latest data from REST API. """ + self.dweet.update() + + +# pylint: disable=too-few-public-methods +class DweetData(object): + """ Class for handling the data retrieval. """ + + def __init__(self, device): + self._device = device + self.data = dict() + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """ Gets the latest data from Dweet.io. """ + import dweepy + + try: + self.data = dweepy.get_latest_dweet_for(self._device) + except dweepy.DweepyError: + _LOGGER.error("Device '%s' could not be found", self._device) + self.data = None From 64e3db2444d6c3822deb98666920f14c206eed2f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Dec 2015 11:12:06 +0100 Subject: [PATCH 042/146] Add dweet sensor --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index 993f8c9533b..44093131cfd 100644 --- a/.coveragerc +++ b/.coveragerc @@ -84,6 +84,7 @@ omit = homeassistant/components/sensor/command_sensor.py homeassistant/components/sensor/cpuspeed.py homeassistant/components/sensor/dht.py + homeassistant/components/sensor/dweet.py homeassistant/components/sensor/efergy.py homeassistant/components/sensor/forecast.py homeassistant/components/sensor/glances.py From 4286e116f3d661bcc86c3c8041e216a5d35af733 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 10 Dec 2015 11:13:59 +0100 Subject: [PATCH 043/146] Add requirement --- homeassistant/components/sensor/dweet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py index 346ecaf6457..124036d298e 100644 --- a/homeassistant/components/sensor/dweet.py +++ b/homeassistant/components/sensor/dweet.py @@ -15,6 +15,7 @@ from homeassistant.helpers.entity import Entity from homeassistant.const import STATE_UNKNOWN _LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ['dweepy==0.2.0'] DEFAULT_NAME = 'Dweet.io Sensor' CONF_DEVICE = 'device' From 1d017beb934bf584780a29c71784dcb658a5c3fa Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 12 Dec 2015 21:56:47 +0100 Subject: [PATCH 044/146] Use templating --- homeassistant/components/sensor/dweet.py | 54 ++++++++++++------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py index 124036d298e..422012bec2c 100644 --- a/homeassistant/components/sensor/dweet.py +++ b/homeassistant/components/sensor/dweet.py @@ -1,18 +1,19 @@ """ homeassistant.components.sensor.dweet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Displays values from Dweet.io.. +Displays values from Dweet.io. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.dweet/ """ from datetime import timedelta import logging +import json -import homeassistant.util as util from homeassistant.util import Throttle +from homeassistant.util import template from homeassistant.helpers.entity import Entity -from homeassistant.const import STATE_UNKNOWN +from homeassistant.const import (STATE_UNKNOWN, CONF_VALUE_TEMPLATE) _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['dweepy==0.2.0'] @@ -24,47 +25,51 @@ CONF_DEVICE = 'device' MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) -# pylint: disable=unused-variable +# pylint: disable=unused-variable, too-many-function-args def setup_platform(hass, config, add_devices, discovery_info=None): """ Setup the Dweet sensor. """ - import dweepy device = config.get('device') + value_template = config.get(CONF_VALUE_TEMPLATE) - if device is None: + if None in (device, value_template): _LOGGER.error('Not all required config keys present: %s', - ', '.join(CONF_DEVICE)) + ', '.join(CONF_DEVICE, CONF_VALUE_TEMPLATE)) return False try: - dweepy.get_latest_dweet_for(device) + content = json.dumps(dweepy.get_latest_dweet_for(device)[0]['content']) except dweepy.DweepyError: _LOGGER.error("Device/thing '%s' could not be found", device) return False + if template.render_with_possible_json_value(hass, + value_template, + content) is '': + _LOGGER.error("'%s' was not found", value_template) + return False + dweet = DweetData(device) - add_devices([DweetSensor(dweet, + add_devices([DweetSensor(hass, + dweet, config.get('name', DEFAULT_NAME), - config.get('variable'), - config.get('unit_of_measurement'), - config.get('correction_factor', None), - config.get('decimal_places', None))]) + value_template, + config.get('unit_of_measurement'))]) +# pylint: disable=too-many-arguments class DweetSensor(Entity): """ Implements a Dweet sensor. """ - def __init__(self, dweet, name, variable, unit_of_measurement, corr_factor, - decimal_places): + def __init__(self, hass, dweet, name, value_template, unit_of_measurement): + self.hass = hass self.dweet = dweet self._name = name - self._variable = variable + self._value_template = value_template self._state = STATE_UNKNOWN self._unit_of_measurement = unit_of_measurement - self._corr_factor = corr_factor - self._decimal_places = decimal_places self.update() @property @@ -80,17 +85,10 @@ class DweetSensor(Entity): @property def state(self): """ Returns the state. """ - values = self.dweet.data - + values = json.dumps(self.dweet.data[0]['content']) if values is not None: - value = util.extract_value_json(values[0]['content'], - self._variable) - if self._corr_factor is not None: - value = float(value) * float(self._corr_factor) - if self._decimal_places is not None: - value = round(value, self._decimal_places) - if self._decimal_places == 0: - value = int(value) + value = template.render_with_possible_json_value( + self.hass, self._value_template, values) return value else: return STATE_UNKNOWN From 27c5c1cb9f59d40c339fb30037172f8d9079d03f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 12 Dec 2015 22:58:08 +0100 Subject: [PATCH 045/146] Add dweepy --- requirements_all.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements_all.txt b/requirements_all.txt index 5db0a85cee4..78234e8fb52 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -177,3 +177,6 @@ pydispatcher==2.0.5 # homeassistant.components.heatmiser heatmiserV3==0.9.1 + +# homeassistant.components.seansor.dweet +dweepy==0.2.0 From ed9b75756aa950296048a76d633b40922537ee58 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 13 Dec 2015 01:00:12 +0100 Subject: [PATCH 046/146] Catch error state --- homeassistant/components/sensor/dweet.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py index 422012bec2c..8aa55c847cf 100644 --- a/homeassistant/components/sensor/dweet.py +++ b/homeassistant/components/sensor/dweet.py @@ -85,13 +85,13 @@ class DweetSensor(Entity): @property def state(self): """ Returns the state. """ - values = json.dumps(self.dweet.data[0]['content']) - if values is not None: + if self.dweet.data is None: + return STATE_UNKNOWN + else: + values = json.dumps(self.dweet.data[0]['content']) value = template.render_with_possible_json_value( self.hass, self._value_template, values) return value - else: - return STATE_UNKNOWN def update(self): """ Gets the latest data from REST API. """ @@ -104,7 +104,7 @@ class DweetData(object): def __init__(self, device): self._device = device - self.data = dict() + self.data = None @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): From 649ce7befbade134db3c56b93eccc4ad9d02ab24 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 13 Dec 2015 01:00:34 +0100 Subject: [PATCH 047/146] Fix typo --- requirements_all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index 78234e8fb52..d26029d909f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -178,5 +178,5 @@ pydispatcher==2.0.5 # homeassistant.components.heatmiser heatmiserV3==0.9.1 -# homeassistant.components.seansor.dweet +# homeassistant.components.sensor.dweet dweepy==0.2.0 From 931f7e86152aef707fbd57ffdefe57ee39293151 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 12 Dec 2015 22:18:38 -0800 Subject: [PATCH 048/146] Simplify http component --- homeassistant/components/http.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/http.py b/homeassistant/components/http.py index 2b260b0e841..81e26aeae5a 100644 --- a/homeassistant/components/http.py +++ b/homeassistant/components/http.py @@ -178,12 +178,8 @@ class RequestHandler(SimpleHTTPRequestHandler): """ Does some common checks and calls appropriate method. """ url = urlparse(self.path) - # Read query input - data = parse_qs(url.query) - - # parse_qs gives a list for each value, take the latest element - for key in data: - data[key] = data[key][-1] + # Read query input. parse_qs gives a list for each value, we want last + data = {key: data[-1] for key, data in parse_qs(url.query).items()} # Did we get post input ? content_length = int(self.headers.get(HTTP_HEADER_CONTENT_LENGTH, 0)) From 360b99be59068a04504b8417d6877a782537cd6e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 12 Dec 2015 22:19:12 -0800 Subject: [PATCH 049/146] Add template is_state method --- homeassistant/util/template.py | 5 +++-- tests/util/test_template.py | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index ad0fabdab53..f8fa2c70f8b 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -41,8 +41,9 @@ def render(hass, template, variables=None, **kwargs): try: return ENV.from_string(template, { - 'states': AllStates(hass) - }).render(kwargs) + 'states': AllStates(hass), + 'is_state': hass.states.is_state + }).render(kwargs).strip() except jinja2.TemplateError as err: raise TemplateError(err) diff --git a/tests/util/test_template.py b/tests/util/test_template.py index ba354f3e7be..1e34d999fa7 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -100,3 +100,11 @@ class TestUtilTemplate(unittest.TestCase): def test_raise_exception_on_error(self): with self.assertRaises(TemplateError): template.render(self.hass, '{{ invalid_syntax') + + def test_is_state(self): + self.hass.states.set('test.object', 'available') + self.assertEqual( + 'yes', + template.render( + self.hass, + '{% if is_state("test.object", "available") %}yes{% else %}no{% endif %}')) From f73f824e0e5df55bb9b86c6771b26c0d262e1d95 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 12 Dec 2015 22:19:37 -0800 Subject: [PATCH 050/146] Make template states var callable --- homeassistant/util/template.py | 14 +++++++++++++- tests/util/test_template.py | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/homeassistant/util/template.py b/homeassistant/util/template.py index f8fa2c70f8b..d0a07507bdf 100644 --- a/homeassistant/util/template.py +++ b/homeassistant/util/template.py @@ -9,6 +9,7 @@ import json import logging import jinja2 from jinja2.sandbox import ImmutableSandboxedEnvironment +from homeassistant.const import STATE_UNKNOWN from homeassistant.exceptions import TemplateError _LOGGER = logging.getLogger(__name__) @@ -60,6 +61,10 @@ class AllStates(object): return iter(sorted(self._hass.states.all(), key=lambda state: state.entity_id)) + def __call__(self, entity_id): + state = self._hass.states.get(entity_id) + return STATE_UNKNOWN if state is None else state.state + class DomainStates(object): """ Class to expose a specific HA domain as attributes. """ @@ -96,6 +101,13 @@ def multiply(value, amount): # If value can't be converted to float return value -ENV = ImmutableSandboxedEnvironment() + +class TemplateEnvironment(ImmutableSandboxedEnvironment): + """ Home Assistant template environment. """ + + def is_safe_callable(self, obj): + return isinstance(obj, AllStates) or super().is_safe_callable(obj) + +ENV = TemplateEnvironment() ENV.filters['round'] = forgiving_round ENV.filters['multiply'] = multiply diff --git a/tests/util/test_template.py b/tests/util/test_template.py index 1e34d999fa7..1ecd7d5b894 100644 --- a/tests/util/test_template.py +++ b/tests/util/test_template.py @@ -101,6 +101,14 @@ class TestUtilTemplate(unittest.TestCase): with self.assertRaises(TemplateError): template.render(self.hass, '{{ invalid_syntax') + def test_if_state_exists(self): + self.hass.states.set('test.object', 'available') + self.assertEqual( + 'exists', + template.render( + self.hass, + '{% if states.test.object %}exists{% else %}not exists{% endif %}')) + def test_is_state(self): self.hass.states.set('test.object', 'available') self.assertEqual( @@ -108,3 +116,12 @@ class TestUtilTemplate(unittest.TestCase): template.render( self.hass, '{% if is_state("test.object", "available") %}yes{% else %}no{% endif %}')) + + def test_states_function(self): + self.hass.states.set('test.object', 'available') + self.assertEqual( + 'available', + template.render(self.hass, '{{ states("test.object") }}')) + self.assertEqual( + 'unknown', + template.render(self.hass, '{{ states("test.object2") }}')) From 729c24d59bada00f0f35a3ae7273a8044a7bb796 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 12 Dec 2015 22:29:02 -0800 Subject: [PATCH 051/146] Add Alexa component --- homeassistant/components/alexa.py | 186 ++++++++++++++++++++++++ tests/components/test_alexa.py | 225 ++++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 homeassistant/components/alexa.py create mode 100644 tests/components/test_alexa.py diff --git a/homeassistant/components/alexa.py b/homeassistant/components/alexa.py new file mode 100644 index 00000000000..c261cfd3f6a --- /dev/null +++ b/homeassistant/components/alexa.py @@ -0,0 +1,186 @@ +""" +components.alexa +~~~~~~~~~~~~~~~~ +Component to offer a service end point for an Alexa skill. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/alexa/ +""" +import enum +import logging + +from homeassistant.const import HTTP_OK, HTTP_UNPROCESSABLE_ENTITY +from homeassistant.util import template + +DOMAIN = 'alexa' +DEPENDENCIES = ['http'] + +_LOGGER = logging.getLogger(__name__) +_CONFIG = {} + +API_ENDPOINT = '/api/alexa' + +CONF_INTENTS = 'intents' +CONF_CARD = 'card' +CONF_SPEECH = 'speech' + + +def setup(hass, config): + """ Activate Alexa component. """ + _CONFIG.update(config[DOMAIN].get(CONF_INTENTS, {})) + + hass.http.register_path('POST', API_ENDPOINT, _handle_alexa, True) + + return True + + +def _handle_alexa(handler, path_match, data): + """ Handle Alexa. """ + _LOGGER.debug('Received Alexa request: %s', data) + + req = data.get('request') + + if req is None: + _LOGGER.error('Received invalid data from Alexa: %s', data) + handler.write_json_message( + "Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY) + return + + req_type = req['type'] + + if req_type == 'SessionEndedRequest': + handler.send_response(HTTP_OK) + handler.end_headers() + return + + intent = req.get('intent') + response = AlexaResponse(handler.server.hass, intent) + + if req_type == 'LaunchRequest': + response.add_speech( + SpeechType.plaintext, + "Hello, and welcome to the future. How may I help?") + handler.write_json(response.as_dict()) + return + + if req_type != 'IntentRequest': + _LOGGER.warning('Received unsupported request: %s', req_type) + return + + intent_name = intent['name'] + config = _CONFIG.get(intent_name) + + if config is None: + _LOGGER.warning('Received unknown intent %s', intent_name) + response.add_speech( + SpeechType.plaintext, + "This intent is not yet configured within Home Assistant.") + handler.write_json(response.as_dict()) + return + + speech = config.get(CONF_SPEECH) + card = config.get(CONF_CARD) + + # pylint: disable=unsubscriptable-object + if speech is not None: + response.add_speech(SpeechType[speech['type']], speech['text']) + + if card is not None: + response.add_card(CardType[card['type']], card['title'], + card['content']) + + handler.write_json(response.as_dict()) + + +class SpeechType(enum.Enum): + """ Alexa speech types. """ + plaintext = "PlainText" + ssml = "SSML" + + +class CardType(enum.Enum): + """ Alexa card types. """ + simple = "Simple" + link_account = "LinkAccount" + + +class AlexaResponse(object): + """ Helps generating the response for Alexa. """ + + def __init__(self, hass, intent=None): + self.hass = hass + self.speech = None + self.card = None + self.reprompt = None + self.session_attributes = {} + self.should_end_session = True + if intent is not None and 'slots' in intent: + self.variables = {key: value['value'] for key, value + in intent['slots'].items()} + else: + self.variables = {} + + def add_card(self, card_type, title, content): + """ Add a card to the response. """ + assert self.card is None + + card = { + "type": card_type.value + } + + if card_type == CardType.link_account: + self.card = card + return + + card["title"] = self._render(title), + card["content"] = self._render(content) + self.card = card + + def add_speech(self, speech_type, text): + """ Add speech to the response. """ + assert self.speech is None + + key = 'ssml' if speech_type == SpeechType.ssml else 'text' + + self.speech = { + 'type': speech_type.value, + key: self._render(text) + } + + def add_reprompt(self, speech_type, text): + """ Add repromopt if user does not answer. """ + assert self.reprompt is None + + key = 'ssml' if speech_type == SpeechType.ssml else 'text' + + self.reprompt = { + 'type': speech_type.value, + key: self._render(text) + } + + def as_dict(self): + """ Returns response in an Alexa valid dict. """ + response = { + 'shouldEndSession': self.should_end_session + } + + if self.card is not None: + response['card'] = self.card + + if self.speech is not None: + response['outputSpeech'] = self.speech + + if self.reprompt is not None: + response['reprompt'] = { + 'outputSpeech': self.reprompt + } + + return { + 'version': '1.0', + 'sessionAttributes': self.session_attributes, + 'response': response, + } + + def _render(self, template_string): + """ Render a response, adding data from intent if available. """ + return template.render(self.hass, template_string, self.variables) diff --git a/tests/components/test_alexa.py b/tests/components/test_alexa.py new file mode 100644 index 00000000000..75aec2b087c --- /dev/null +++ b/tests/components/test_alexa.py @@ -0,0 +1,225 @@ +""" +tests.test_component_alexa +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tests Home Assistant Alexa component does what it should do. +""" +# pylint: disable=protected-access,too-many-public-methods +import unittest +import json +from unittest.mock import patch + +import requests + +from homeassistant import bootstrap, const +import homeassistant.core as ha +from homeassistant.components import alexa, http + +API_PASSWORD = "test1234" + +# Somehow the socket that holds the default port does not get released +# when we close down HA in a different test case. Until I have figured +# out what is going on, let's run this test on a different port. +SERVER_PORT = 8119 + +API_URL = "http://127.0.0.1:{}{}".format(SERVER_PORT, alexa.API_ENDPOINT) + +HA_HEADERS = {const.HTTP_HEADER_HA_AUTH: API_PASSWORD} + +hass = None + + +@patch('homeassistant.components.http.util.get_local_ip', + return_value='127.0.0.1') +def setUpModule(mock_get_local_ip): # pylint: disable=invalid-name + """ Initalizes a Home Assistant server. """ + global hass + + hass = ha.HomeAssistant() + + bootstrap.setup_component( + hass, http.DOMAIN, + {http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD, + http.CONF_SERVER_PORT: SERVER_PORT}}) + + bootstrap.setup_component(hass, alexa.DOMAIN, { + 'alexa': { + 'intents': { + 'WhereAreWeIntent': { + 'speech': { + 'type': 'plaintext', + 'text': + """ + {%- if is_state('device_tracker.paulus', 'home') and is_state('device_tracker.anne_therese', 'home') -%} + You are both home, you silly + {%- else -%} + Anne Therese is at {{ states("device_tracker.anne_therese") }} and Paulus is at {{ states("device_tracker.paulus") }} + {% endif %} + """, + } + }, + 'GetZodiacHoroscopeIntent': { + 'speech': { + 'type': 'plaintext', + 'text': 'You told us your sign is {{ ZodiacSign }}.' + } + } + } + } + }) + + hass.start() + + +def tearDownModule(): # pylint: disable=invalid-name + """ Stops the Home Assistant server. """ + hass.stop() + + +def _req(data={}): + return requests.post(API_URL, data=json.dumps(data), timeout=5, + headers=HA_HEADERS) + + +class TestAlexa(unittest.TestCase): + """ Test Alexa. """ + + def test_launch_request(self): + data = { + 'version': '1.0', + 'session': { + 'new': True, + 'sessionId': 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000', + 'application': { + 'applicationId': 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe' + }, + 'attributes': {}, + 'user': { + 'userId': 'amzn1.account.AM3B00000000000000000000000' + } + }, + 'request': { + 'type': 'LaunchRequest', + 'requestId': 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000', + 'timestamp': '2015-05-13T12:34:56Z' + } + } + req = _req(data) + self.assertEqual(200, req.status_code) + resp = req.json() + self.assertIn('outputSpeech', resp['response']) + + def test_intent_request_with_slots(self): + data = { + 'version': '1.0', + 'session': { + 'new': False, + 'sessionId': 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000', + 'application': { + 'applicationId': 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe' + }, + 'attributes': { + 'supportedHoroscopePeriods': { + 'daily': True, + 'weekly': False, + 'monthly': False + } + }, + 'user': { + 'userId': 'amzn1.account.AM3B00000000000000000000000' + } + }, + 'request': { + 'type': 'IntentRequest', + 'requestId': ' amzn1.echo-api.request.0000000-0000-0000-0000-00000000000', + 'timestamp': '2015-05-13T12:34:56Z', + 'intent': { + 'name': 'GetZodiacHoroscopeIntent', + 'slots': { + 'ZodiacSign': { + 'name': 'ZodiacSign', + 'value': 'virgo' + } + } + } + } + } + req = _req(data) + self.assertEqual(200, req.status_code) + text = req.json().get('response', {}).get('outputSpeech', {}).get('text') + self.assertEqual('You told us your sign is virgo.', text) + + def test_intent_request_without_slots(self): + data = { + 'version': '1.0', + 'session': { + 'new': False, + 'sessionId': 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000', + 'application': { + 'applicationId': 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe' + }, + 'attributes': { + 'supportedHoroscopePeriods': { + 'daily': True, + 'weekly': False, + 'monthly': False + } + }, + 'user': { + 'userId': 'amzn1.account.AM3B00000000000000000000000' + } + }, + 'request': { + 'type': 'IntentRequest', + 'requestId': ' amzn1.echo-api.request.0000000-0000-0000-0000-00000000000', + 'timestamp': '2015-05-13T12:34:56Z', + 'intent': { + 'name': 'WhereAreWeIntent', + } + } + } + req = _req(data) + self.assertEqual(200, req.status_code) + text = req.json().get('response', {}).get('outputSpeech', {}).get('text') + + self.assertEqual('Anne Therese is at unknown and Paulus is at unknown', text) + + hass.states.set('device_tracker.paulus', 'home') + hass.states.set('device_tracker.anne_therese', 'home') + + req = _req(data) + self.assertEqual(200, req.status_code) + text = req.json().get('response', {}).get('outputSpeech', {}).get('text') + self.assertEqual('You are both home, you silly', text) + + def test_session_ended_request(self): + data = { + 'version': '1.0', + 'session': { + 'new': False, + 'sessionId': 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000', + 'application': { + 'applicationId': 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe' + }, + 'attributes': { + 'supportedHoroscopePeriods': { + 'daily': True, + 'weekly': False, + 'monthly': False + } + }, + 'user': { + 'userId': 'amzn1.account.AM3B00000000000000000000000' + } + }, + 'request': { + 'type': 'SessionEndedRequest', + 'requestId': 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000', + 'timestamp': '2015-05-13T12:34:56Z', + 'reason': 'USER_INITIATED' + } + } + + req = _req(data) + self.assertEqual(200, req.status_code) + self.assertEqual('', req.text) From 46f742f82f6d0fda347e2ffade32b4b49d30879c Mon Sep 17 00:00:00 2001 From: Richard Arends Date: Sun, 13 Dec 2015 18:42:53 +0100 Subject: [PATCH 052/146] Added support for MPD to display the name before the title if it is available When using a radio stream, the name of the station is often available in currentsong['name']. Just like the 'mpc' CLI client, this change displays the name of the station before the current song title. For example: "Mick Jagger - Let's Work" becomes "Radio 10: Mick Jagger - Let's Work" --- homeassistant/components/media_player/mpd.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/media_player/mpd.py b/homeassistant/components/media_player/mpd.py index b6c89cbfc3f..e1cdadd9ae2 100644 --- a/homeassistant/components/media_player/mpd.py +++ b/homeassistant/components/media_player/mpd.py @@ -141,7 +141,15 @@ class MpdDevice(MediaPlayerDevice): @property def media_title(self): """ Title of current playing media. """ - return self.currentsong['title'] + name = self.currentsong['name'] + title = self.currentsong['title'] + + if name: + separator = ': ' + nameandtitle = (name, title) + return separator.join(nameandtitle) + else: + return title @property def media_artist(self): From 85b62a20c8e7326d4110a22078fa61af8083ed8e Mon Sep 17 00:00:00 2001 From: Richard Arends Date: Sun, 13 Dec 2015 19:46:17 +0100 Subject: [PATCH 053/146] Use format instead of str.join to join name and title --- homeassistant/components/media_player/mpd.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/media_player/mpd.py b/homeassistant/components/media_player/mpd.py index e1cdadd9ae2..f84013fd573 100644 --- a/homeassistant/components/media_player/mpd.py +++ b/homeassistant/components/media_player/mpd.py @@ -145,9 +145,7 @@ class MpdDevice(MediaPlayerDevice): title = self.currentsong['title'] if name: - separator = ': ' - nameandtitle = (name, title) - return separator.join(nameandtitle) + return '{}: {}'.format(name, title) else: return title From 035d518cb686d314f586ed6a2acc94e3b59183fe Mon Sep 17 00:00:00 2001 From: Richard Arends Date: Sun, 13 Dec 2015 19:54:10 +0100 Subject: [PATCH 054/146] Expect the case where currentsong['name'] can be absent. Use the .get funtion with a default value set to None --- homeassistant/components/media_player/mpd.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/media_player/mpd.py b/homeassistant/components/media_player/mpd.py index f84013fd573..a61dac88150 100644 --- a/homeassistant/components/media_player/mpd.py +++ b/homeassistant/components/media_player/mpd.py @@ -141,13 +141,13 @@ class MpdDevice(MediaPlayerDevice): @property def media_title(self): """ Title of current playing media. """ - name = self.currentsong['name'] + name = self.currentsong.get('name', None) title = self.currentsong['title'] - if name: - return '{}: {}'.format(name, title) - else: + if name is None: return title + else: + return '{}: {}'.format(name, title) @property def media_artist(self): From b3171c7cde16c08a0d7da7f3c4c869211cfc2022 Mon Sep 17 00:00:00 2001 From: caius Date: Wed, 9 Dec 2015 20:12:23 +0100 Subject: [PATCH 055/146] Add fritzconnection library to requirements --- requirements_all.txt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/requirements_all.txt b/requirements_all.txt index d26029d909f..0712569561a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -83,9 +83,6 @@ https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b6 # homeassistant.components.mqtt paho-mqtt==1.1 -# homeassistant.components.mqtt -jsonpath-rw==1.4.0 - # homeassistant.components.notify.pushbullet pushbullet.py==0.9.0 @@ -119,6 +116,9 @@ py-cpuinfo==0.1.6 # homeassistant.components.sensor.dht # http://github.com/mala-zaba/Adafruit_Python_DHT/archive/4101340de8d2457dd194bca1e8d11cbfc237e919.zip#Adafruit_DHT==1.1.0 +# homeassistant.components.sensor.dweet +dweepy==0.2.0 + # homeassistant.components.sensor.forecast python-forecastio==1.3.3 @@ -160,6 +160,9 @@ orvibo==1.0.1 # homeassistant.components.switch.wemo pywemo==0.3.3 +# homeassistant.components.thermostat.heatmiser +heatmiserV3==0.9.1 + # homeassistant.components.thermostat.honeywell evohomeclient==0.2.4 @@ -174,9 +177,3 @@ https://github.com/persandstrom/python-verisure/archive/9873c4527f01b1ba1f72ae60 # homeassistant.components.zwave pydispatcher==2.0.5 - -# homeassistant.components.heatmiser -heatmiserV3==0.9.1 - -# homeassistant.components.sensor.dweet -dweepy==0.2.0 From 9833b4b66337f6116147ed9b11f60ca8db2b7b04 Mon Sep 17 00:00:00 2001 From: caius Date: Wed, 9 Dec 2015 20:22:40 +0100 Subject: [PATCH 056/146] Add the fritz device tracker to track established connections to FritzBox routers --- .../components/device_tracker/fritz.py | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 homeassistant/components/device_tracker/fritz.py diff --git a/homeassistant/components/device_tracker/fritz.py b/homeassistant/components/device_tracker/fritz.py new file mode 100644 index 00000000000..99c405d479f --- /dev/null +++ b/homeassistant/components/device_tracker/fritz.py @@ -0,0 +1,165 @@ +""" +homeassistant.components.device_tracker.fritz +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Unfortunately, you have to execute the following command by hand: +sudo apt-get install libxslt-dev libxml2-dev + +Device tracker platform that supports scanning a FitzBox router for device +presence. + +Configuration: + +To use the fritz tracker you have to adapt your configuration.yaml by +using the following template: + +device_tracker: + platform: fritz + host: YOUR_ROUTER_IP + username: YOUR_ADMIN_USERNAME + password: YOUR_ADMIN_PASSWORD + + +Description: + +host +*Optional +The IP address of your router, e.g. 192.168.0.1. +It is optional since every fritzbox is also reachable by using +the 169.254.1.1 IP. + +username +*Optional +The username of an user with administrative privileges, usually 'admin'. +However, it seems that it is not necessary to use it in +current generation fritzbox routers because the necessary data +can be retrieved anonymously. + +password +*Optional +The password for your given admin account. +However, it seems that it is not necessary to use it in current +generation fritzbox routers because the necessary data can +be retrieved anonymously. +""" + +import logging +from datetime import timedelta + +from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD +from homeassistant.helpers import validate_config +from homeassistant.util import Throttle +from homeassistant.components.device_tracker import DOMAIN + +# Return cached results if last scan was less then this time ago +MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) + +_LOGGER = logging.getLogger(__name__) + + +# noinspection PyUnusedLocal +def get_scanner(hass, config): + """ + Validates config and returns FritzBoxScanner + @param hass: + @param config: + @return: + """ + if not validate_config(config, + {DOMAIN: []}, + _LOGGER): + return None + scanner = FritzBoxScanner(config[DOMAIN]) + return scanner if scanner.success_init else None + + +# pylint: disable=too-many-instance-attributes +class FritzBoxScanner(object): + """ + This class queries a FritzBox router. It is using the + fritzconnection library for communication with the router. + + The API description can be found under: + https://pypi.python.org/pypi/fritzconnection/0.4.6 + + This scanner retrieves the list of known hosts and checks + their corresponding states (on, or off). + + Due to a bug of the fritzbox api (router side) it is not possible + to track more than 16 hosts. + """ + def __init__(self, config): + self.last_results = [] + self.host = '169.254.1.1' # This IP is valid for all fritzboxes + self.username = 'admin' + self.password = '' + self.success_init = True + + # Try to import the fritzconnection library + try: + # noinspection PyPackageRequirements,PyUnresolvedReferences + import fritzconnection as fc + except ImportError: + _LOGGER.exception("""Failed to import Python library + fritzconnection. Please run + /setup to install it.""") + self.success_init = False + return + + # Check for user specific configuration + if CONF_HOST in config.keys(): + self.host = config[CONF_HOST] + if CONF_USERNAME in config.keys(): + self.username = config[CONF_USERNAME] + if CONF_PASSWORD in config.keys(): + self.password = config[CONF_PASSWORD] + + # Establish a connection to the fritzbox + # noinspection PyBroadException + try: + self.fritz_box = fc.FritzHosts(address=self.host, + user=self.username, + password=self.password) + except Exception: + self.fritz_box = None + + # At this point it is difficult to tell if a connection is established. + # So just check for null objects ... + if self.fritz_box is None or not self.fritz_box.modelname: + self.success_init = False + + if self.success_init: + _LOGGER.info("Successfully connected to {0}" + .format(self.fritz_box.modelname)) + self._update_info() + else: + _LOGGER.error("Failed to establish connection to FritzBox " + "with IP: {0}".format(self.host)) + + def scan_devices(self): + """ Scan for new devices and return a list of found device ids. """ + self._update_info() + active_hosts = [] + for known_host in self.last_results: + if known_host["status"] == "1": + active_hosts.append(known_host["mac"]) + return active_hosts + + def get_device_name(self, mac): + """ Returns the name of the given device or None if is not known. """ + ret = self.fritz_box.get_specific_host_entry(mac)["NewHostName"] + if ret == {}: + return None + return ret + + @Throttle(MIN_TIME_BETWEEN_SCANS) + def _update_info(self): + """ + Retrieves latest information from the FritzBox. + Returns boolean if scanning successful. + """ + if not self.success_init: + return False + + _LOGGER.info("Scanning") + self.last_results = self.fritz_box.get_hosts_info() + return True From cc962c6bb2f582636543138352eebe0b36be4048 Mon Sep 17 00:00:00 2001 From: caius Date: Wed, 9 Dec 2015 20:31:40 +0100 Subject: [PATCH 057/146] Add some lint suggested modifications --- homeassistant/components/device_tracker/fritz.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/device_tracker/fritz.py b/homeassistant/components/device_tracker/fritz.py index 99c405d479f..df439a4fb24 100644 --- a/homeassistant/components/device_tracker/fritz.py +++ b/homeassistant/components/device_tracker/fritz.py @@ -114,12 +114,11 @@ class FritzBoxScanner(object): self.password = config[CONF_PASSWORD] # Establish a connection to the fritzbox - # noinspection PyBroadException try: self.fritz_box = fc.FritzHosts(address=self.host, user=self.username, password=self.password) - except Exception: + except (ValueError, TypeError): self.fritz_box = None # At this point it is difficult to tell if a connection is established. @@ -128,12 +127,12 @@ class FritzBoxScanner(object): self.success_init = False if self.success_init: - _LOGGER.info("Successfully connected to {0}" - .format(self.fritz_box.modelname)) + _LOGGER.info("Successfully connected to %s", + self.fritz_box.modelname) self._update_info() else: _LOGGER.error("Failed to establish connection to FritzBox " - "with IP: {0}".format(self.host)) + "with IP: %s", self.host) def scan_devices(self): """ Scan for new devices and return a list of found device ids. """ From 0f777ecd4c665733e1c646841f1bad4bcf954e93 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 13 Dec 2015 13:21:38 -0800 Subject: [PATCH 058/146] Update coveragerc --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index 44093131cfd..7192883b655 100644 --- a/.coveragerc +++ b/.coveragerc @@ -39,6 +39,7 @@ omit = homeassistant/components/device_tracker/aruba.py homeassistant/components/device_tracker/asuswrt.py homeassistant/components/device_tracker/ddwrt.py + homeassistant/components/device_tracker/fritz.py homeassistant/components/device_tracker/geofancy.py homeassistant/components/device_tracker/luci.py homeassistant/components/device_tracker/ubus.py From f93d6a1a1159016f4de8f2a8b3eeaabfcaf7e37c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 13 Dec 2015 13:40:42 -0800 Subject: [PATCH 059/146] Fix local dir config path --- homeassistant/components/frontend/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index fc955e30d44..3de4fdc99f8 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -109,8 +109,6 @@ def _handle_get_local(handler, path_match, data): """ req_file = util.sanitize_path(path_match.group('file')) - path = os.path.join(get_default_config_dir(), 'www', req_file) - if not os.path.isfile(path): - return False + path = handler.server.hass.config.path('www', req_file) handler.write_file(path) From 3faa1a4393c188855e9179f1e693b2783f3e83d3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 13 Dec 2015 13:47:05 -0800 Subject: [PATCH 060/146] Fix lint issues --- homeassistant/components/frontend/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 3de4fdc99f8..37e9b39079e 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -11,7 +11,6 @@ import logging from . import version, mdi_version import homeassistant.util as util from homeassistant.const import URL_ROOT, HTTP_OK -from homeassistant.config import get_default_config_dir DOMAIN = 'frontend' DEPENDENCIES = ['api'] From 90f0632a6986f851c069cab969744cf4b7368d21 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 13 Dec 2015 23:54:15 -0800 Subject: [PATCH 061/146] Install bower dependencies on frontend bootstrap --- script/bootstrap_frontend | 1 + 1 file changed, 1 insertion(+) diff --git a/script/bootstrap_frontend b/script/bootstrap_frontend index 6fc94f95725..5bc3baf38c9 100755 --- a/script/bootstrap_frontend +++ b/script/bootstrap_frontend @@ -1,5 +1,6 @@ echo "Bootstrapping frontend..." cd homeassistant/components/frontend/www_static/home-assistant-polymer npm install +bower install npm run setup_js_dev cd ../../../../.. From df24a1bfa7afb3a7c1595694e056d145637102e5 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 13 Dec 2015 23:59:40 -0800 Subject: [PATCH 062/146] Update frontend (babel 6) --- homeassistant/components/frontend/version.py | 2 +- .../frontend/www_static/frontend.html | 17 ++++++++--------- .../frontend/www_static/home-assistant-polymer | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 83383baf11d..13335959c9f 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,2 +1,2 @@ """ DO NOT MODIFY. Auto-generated by build_frontend script """ -VERSION = "aac488c33cd4291cd0924e60a55bd309" +VERSION = "026761064bba4614a0441b7b4fc4eeea" diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 907722b09ee..dc839ee6f9f 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -6080,12 +6080,11 @@ case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return font-weight: 300; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; - } \ No newline at end of file + } \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index e51b8add369..eff286e7425 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit e51b8add369f9e81d22b25b4be2400675361afdb +Subproject commit eff286e7425f53750048a68506767c5bc2f3a985 From 3ed69cec68dfcc2e9b2e6fdd1f968e629212be16 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 14 Dec 2015 10:13:51 -0500 Subject: [PATCH 063/146] Add Egg Minder support --- .../components/sensor/wink-eggminder.py | 64 +++++++++++++++++++ homeassistant/components/wink.py | 8 +-- 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100755 homeassistant/components/sensor/wink-eggminder.py diff --git a/homeassistant/components/sensor/wink-eggminder.py b/homeassistant/components/sensor/wink-eggminder.py new file mode 100755 index 00000000000..9398d11d177 --- /dev/null +++ b/homeassistant/components/sensor/wink-eggminder.py @@ -0,0 +1,64 @@ +""" +homeassistant.components.egg_minder.wink +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Support for Wink Egg Minder. +For more details about this platform, please refer to the documentation at +at https://home-assistant.io/components/sensor.wink/ +""" +import logging + +from homeassistant.helpers.entity import Entity +from homeassistant.const import CONF_ACCESS_TOKEN + +REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' + '42fdcfa721b1bc583688e3592d8427f4c13ba6d9.zip' + '#python-wink==0.2'] + +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the Wink platform. """ + import pywink + + if discovery_info is None: + token = config.get('access_token') + + if token is None: + logging.getLogger(__name__).error( + "Missing wink access_token. " + "Get one at https://winkbearertoken.appspot.com/") + return + + pywink.set_bearer_token(token) + + add_devices(WinkEggMinder(eggtray) for eggtray in pywink.get_eggtrays()) + + +class WinkEggMinder(Entity): + """ Represents a Wink sensor. """ + + def __init__(self, wink): + self.wink = wink + + @property + def state(self): + """ Returns the state. """ + return self.egg_count + + @property + def unique_id(self): + """ Returns the id of this wink sensor """ + return "{}.{}".format(self.__class__, self.wink.deviceId()) + + @property + def name(self): + """ Returns the name of the sensor if any. """ + return self.wink.name() + + @property + def update(self): + """ Update state of the Egg Minder. """ + self.wink.updateState() + + @property + def egg_count(self): + """ The number of eggs """ + return self.wink.state() diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 1ab82236596..2ea93cce3a7 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -17,14 +17,14 @@ from homeassistant.const import ( ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME) DOMAIN = "wink" +DEPENDENCIES = [] REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' - '42fdcfa721b1bc583688e3592d8427f4c13ba6d9.zip' - '#python-wink==0.2'] + '9eb39eaba0717922815e673ad1114c685839d890.zip' + '#python-wink==0.1.1'] DISCOVER_LIGHTS = "wink.lights" DISCOVER_SWITCHES = "wink.switches" DISCOVER_SENSORS = "wink.sensors" -DISCOVER_LOCKS = "wink.locks" def setup(hass, config): @@ -42,7 +42,7 @@ def setup(hass, config): ('light', pywink.get_bulbs, DISCOVER_LIGHTS), ('switch', pywink.get_switches, DISCOVER_SWITCHES), ('sensor', pywink.get_sensors, DISCOVER_SENSORS), - ('lock', pywink.get_locks, DISCOVER_LOCKS)): + ('sensor', pywink.get_eggtrays, DISCOVER_SENSORS)): if func_exists(): component = get_component(component_name) From 5755c6f593c2f74cf2c7898a1aff3db8ef62bb15 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 14 Dec 2015 10:45:03 -0500 Subject: [PATCH 064/146] Fixed get method name --- files.txt | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 files.txt diff --git a/files.txt b/files.txt new file mode 100644 index 00000000000..24cdbbd9cf5 --- /dev/null +++ b/files.txt @@ -0,0 +1,459 @@ +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/dependency_links.txt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/top_level.txt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/SOURCES.txt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/requires.txt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/not-zip-safe +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/PKG-INFO +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/entry_points.txt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__main__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/config.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/exceptions.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/bootstrap.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/remote.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/loader.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/core.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/const.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/startup/launchd.plist +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/history.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/arduino.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/wink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rfxtrx.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/updater.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/isy994.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/keyboard.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/discovery.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/zone.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/logger.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/http.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/shell_command.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/scene.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/conversation.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/simple_alarm.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/introduction.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/recorder.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/script.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/ecobee.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/logbook.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_sun_light_trigger.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/browser.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/configurator.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sun.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/api.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/zwave.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/influxdb.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/ifttt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/downloader.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/verisure.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/group.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/modbus.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/manual.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/verisure.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/manual.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/verisure.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/version.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/index.html.template +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/mdi_version.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-384x384.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/webcomponents-lite.min.js +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/service_worker.js +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-192x192.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-apple-180x180.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/frontend.html +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/manifest.json +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/mdi.html +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon.ico +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_philips_hue.jpg +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_plex_mediaserver.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_ecobee_thermostat.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-icon.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-icon-2x.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/layers-2x.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/layers.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-shadow.png +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/mdi_version.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/version.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/vera.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/arduino.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/wink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rpi_gpio.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rfxtrx.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/isy994.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/wemo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/command_switch.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/mystrom.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/arest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/edimax.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/transmission.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/zwave.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/orvibo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/tellstick.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/hikvisioncam.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/verisure.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/modbus.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/transmission.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/hikvisioncam.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/orvibo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/modbus.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/arduino.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/command_switch.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/zwave.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/isy994.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/tellstick.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/arest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/wemo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/wink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rpi_gpio.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/vera.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/edimax.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/verisure.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rfxtrx.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/mystrom.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/plex.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/squeezebox.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/kodi.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/mpd.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/firetv.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/itunes.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/denon.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/sonos.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/cast.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/squeezebox.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/cast.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/mpd.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/sonos.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/itunes.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/plex.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/kodi.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/denon.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/firetv.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/arest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/arest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/ubus.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/netgear.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/asuswrt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/tplink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/luci.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/actiontec.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/nmap_tracker.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/aruba.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/tomato.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/owntracks.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/thomson.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/snmp.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/geofancy.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/ddwrt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/tomato.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/ddwrt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/tplink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/geofancy.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/thomson.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/owntracks.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/ubus.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/luci.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/netgear.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/asuswrt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/aruba.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/nmap_tracker.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/snmp.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/actiontec.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/wink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/wink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/glances.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/vera.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/worldclock.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/arduino.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/wink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/sabnzbd.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rpi_gpio.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rfxtrx.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/forecast.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/isy994.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/arest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/systemmonitor.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/efergy.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/bitcoin.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/dht.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/temper.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/ecobee.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/transmission.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/cpuspeed.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/wink-eggminder.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/zwave.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/command_sensor.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/mysensors.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/openweathermap.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/swiss_public_transport.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/tellstick.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/time_date.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/verisure.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/modbus.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/transmission.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/worldclock.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/forecast.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/bitcoin.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/systemmonitor.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/glances.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/modbus.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/ecobee.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/arduino.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/zwave.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/isy994.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/swiss_public_transport.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/cpuspeed.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/tellstick.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/wink-eggminder.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/sabnzbd.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/arest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/command_sensor.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/dht.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/temper.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/wink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rpi_gpio.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/time_date.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/vera.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/verisure.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/efergy.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rfxtrx.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/mysensors.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/openweathermap.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/radiotherm.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/nest.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/heat_control.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/homematic.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/ecobee.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/honeywell.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/heatmiser.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/heat_control.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/ecobee.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/nest.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/homematic.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/honeywell.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/radiotherm.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/heatmiser.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/vera.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/wink.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/rfxtrx.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/isy994.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/hyperion.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/light_profiles.csv +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/blinksticklight.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/limitlessled.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/zwave.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/hue.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/tellstick.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/limitlessled.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/zwave.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/isy994.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/tellstick.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/blinksticklight.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/wink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/hyperion.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/hue.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/vera.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/rfxtrx.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/mjpeg.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_3.jpg +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_0.jpg +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/generic.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_2.jpg +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/foscam.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_1.jpg +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/generic.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/mjpeg.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/foscam.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/addtrustexternalcaroot.crt +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/instapush.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/nma.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/xmpp.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushover.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/file.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/syslog.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/telegram.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushbullet.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/slack.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/smtp.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushetta.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushover.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushetta.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/instapush.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/slack.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushbullet.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/smtp.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/nma.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/telegram.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/syslog.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/xmpp.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/file.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/logbook.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/discovery.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/group.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/influxdb.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/modbus.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/ecobee.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/configurator.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/arduino.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/sun.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/conversation.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/zone.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/zwave.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/isy994.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/device_sun_light_trigger.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/script.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/api.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/ifttt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/keyboard.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/browser.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/logger.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/simple_alarm.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/history.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/http.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/downloader.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/recorder.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/wink.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/updater.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/introduction.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/scene.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/verisure.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/shell_command.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/rfxtrx.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/demo.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/services.yaml +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/demo.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/mqtt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/state.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/numeric_state.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/zone.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/event.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/time.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/sun.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/event.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/mqtt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/sun.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/zone.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/numeric_state.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/state.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/time.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/dt.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/package.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/location.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/color.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/environment.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/temperature.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/template.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/template.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/temperature.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/location.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/package.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/environment.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/color.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/dt.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__init__.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/state.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/temperature.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/event.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/entity_component.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/entity.py +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/event.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/temperature.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/entity.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/entity_component.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/state.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/__main__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/__init__.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/core.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/config.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/bootstrap.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/exceptions.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/const.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/loader.cpython-34.pyc +/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/remote.cpython-34.pyc +/usr/local/bin/hass +/usr/local/bin/pip3 +/usr/local/bin/pip3.4 +/usr/local/bin/pip From 87d40f667361c0925963e4ed87feecce30eac9d4 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 14 Dec 2015 18:18:56 +0100 Subject: [PATCH 065/146] Move config details to doc --- .../components/device_tracker/fritz.py | 66 ++++--------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/homeassistant/components/device_tracker/fritz.py b/homeassistant/components/device_tracker/fritz.py index df439a4fb24..73c2e98792f 100644 --- a/homeassistant/components/device_tracker/fritz.py +++ b/homeassistant/components/device_tracker/fritz.py @@ -1,47 +1,12 @@ """ homeassistant.components.device_tracker.fritz -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Unfortunately, you have to execute the following command by hand: -sudo apt-get install libxslt-dev libxml2-dev - -Device tracker platform that supports scanning a FitzBox router for device +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Device tracker platform that supports scanning a FRITZ!Box router for device presence. -Configuration: - -To use the fritz tracker you have to adapt your configuration.yaml by -using the following template: - -device_tracker: - platform: fritz - host: YOUR_ROUTER_IP - username: YOUR_ADMIN_USERNAME - password: YOUR_ADMIN_PASSWORD - - -Description: - -host -*Optional -The IP address of your router, e.g. 192.168.0.1. -It is optional since every fritzbox is also reachable by using -the 169.254.1.1 IP. - -username -*Optional -The username of an user with administrative privileges, usually 'admin'. -However, it seems that it is not necessary to use it in -current generation fritzbox routers because the necessary data -can be retrieved anonymously. - -password -*Optional -The password for your given admin account. -However, it seems that it is not necessary to use it in current -generation fritzbox routers because the necessary data can -be retrieved anonymously. +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/device_tracker.fritz/ """ - import logging from datetime import timedelta @@ -58,16 +23,12 @@ _LOGGER = logging.getLogger(__name__) # noinspection PyUnusedLocal def get_scanner(hass, config): - """ - Validates config and returns FritzBoxScanner - @param hass: - @param config: - @return: - """ + """ Validates config and returns FritzBoxScanner. """ if not validate_config(config, {DOMAIN: []}, _LOGGER): return None + scanner = FritzBoxScanner(config[DOMAIN]) return scanner if scanner.success_init else None @@ -75,14 +36,14 @@ def get_scanner(hass, config): # pylint: disable=too-many-instance-attributes class FritzBoxScanner(object): """ - This class queries a FritzBox router. It is using the + This class queries a FRITZ!Box router. It is using the fritzconnection library for communication with the router. The API description can be found under: https://pypi.python.org/pypi/fritzconnection/0.4.6 - This scanner retrieves the list of known hosts and checks - their corresponding states (on, or off). + This scanner retrieves the list of known hosts and checks their + corresponding states (on, or off). Due to a bug of the fritzbox api (router side) it is not possible to track more than 16 hosts. @@ -113,7 +74,7 @@ class FritzBoxScanner(object): if CONF_PASSWORD in config.keys(): self.password = config[CONF_PASSWORD] - # Establish a connection to the fritzbox + # Establish a connection to the FRITZ!Box try: self.fritz_box = fc.FritzHosts(address=self.host, user=self.username, @@ -131,7 +92,7 @@ class FritzBoxScanner(object): self.fritz_box.modelname) self._update_info() else: - _LOGGER.error("Failed to establish connection to FritzBox " + _LOGGER.error("Failed to establish connection to FRITZ!Box " "with IP: %s", self.host) def scan_devices(self): @@ -152,10 +113,7 @@ class FritzBoxScanner(object): @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): - """ - Retrieves latest information from the FritzBox. - Returns boolean if scanning successful. - """ + """ Retrieves latest information from the FRITZ!Box. """ if not self.success_init: return False From 600831cff5a6da5fdfc873dc72f78e4ea7bf717c Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 10:29:27 -0700 Subject: [PATCH 066/146] Add support for template --- .../components/sensor/command_sensor.py | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/sensor/command_sensor.py b/homeassistant/components/sensor/command_sensor.py index e60723f6bfa..1fd30a8bdb5 100644 --- a/homeassistant/components/sensor/command_sensor.py +++ b/homeassistant/components/sensor/command_sensor.py @@ -10,8 +10,9 @@ import logging import subprocess from datetime import timedelta +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.helpers.entity import Entity -from homeassistant.util import Throttle +from homeassistant.util import template, Throttle _LOGGER = logging.getLogger(__name__) @@ -32,25 +33,24 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): data = CommandSensorData(config.get('command')) add_devices_callback([CommandSensor( + hass, data, config.get('name', DEFAULT_NAME), config.get('unit_of_measurement'), - config.get('correction_factor', None), - config.get('decimal_places', None) + config.get(CONF_VALUE_TEMPLATE) )]) # pylint: disable=too-many-arguments class CommandSensor(Entity): """ Represents a sensor that is returning a value of a shell commands. """ - def __init__(self, data, name, unit_of_measurement, corr_factor, - decimal_places): + def __init__(self, hass, data, name, unit_of_measurement, value_template): + self._hass = hass self.data = data self._name = name self._state = False self._unit_of_measurement = unit_of_measurement - self._corr_factor = corr_factor - self._decimal_places = decimal_places + self._value_template = value_template self.update() @property @@ -73,17 +73,8 @@ class CommandSensor(Entity): self.data.update() value = self.data.value - try: - if value is not None: - if self._corr_factor is not None: - value = float(value) * float(self._corr_factor) - if self._decimal_places is not None: - value = round(value, self._decimal_places) - if self._decimal_places == 0: - value = int(value) - self._state = value - except ValueError: - self._state = value + self._state = template.render_with_possible_json_value( + self._hass, self._value_template, value, 'N/A') # pylint: disable=too-few-public-methods From e821b546d5666f5a51d26738e50d9b0f2a359b9a Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 10:49:54 -0700 Subject: [PATCH 067/146] Ignore template if it isn't set --- homeassistant/components/sensor/command_sensor.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/command_sensor.py b/homeassistant/components/sensor/command_sensor.py index 1fd30a8bdb5..95751e73645 100644 --- a/homeassistant/components/sensor/command_sensor.py +++ b/homeassistant/components/sensor/command_sensor.py @@ -73,8 +73,11 @@ class CommandSensor(Entity): self.data.update() value = self.data.value - self._state = template.render_with_possible_json_value( - self._hass, self._value_template, value, 'N/A') + if self._value_template is not None: + self._state = template.render_with_possible_json_value( + self._hass, self._value_template, value, 'N/A') + else: + self._state = value # pylint: disable=too-few-public-methods From a1009d9138c2733cbda9e10dafd0d61eb5446b96 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 14 Dec 2015 21:38:56 +0100 Subject: [PATCH 068/146] Add template support --- homeassistant/components/binary_sensor/mqtt.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/binary_sensor/mqtt.py b/homeassistant/components/binary_sensor/mqtt.py index cac991d4eb2..916f1226c82 100644 --- a/homeassistant/components/binary_sensor/mqtt.py +++ b/homeassistant/components/binary_sensor/mqtt.py @@ -7,7 +7,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.mqtt/ """ import logging + +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.util import template import homeassistant.components.mqtt as mqtt _LOGGER = logging.getLogger(__name__) @@ -34,13 +37,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get('state_topic', None), config.get('qos', DEFAULT_QOS), config.get('payload_on', DEFAULT_PAYLOAD_ON), - config.get('payload_off', DEFAULT_PAYLOAD_OFF))]) + config.get('payload_off', DEFAULT_PAYLOAD_OFF), + config.get(CONF_VALUE_TEMPLATE))]) # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttBinarySensor(BinarySensorDevice): """ Represents a binary sensor that is updated by MQTT. """ - def __init__(self, hass, name, state_topic, qos, payload_on, payload_off): + def __init__(self, hass, name, state_topic, qos, payload_on, payload_off, + value_template): self._hass = hass self._name = name self._state = False @@ -51,6 +56,9 @@ class MqttBinarySensor(BinarySensorDevice): def message_received(topic, payload, qos): """ A new MQTT message has been received. """ + if value_template is not None: + payload = template.render_with_possible_json_value( + hass, value_template, payload) if payload == self._payload_on: self._state = True self.update_ha_state() From 53239387e066d4744666f5c8123216c50b1169da Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 11:08:31 -0700 Subject: [PATCH 069/146] Add support for template --- .../components/automation/numeric_state.py | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py index 9f099100084..93fedcc8e3b 100644 --- a/homeassistant/components/automation/numeric_state.py +++ b/homeassistant/components/automation/numeric_state.py @@ -8,13 +8,14 @@ at https://home-assistant.io/components/automation/#numeric-state-trigger """ import logging +from homeassistant.const import CONF_VALUE_TEMPLATE from homeassistant.helpers.event import track_state_change +from homeassistant.util import template CONF_ENTITY_ID = "entity_id" CONF_BELOW = "below" CONF_ABOVE = "above" -CONF_ATTRIBUTE = "attribute" _LOGGER = logging.getLogger(__name__) @@ -29,7 +30,7 @@ def trigger(hass, config, action): below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) - attribute = config.get(CONF_ATTRIBUTE) + value_template = config.get(CONF_VALUE_TEMPLATE) if below is None and above is None: _LOGGER.error("Missing configuration key." @@ -37,13 +38,18 @@ def trigger(hass, config, action): CONF_BELOW, CONF_ABOVE) return False + if value_template is not None: + renderer = lambda value: template.render(hass, value_template, value) + else: + renderer = None + # pylint: disable=unused-argument def state_automation_listener(entity, from_s, to_s): """ Listens for state changes and calls action. """ # Fire action if we go from outside range into range - if _in_range(to_s, above, below, attribute) and \ - (from_s is None or not _in_range(from_s, above, below, attribute)): + if _in_range(to_s, above, below, renderer) and \ + (from_s is None or not _in_range(from_s, above, below, renderer)): action() track_state_change( @@ -63,7 +69,7 @@ def if_action(hass, config): below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) - attribute = config.get(CONF_ATTRIBUTE) + value_template = config.get(CONF_VALUE_TEMPLATE) if below is None and above is None: _LOGGER.error("Missing configuration key." @@ -71,18 +77,29 @@ def if_action(hass, config): CONF_BELOW, CONF_ABOVE) return None + if value_template is not None: + renderer = lambda value: template.render(hass, value_template, value) + else: + renderer = None + def if_numeric_state(): """ Test numeric state condition. """ state = hass.states.get(entity_id) - return state is not None and _in_range(state, above, below, attribute) + return state is not None and _in_range(state, above, below, + renderer) return if_numeric_state -def _in_range(state, range_start, range_end, attribute): +def _in_range(state, range_start, range_end, renderer): """ Checks if value is inside the range """ - value = (state.state if attribute is None - else state.attributes.get(attribute)) + + if renderer is not None: + value = renderer({'value': state}) + else: + # If no renderer is provided, just assume they want the state + value = state.state + try: value = float(value) except ValueError: From cec62bdf874d3963096b4ce469b679487e3d08f0 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 14:47:32 -0700 Subject: [PATCH 070/146] Add tests --- .../automation/test_numeric_state.py | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/tests/components/automation/test_numeric_state.py b/tests/components/automation/test_numeric_state.py index 8280f396f93..9e0301168f2 100644 --- a/tests/components/automation/test_numeric_state.py +++ b/tests/components/automation/test_numeric_state.py @@ -295,7 +295,7 @@ class TestAutomationNumericState(unittest.TestCase): 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { @@ -314,7 +314,7 @@ class TestAutomationNumericState(unittest.TestCase): 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { @@ -333,7 +333,7 @@ class TestAutomationNumericState(unittest.TestCase): 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { @@ -352,7 +352,7 @@ class TestAutomationNumericState(unittest.TestCase): 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { @@ -371,7 +371,7 @@ class TestAutomationNumericState(unittest.TestCase): 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { @@ -384,13 +384,51 @@ class TestAutomationNumericState(unittest.TestCase): self.hass.pool.block_till_done() self.assertEqual(1, len(self.calls)) + def test_template_list(self): + self.assertTrue(automation.setup(self.hass, { + automation.DOMAIN: { + 'trigger': { + 'platform': 'numeric_state', + 'entity_id': 'test.entity', + 'value_template': '{{ value.attributes.test_attribute[2] }}', + 'below': 10, + }, + 'action': { + 'service': 'test.automation' + } + } + })) + # 3 is below 10 + self.hass.states.set('test.entity', 'entity', { 'test_attribute': [11, 15, 3] }) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + + def test_template_string(self): + self.assertTrue(automation.setup(self.hass, { + automation.DOMAIN: { + 'trigger': { + 'platform': 'numeric_state', + 'entity_id': 'test.entity', + 'value_template': '{{ value.attributes.test_attribute | multiply(10) }}', + 'below': 10, + }, + 'action': { + 'service': 'test.automation' + } + } + })) + # 9 is below 10 + self.hass.states.set('test.entity', 'entity', { 'test_attribute': '0.9' }) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + def test_if_not_fires_on_attribute_change_with_attribute_not_below_multiple_attributes(self): self.assertTrue(automation.setup(self.hass, { automation.DOMAIN: { 'trigger': { 'platform': 'numeric_state', 'entity_id': 'test.entity', - 'attribute': 'test_attribute', + 'value_template': '{{ value.attributes.test_attribute }}', 'below': 10, }, 'action': { From 91a945f4c73d4c539e14c73baec0c153eb3bd61d Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 15:01:38 -0700 Subject: [PATCH 071/146] Slight style change --- homeassistant/components/automation/numeric_state.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py index 93fedcc8e3b..40249372b43 100644 --- a/homeassistant/components/automation/numeric_state.py +++ b/homeassistant/components/automation/numeric_state.py @@ -85,8 +85,7 @@ def if_action(hass, config): def if_numeric_state(): """ Test numeric state condition. """ state = hass.states.get(entity_id) - return state is not None and _in_range(state, above, below, - renderer) + return state is not None and _in_range(state, above, below, renderer) return if_numeric_state From a517784c9e6d4d67e51652f58ade87430376e1f0 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Mon, 14 Dec 2015 15:07:35 -0700 Subject: [PATCH 072/146] Condense in_range template logic --- homeassistant/components/automation/numeric_state.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py index 40249372b43..d73b7061eb8 100644 --- a/homeassistant/components/automation/numeric_state.py +++ b/homeassistant/components/automation/numeric_state.py @@ -92,12 +92,7 @@ def if_action(hass, config): def _in_range(state, range_start, range_end, renderer): """ Checks if value is inside the range """ - - if renderer is not None: - value = renderer({'value': state}) - else: - # If no renderer is provided, just assume they want the state - value = state.state + value = state.state if renderer is None else renderer({'value': state}) try: value = float(value) From c1d728ce002ed41640a5ff3517a30812bd6bee22 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 14 Dec 2015 18:31:09 -0500 Subject: [PATCH 073/146] Remove @property from update function --- homeassistant/components/sensor/wink-eggminder.py | 15 +++++++-------- homeassistant/components/wink.py | 11 +++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/sensor/wink-eggminder.py b/homeassistant/components/sensor/wink-eggminder.py index 9398d11d177..6da42811a48 100755 --- a/homeassistant/components/sensor/wink-eggminder.py +++ b/homeassistant/components/sensor/wink-eggminder.py @@ -10,8 +10,8 @@ import logging from homeassistant.helpers.entity import Entity from homeassistant.const import CONF_ACCESS_TOKEN -REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' - '42fdcfa721b1bc583688e3592d8427f4c13ba6d9.zip' +REQUIREMENTS = ['https://github.com/w1ll1am23/python-wink/archive/' + 'master.zip' '#python-wink==0.2'] def setup_platform(hass, config, add_devices, discovery_info=None): @@ -41,7 +41,7 @@ class WinkEggMinder(Entity): @property def state(self): """ Returns the state. """ - return self.egg_count + return self.wink.state() @property def unique_id(self): @@ -53,12 +53,11 @@ class WinkEggMinder(Entity): """ Returns the name of the sensor if any. """ return self.wink.name() - @property def update(self): """ Update state of the Egg Minder. """ self.wink.updateState() - @property - def egg_count(self): - """ The number of eggs """ - return self.wink.state() + #@property + #def egg_count(self): + # """ The number of eggs """ + # return self.wink.state() diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 2ea93cce3a7..038bb046f78 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -1,8 +1,7 @@ """ homeassistant.components.wink -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Connects to a Wink hub and loads relevant components to control its devices. - For more details about this component, please refer to the documentation at https://home-assistant.io/components/wink/ """ @@ -17,14 +16,14 @@ from homeassistant.const import ( ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME) DOMAIN = "wink" -DEPENDENCIES = [] REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' - '9eb39eaba0717922815e673ad1114c685839d890.zip' - '#python-wink==0.1.1'] + '42fdcfa721b1bc583688e3592d8427f4c13ba6d9.zip' + '#python-wink==0.2'] DISCOVER_LIGHTS = "wink.lights" DISCOVER_SWITCHES = "wink.switches" DISCOVER_SENSORS = "wink.sensors" +DISCOVER_LOCKS = "wink.locks" def setup(hass, config): @@ -42,7 +41,7 @@ def setup(hass, config): ('light', pywink.get_bulbs, DISCOVER_LIGHTS), ('switch', pywink.get_switches, DISCOVER_SWITCHES), ('sensor', pywink.get_sensors, DISCOVER_SENSORS), - ('sensor', pywink.get_eggtrays, DISCOVER_SENSORS)): + ('lock', pywink.get_locks, DISCOVER_LOCKS)): if func_exists(): component = get_component(component_name) From 6a4442cddf9cde20eb6e9f2f072e8d48e45e9311 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 14 Dec 2015 18:34:11 -0500 Subject: [PATCH 074/146] Set REQUIREMENTS back to master --- homeassistant/components/sensor/wink-eggminder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wink-eggminder.py b/homeassistant/components/sensor/wink-eggminder.py index 6da42811a48..acdf4b79409 100755 --- a/homeassistant/components/sensor/wink-eggminder.py +++ b/homeassistant/components/sensor/wink-eggminder.py @@ -10,8 +10,8 @@ import logging from homeassistant.helpers.entity import Entity from homeassistant.const import CONF_ACCESS_TOKEN -REQUIREMENTS = ['https://github.com/w1ll1am23/python-wink/archive/' - 'master.zip' +REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' + '42fdcfa721b1bc583688e3592d8427f4c13ba6d9.zip' '#python-wink==0.2'] def setup_platform(hass, config, add_devices, discovery_info=None): From d16526739c549afd0c8e3facf1f3f5562cb256d1 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 14 Dec 2015 23:53:35 +0000 Subject: [PATCH 075/146] Add PlayMedia support to Chromecast --- homeassistant/components/media_player/cast.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 2b343129861..5ad9607d9a3 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -15,7 +15,7 @@ from homeassistant.const import ( from homeassistant.components.media_player import ( MediaPlayerDevice, SUPPORT_PAUSE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_MUTE, - SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_YOUTUBE, + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_YOUTUBE, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_VIDEO) @@ -24,7 +24,7 @@ CONF_IGNORE_CEC = 'ignore_cec' CAST_SPLASH = 'https://home-assistant.io/images/cast/splash.png' SUPPORT_CAST = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PREVIOUS_TRACK | \ - SUPPORT_NEXT_TRACK | SUPPORT_YOUTUBE + SUPPORT_NEXT_TRACK | SUPPORT_YOUTUBE | SUPPORT_PLAY_MEDIA KNOWN_HOSTS = [] # pylint: disable=invalid-name @@ -261,6 +261,10 @@ class CastDevice(MediaPlayerDevice): """ Seek the media to a specific location. """ self.cast.media_controller.seek(position) + def play_media(self, media_type, media_id): + """ Plays media from a URL """ + self.cast.media_controller.play_media(media_id, media_type) + def play_youtube(self, media_id): """ Plays a YouTube media. """ self.youtube.play_video(media_id) From 056645fe1305d46e73009b05df186c6d6ec28083 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 14 Dec 2015 19:08:45 -0500 Subject: [PATCH 076/146] Removed files.txt --- files.txt | 459 ------------------------------------------------------ 1 file changed, 459 deletions(-) delete mode 100644 files.txt diff --git a/files.txt b/files.txt deleted file mode 100644 index 24cdbbd9cf5..00000000000 --- a/files.txt +++ /dev/null @@ -1,459 +0,0 @@ -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/dependency_links.txt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/top_level.txt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/SOURCES.txt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/requires.txt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/not-zip-safe -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/PKG-INFO -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/EGG-INFO/entry_points.txt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__main__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/config.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/exceptions.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/bootstrap.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/remote.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/loader.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/core.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/const.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/startup/launchd.plist -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/history.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/arduino.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/wink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rfxtrx.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/updater.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/isy994.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/keyboard.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/discovery.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/zone.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/logger.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/http.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/shell_command.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/scene.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/conversation.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/simple_alarm.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/introduction.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/recorder.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/script.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/ecobee.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/logbook.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_sun_light_trigger.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/browser.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/configurator.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sun.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/api.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/zwave.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/influxdb.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/ifttt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/downloader.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/verisure.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/group.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/modbus.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/manual.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/verisure.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/manual.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/alarm_control_panel/__pycache__/verisure.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/version.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/index.html.template -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/mdi_version.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-384x384.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/webcomponents-lite.min.js -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/service_worker.js -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-192x192.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon-apple-180x180.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/frontend.html -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/manifest.json -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/mdi.html -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/favicon.ico -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_philips_hue.jpg -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_plex_mediaserver.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/config_ecobee_thermostat.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-icon.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-icon-2x.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/layers-2x.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/layers.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/www_static/images/leaflet/marker-shadow.png -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/mdi_version.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/frontend/__pycache__/version.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/vera.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/arduino.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/wink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rpi_gpio.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rfxtrx.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/isy994.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/wemo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/command_switch.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/mystrom.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/arest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/edimax.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/transmission.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/zwave.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/orvibo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/tellstick.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/hikvisioncam.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/rest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/verisure.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/modbus.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/transmission.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/hikvisioncam.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/orvibo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/modbus.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/arduino.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/command_switch.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/zwave.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/isy994.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/tellstick.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/arest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/wemo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/wink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rpi_gpio.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/vera.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/edimax.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/verisure.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rfxtrx.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/mystrom.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/switch/__pycache__/rest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/plex.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/squeezebox.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/kodi.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/mpd.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/firetv.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/itunes.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/denon.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/sonos.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/cast.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/squeezebox.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/cast.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/mpd.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/sonos.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/itunes.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/plex.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/kodi.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/denon.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/media_player/__pycache__/firetv.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/arest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/binary_sensor/__pycache__/arest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/ubus.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/netgear.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/asuswrt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/tplink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/luci.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/actiontec.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/nmap_tracker.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/aruba.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/tomato.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/owntracks.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/thomson.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/snmp.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/geofancy.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/ddwrt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/tomato.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/ddwrt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/tplink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/geofancy.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/thomson.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/owntracks.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/ubus.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/luci.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/netgear.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/asuswrt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/aruba.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/nmap_tracker.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/snmp.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/device_tracker/__pycache__/actiontec.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/wink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/lock/__pycache__/wink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/glances.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/vera.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/worldclock.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/arduino.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/wink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/sabnzbd.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rpi_gpio.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rfxtrx.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/forecast.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/isy994.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/arest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/systemmonitor.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/efergy.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/bitcoin.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/dht.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/temper.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/ecobee.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/transmission.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/cpuspeed.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/wink-eggminder.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/zwave.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/command_sensor.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/mysensors.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/openweathermap.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/swiss_public_transport.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/tellstick.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/time_date.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/rest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/verisure.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/modbus.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/transmission.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/worldclock.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/forecast.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/bitcoin.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/systemmonitor.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/glances.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/modbus.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/ecobee.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/arduino.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/zwave.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/isy994.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/swiss_public_transport.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/cpuspeed.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/tellstick.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/wink-eggminder.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/sabnzbd.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/arest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/command_sensor.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/dht.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/temper.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/wink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rpi_gpio.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/time_date.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/vera.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/verisure.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/efergy.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rfxtrx.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/mysensors.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/rest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/sensor/__pycache__/openweathermap.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/radiotherm.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/nest.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/heat_control.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/homematic.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/ecobee.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/honeywell.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/heatmiser.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/heat_control.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/ecobee.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/nest.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/homematic.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/honeywell.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/radiotherm.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/thermostat/__pycache__/heatmiser.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/vera.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/wink.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/rfxtrx.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/isy994.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/hyperion.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/light_profiles.csv -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/blinksticklight.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/limitlessled.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/zwave.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/hue.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/tellstick.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/limitlessled.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/zwave.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/isy994.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/tellstick.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/blinksticklight.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/wink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/hyperion.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/hue.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/vera.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/light/__pycache__/rfxtrx.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/mjpeg.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_3.jpg -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_0.jpg -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/generic.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_2.jpg -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/foscam.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/demo_1.jpg -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/generic.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/mjpeg.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/camera/__pycache__/foscam.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/addtrustexternalcaroot.crt -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/mqtt/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/instapush.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/nma.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/xmpp.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushover.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/file.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/syslog.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/telegram.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushbullet.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/slack.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/smtp.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/pushetta.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushover.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushetta.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/instapush.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/slack.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/pushbullet.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/smtp.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/nma.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/telegram.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/syslog.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/xmpp.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/notify/__pycache__/file.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/logbook.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/discovery.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/group.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/influxdb.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/modbus.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/ecobee.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/configurator.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/arduino.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/sun.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/conversation.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/zone.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/zwave.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/isy994.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/device_sun_light_trigger.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/script.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/api.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/ifttt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/keyboard.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/browser.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/logger.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/simple_alarm.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/history.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/http.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/downloader.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/recorder.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/wink.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/updater.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/introduction.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/scene.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/verisure.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/shell_command.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/__pycache__/rfxtrx.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/demo.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/services.yaml -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/rollershutter/__pycache__/demo.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/mqtt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/state.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/numeric_state.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/zone.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/event.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/time.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/sun.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/event.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/mqtt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/sun.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/zone.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/numeric_state.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/state.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/components/automation/__pycache__/time.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/dt.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/package.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/location.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/color.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/environment.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/temperature.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/template.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/template.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/temperature.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/location.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/package.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/environment.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/color.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/util/__pycache__/dt.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__init__.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/state.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/temperature.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/event.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/entity_component.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/entity.py -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/event.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/temperature.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/entity.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/entity_component.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/helpers/__pycache__/state.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/__main__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/__init__.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/core.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/config.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/bootstrap.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/exceptions.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/const.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/loader.cpython-34.pyc -/usr/local/lib/python3.4/dist-packages/homeassistant-0.10.0.dev0-py3.4.egg/homeassistant/__pycache__/remote.cpython-34.pyc -/usr/local/bin/hass -/usr/local/bin/pip3 -/usr/local/bin/pip3.4 -/usr/local/bin/pip From 2e0042adb017f9bbc7322809aba522f121f66c04 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 14 Dec 2015 21:39:48 -0800 Subject: [PATCH 077/146] Tweak iCloud device tracker --- .coveragerc | 1 + .../components/device_tracker/icloud.py | 32 +++++++++++++------ requirements_all.txt | 6 ++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.coveragerc b/.coveragerc index 7192883b655..94f4352ef89 100644 --- a/.coveragerc +++ b/.coveragerc @@ -41,6 +41,7 @@ omit = homeassistant/components/device_tracker/ddwrt.py homeassistant/components/device_tracker/fritz.py homeassistant/components/device_tracker/geofancy.py + homeassistant/components/device_tracker/icloud.py homeassistant/components/device_tracker/luci.py homeassistant/components/device_tracker/ubus.py homeassistant/components/device_tracker/netgear.py diff --git a/homeassistant/components/device_tracker/icloud.py b/homeassistant/components/device_tracker/icloud.py index a4adaa547bc..a617fda9411 100644 --- a/homeassistant/components/device_tracker/icloud.py +++ b/homeassistant/components/device_tracker/icloud.py @@ -20,14 +20,15 @@ import re from homeassistant.const import CONF_USERNAME, CONF_PASSWORD from homeassistant.helpers.event import track_utc_time_change -SCAN_INTERVAL = 1800 - _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['https://github.com/picklepete/pyicloud/archive/' '80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip' '#pyicloud==0.8.0'] +CONF_INTERVAL = 'interval' +DEFAULT_INTERVAL = 8 + def setup_scanner(hass, config, see): """ @@ -38,8 +39,12 @@ def setup_scanner(hass, config, see): from pyicloud.exceptions import PyiCloudNoDevicesException # Get the username and password from the configuration - username = config[CONF_USERNAME] - password = config[CONF_PASSWORD] + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + + if username is None or password is None: + _LOGGER.error('Must specify a username and password') + return try: _LOGGER.info('Logging into iCloud Account') @@ -48,11 +53,18 @@ def setup_scanner(hass, config, see): password, verify=True) except PyiCloudFailedLoginException as error: - _LOGGER.exception( - 'Error logging into iCloud Service: %s' % error - ) + _LOGGER.exception('Error logging into iCloud Service: %s', error) return + def keep_alive(now): + """ + Keeps authenticating icloud connection + """ + api.authenticate() + _LOGGER.info("Authenticate against iCloud.") + + track_utc_time_change(hass, keep_alive, second=0) + def update_icloud(now): """ Authenticate against iCloud and scan for devices. @@ -83,7 +95,7 @@ def setup_scanner(hass, config, see): _LOGGER.info('No iCloud Devices found!') track_utc_time_change( - hass, - update_icloud, - second=range(0, 60, SCAN_INTERVAL) + hass, update_icloud, + minute=range(0, 60, config.get(CONF_INTERVAL, DEFAULT_INTERVAL)), + second=0 ) diff --git a/requirements_all.txt b/requirements_all.txt index c9835294a20..48a127b0f30 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -9,6 +9,9 @@ jinja2>=2.8 # homeassistant.components.arduino PyMata==2.07a +# homeassistant.components.device_tracker.icloud +https://github.com/picklepete/pyicloud/archive/80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip#pyicloud==0.8.0 + # homeassistant.components.device_tracker.netgear pynetgear==0.3 @@ -177,6 +180,3 @@ https://github.com/persandstrom/python-verisure/archive/9873c4527f01b1ba1f72ae60 # homeassistant.components.zwave pydispatcher==2.0.5 - -# homeassistant.sensor.icloud -https://github.com/picklepete/pyicloud/archive/80f6cd6decc950514b8dc43b30c5bded81b34d5f.zip#pyicloud==0.8.0 From 027b891052889325cd97587fc3fadff3c06cc303 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 14 Dec 2015 23:20:43 -0800 Subject: [PATCH 078/146] Add tests for API.stream --- homeassistant/components/api.py | 17 ++++++--- homeassistant/components/http.py | 18 +++++---- tests/components/test_api.py | 64 +++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/api.py b/homeassistant/components/api.py index 6d2f9e52a7a..18b743d06ca 100644 --- a/homeassistant/components/api.py +++ b/homeassistant/components/api.py @@ -125,7 +125,6 @@ def _handle_get_api_stream(handler, path_match, data): try: wfile.write(msg.encode("UTF-8")) wfile.flush() - handler.server.sessions.extend_validation(session_id) except (IOError, ValueError): # IOError: socket errors # ValueError: raised when 'I/O operation on closed file' @@ -135,14 +134,14 @@ def _handle_get_api_stream(handler, path_match, data): """ Forwards events to the open request. """ nonlocal gracefully_closed - if block.is_set() or event.event_type == EVENT_TIME_CHANGED or \ - restrict and event.event_type not in restrict: + if block.is_set() or event.event_type == EVENT_TIME_CHANGED: return elif event.event_type == EVENT_HOMEASSISTANT_STOP: gracefully_closed = True block.set() return + handler.server.sessions.extend_validation(session_id) write_message(json.dumps(event, cls=rem.JSONEncoder)) handler.send_response(HTTP_OK) @@ -150,7 +149,11 @@ def _handle_get_api_stream(handler, path_match, data): session_id = handler.set_session_cookie_header() handler.end_headers() - hass.bus.listen(MATCH_ALL, forward_events) + if restrict: + for event in restrict: + hass.bus.listen(event, forward_events) + else: + hass.bus.listen(MATCH_ALL, forward_events) while True: write_message(STREAM_PING_PAYLOAD) @@ -164,7 +167,11 @@ def _handle_get_api_stream(handler, path_match, data): _LOGGER.info("Found broken event stream to %s, cleaning up", handler.client_address[0]) - hass.bus.remove_listener(MATCH_ALL, forward_events) + if restrict: + for event in restrict: + hass.bus.remove_listener(event, forward_events) + else: + hass.bus.remove_listener(MATCH_ALL, forward_events) def _handle_get_api_config(handler, path_match, data): diff --git a/homeassistant/components/http.py b/homeassistant/components/http.py index 81e26aeae5a..7a4e87de5a8 100644 --- a/homeassistant/components/http.py +++ b/homeassistant/components/http.py @@ -359,13 +359,13 @@ class RequestHandler(SimpleHTTPRequestHandler): def set_session_cookie_header(self): """ Add the header for the session cookie and return session id. """ if not self.authenticated: - return + return None session_id = self.get_cookie_session_id() if session_id is not None: self.server.sessions.extend_validation(session_id) - return + return session_id self.send_header( 'Set-Cookie', @@ -422,10 +422,10 @@ def session_valid_time(): class SessionStore(object): """ Responsible for storing and retrieving http sessions """ - def __init__(self, enabled=True): + def __init__(self): """ Set up the session store """ self._sessions = {} - self.lock = threading.RLock() + self._lock = threading.RLock() @util.Throttle(SESSION_CLEAR_INTERVAL) def _remove_expired(self): @@ -437,7 +437,7 @@ class SessionStore(object): def is_valid(self, key): """ Return True if a valid session is given. """ - with self.lock: + with self._lock: self._remove_expired() return (key in self._sessions and @@ -445,17 +445,19 @@ class SessionStore(object): def extend_validation(self, key): """ Extend a session validation time. """ - with self.lock: + with self._lock: + if key not in self._sessions: + return self._sessions[key] = session_valid_time() def destroy(self, key): """ Destroy a session by key. """ - with self.lock: + with self._lock: self._sessions.pop(key, None) def create(self): """ Creates a new session. """ - with self.lock: + with self._lock: session_id = util.get_random_string(20) while session_id in self._sessions: diff --git a/tests/components/test_api.py b/tests/components/test_api.py index cf530c1f301..c8d8fa50ae1 100644 --- a/tests/components/test_api.py +++ b/tests/components/test_api.py @@ -5,10 +5,11 @@ tests.test_component_http Tests Home Assistant HTTP component does what it should do. """ # pylint: disable=protected-access,too-many-public-methods -import unittest +from contextlib import closing import json -from unittest.mock import patch import tempfile +import unittest +from unittest.mock import patch import requests @@ -415,3 +416,62 @@ class TestAPI(unittest.TestCase): }), headers=HA_HEADERS) self.assertEqual(200, req.status_code) + + def test_stream(self): + listen_count = self._listen_count() + with closing(requests.get(_url(const.URL_API_STREAM), + stream=True, headers=HA_HEADERS)) as req: + + self.assertEqual(listen_count + 1, self._listen_count()) + data = self._stream_next_event(req) + + self.assertEqual('ping', data) + + hass.bus.fire('test_event') + hass.pool.block_till_done() + + data = self._stream_next_event(req) + + self.assertEqual('test_event', data['event_type']) + + def test_stream_with_restricted(self): + listen_count = self._listen_count() + with closing(requests.get(_url(const.URL_API_STREAM), + data=json.dumps({ + 'restrict': 'test_event1,test_event3'}), + stream=True, headers=HA_HEADERS)) as req: + + self.assertEqual(listen_count + 2, self._listen_count()) + + data = self._stream_next_event(req) + + self.assertEqual('ping', data) + + hass.bus.fire('test_event1') + hass.pool.block_till_done() + hass.bus.fire('test_event2') + hass.pool.block_till_done() + hass.bus.fire('test_event3') + hass.pool.block_till_done() + + data = self._stream_next_event(req) + self.assertEqual('test_event1', data['event_type']) + data = self._stream_next_event(req) + self.assertEqual('test_event3', data['event_type']) + + def _stream_next_event(self, stream): + data = b'' + last_new_line = False + for dat in stream.iter_content(1): + if dat == b'\n' and last_new_line: + break + data += dat + last_new_line = dat == b'\n' + + conv = data.decode('utf-8').strip()[6:] + + return conv if conv == 'ping' else json.loads(conv) + + def _listen_count(self): + """ Return number of event listeners. """ + return sum(hass.bus.listeners.values()) From 4029d149fbbe661a5c726c703c08885e7787f979 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 14 Dec 2015 23:27:22 -0800 Subject: [PATCH 079/146] Weird travis fix for api --- tests/components/test_api.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/components/test_api.py b/tests/components/test_api.py index c8d8fa50ae1..644982e18fc 100644 --- a/tests/components/test_api.py +++ b/tests/components/test_api.py @@ -422,11 +422,11 @@ class TestAPI(unittest.TestCase): with closing(requests.get(_url(const.URL_API_STREAM), stream=True, headers=HA_HEADERS)) as req: - self.assertEqual(listen_count + 1, self._listen_count()) data = self._stream_next_event(req) - self.assertEqual('ping', data) + self.assertEqual(listen_count + 1, self._listen_count()) + hass.bus.fire('test_event') hass.pool.block_till_done() @@ -441,12 +441,11 @@ class TestAPI(unittest.TestCase): 'restrict': 'test_event1,test_event3'}), stream=True, headers=HA_HEADERS)) as req: - self.assertEqual(listen_count + 2, self._listen_count()) - data = self._stream_next_event(req) - self.assertEqual('ping', data) + self.assertEqual(listen_count + 2, self._listen_count()) + hass.bus.fire('test_event1') hass.pool.block_till_done() hass.bus.fire('test_event2') From a35dcf860e234d0d1c641c27914c509c2112cca0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 14 Dec 2015 23:53:32 -0800 Subject: [PATCH 080/146] Update frontend with layout bugfix --- homeassistant/components/frontend/version.py | 2 +- homeassistant/components/frontend/www_static/frontend.html | 7 +++++++ .../components/frontend/www_static/home-assistant-polymer | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 13335959c9f..c0bafc4f8f3 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,2 +1,2 @@ """ DO NOT MODIFY. Auto-generated by build_frontend script """ -VERSION = "026761064bba4614a0441b7b4fc4eeea" +VERSION = "0d8516cd9a13ee2ae3f27c702777e028" diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index dc839ee6f9f..7d20e4bb667 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -3775,6 +3775,7 @@ case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return .column { max-width: 500px; + overflow-x: hidden; } .zone-card { @@ -3790,6 +3791,12 @@ case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return .zone-card { margin-left: 0; } + } + + @media (max-width: 599px) { + .column { + max-width: 600px; + } }