diff --git a/.coveragerc b/.coveragerc index f0953f49cd5..cccd815df2d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -12,21 +12,21 @@ omit = homeassistant/components/*/zwave.py homeassistant/components/*/tellstick.py + homeassistant/components/*/vera.py homeassistant/components/keyboard.py homeassistant/components/switch/wemo.py homeassistant/components/thermostat/nest.py homeassistant/components/light/hue.py homeassistant/components/sensor/systemmonitor.py + homeassistant/components/sensor/sabnzbd.py homeassistant/components/notify/pushbullet.py + homeassistant/components/notify/pushover.py homeassistant/components/media_player/cast.py homeassistant/components/device_tracker/luci.py homeassistant/components/device_tracker/tomato.py homeassistant/components/device_tracker/netgear.py homeassistant/components/device_tracker/nmap_tracker.py - homeassistant/components/light/vera.py - homeassistant/components/sensor/vera.py - homeassistant/components/switch/vera.py [report] diff --git a/.gitmodules b/.gitmodules index 2e43a7d4dd0..ae38be7c61b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "homeassistant/external/vera"] path = homeassistant/external/vera url = https://github.com/jamespcole/home-assistant-vera-api.git +[submodule "homeassistant/external/nzbclients"] + path = homeassistant/external/nzbclients + url = https://github.com/jamespcole/home-assistant-nzb-clients.git diff --git a/Dockerfile b/Dockerfile index a78322bbd80..ff34dc79297 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ MAINTAINER Paulus Schoutsen VOLUME /config RUN apt-get update && \ - apt-get install -y cython3 libudev-dev python-sphinx python3-setuptools mercurial && \ + apt-get install -y cython3 libudev-dev && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ pip3 install cython && \ scripts/build_python_openzwave diff --git a/config/configuration.yaml.example b/config/configuration.yaml.example index c758833d336..125be6e2d05 100644 --- a/config/configuration.yaml.example +++ b/config/configuration.yaml.example @@ -1,8 +1,20 @@ homeassistant: + # Omitted values in this section will be auto detected using freegeoip.net + # Location required to calculate the time the sun rises and sets latitude: 32.87336 longitude: 117.22743 + # C for Celcius, F for Fahrenheit + temperature_unit: C + + # Pick yours from here: + # http://en.wikipedia.org/wiki/List_of_tz_database_time_zones + time_zone: America/Los_Angeles + + # Name of the location where Home Assistant is running + name: Home + http: api_password: mypass # Set to 1 to enable development mode @@ -120,4 +132,31 @@ sensor: - type: 'memory_free' - type: 'processor_use' - type: 'process' - arg: 'octave-cli' \ No newline at end of file + arg: 'octave-cli' + +script: + # Turns on the bedroom lights and then the living room lights 1 minute later + wakeup: + alias: Wake Up + sequence: + # alias is optional + - alias: Bedroom lights on + execute_service: light.turn_on + service_data: + entity_id: group.bedroom + - delay: + # supports seconds, milliseconds, minutes, hours, etc. + minutes: 1 + - alias: Living room lights on + execute_service: light.turn_on + service_data: + entity_id: group.living_room + +scene: + - name: Romantic + entities: + light.tv_back_light: on + light.ceiling: + state: on + color: [0.33, 0.66] + brightness: 200 diff --git a/homeassistant/__init__.py b/homeassistant/__init__.py index 354898c0319..b93a8ee99be 100644 --- a/homeassistant/__init__.py +++ b/homeassistant/__init__.py @@ -15,11 +15,14 @@ import re import datetime as dt import functools as ft +import requests + from homeassistant.const import ( EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED, EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL, - EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED) + EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED, + TEMP_CELCIUS, TEMP_FAHRENHEIT) import homeassistant.util as util DOMAIN = "homeassistant" @@ -49,19 +52,34 @@ class HomeAssistant(object): self.bus = EventBus(pool) self.services = ServiceRegistry(self.bus, pool) self.states = StateMachine(self.bus) + self.config = Config() - # List of loaded components - self.components = [] + @property + def components(self): + """ DEPRECATED 3/21/2015. Use hass.config.components """ + _LOGGER.warning( + 'hass.components is deprecated. Use hass.config.components') + return self.config.components - # Remote.API object pointing at local API - self.local_api = None + @property + def local_api(self): + """ DEPRECATED 3/21/2015. Use hass.config.api """ + _LOGGER.warning( + 'hass.local_api is deprecated. Use hass.config.api') + return self.config.api - # Directory that holds the configuration - self.config_dir = os.path.join(os.getcwd(), 'config') + @property + def config_dir(self): + """ DEPRECATED 3/18/2015. Use hass.config.config_dir """ + _LOGGER.warning( + 'hass.config_dir is deprecated. Use hass.config.config_dir') + return self.config.config_dir def get_config_path(self, path): - """ Returns path to the file within the config dir. """ - return os.path.join(self.config_dir, path) + """ DEPRECATED 3/18/2015. Use hass.config.path """ + _LOGGER.warning( + 'hass.get_config_path is deprecated. Use hass.config.path') + return self.config.path(path) def start(self): """ Start home assistant. """ @@ -115,6 +133,7 @@ class HomeAssistant(object): action(now) self.bus.listen(EVENT_TIME_CHANGED, point_in_time_listener) + return point_in_time_listener # pylint: disable=too-many-arguments def track_time_change(self, action, @@ -154,6 +173,7 @@ class HomeAssistant(object): action(event.data[ATTR_NOW]) self.bus.listen(EVENT_TIME_CHANGED, time_listener) + return time_listener def stop(self): """ Stops Home Assistant and shuts down all threads. """ @@ -457,6 +477,11 @@ class State(object): self.last_changed = util.strip_microseconds( last_changed or self.last_updated) + @property + def domain(self): + """ Returns domain of this state. """ + return util.split_entity_id(self.entity_id)[0] + def copy(self): """ Creates a copy of itself. """ return State(self.entity_id, self.state, @@ -829,6 +854,83 @@ class Timer(threading.Thread): self.hass.bus.fire(EVENT_TIME_CHANGED, {ATTR_NOW: now}) +class Config(object): + """ Configuration settings for Home Assistant. """ + + # pylint: disable=too-many-instance-attributes + def __init__(self): + self.latitude = None + self.longitude = None + self.temperature_unit = None + self.location_name = None + self.time_zone = None + + # List of loaded components + self.components = [] + + # Remote.API object pointing at local API + self.api = None + + # Directory that holds the configuration + self.config_dir = os.path.join(os.getcwd(), 'config') + + def auto_detect(self): + """ Will attempt to detect config of Home Assistant. """ + # Only detect if location or temp unit missing + if None not in (self.latitude, self.longitude, self.temperature_unit): + return + + _LOGGER.info('Auto detecting location and temperature unit') + + try: + info = requests.get('https://freegeoip.net/json/').json() + except requests.RequestException: + return + + if self.latitude is None and self.longitude is None: + self.latitude = info['latitude'] + self.longitude = info['longitude'] + + if self.temperature_unit is None: + # From Wikipedia: + # Fahrenheit is used in the Bahamas, Belize, the Cayman Islands, + # Palau, and the United States and associated territories of + # American Samoa and the U.S. Virgin Islands + if info['country_code'] in ('BS', 'BZ', 'KY', 'PW', + 'US', 'AS', 'VI'): + self.temperature_unit = TEMP_FAHRENHEIT + else: + self.temperature_unit = TEMP_CELCIUS + + if self.location_name is None: + self.location_name = info['city'] + + if self.time_zone is None: + self.time_zone = info['time_zone'] + + def path(self, path): + """ Returns path to the file within the config dir. """ + return os.path.join(self.config_dir, path) + + def temperature(self, value, unit): + """ Converts temperature to user preferred unit if set. """ + if not (unit and self.temperature_unit and + unit != self.temperature_unit): + return value, unit + + try: + if unit == TEMP_CELCIUS: + # Convert C to F + return round(float(value) * 1.8 + 32.0, 1), TEMP_FAHRENHEIT + + # Convert F to C + return round((float(value)-32.0)/1.8, 1), TEMP_CELCIUS + + except ValueError: + # Could not convert value to float + return value, unit + + class HomeAssistantError(Exception): """ General Home Assistant exception occured. """ pass diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 56d77fdcb26..4a6aab53483 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -20,7 +20,10 @@ import homeassistant import homeassistant.loader as loader import homeassistant.components as core_components import homeassistant.components.group as group -from homeassistant.const import EVENT_COMPONENT_LOADED +from homeassistant.const import ( + EVENT_COMPONENT_LOADED, CONF_LATITUDE, CONF_LONGITUDE, + CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, TEMP_CELCIUS, + TEMP_FAHRENHEIT) _LOGGER = logging.getLogger(__name__) @@ -28,21 +31,49 @@ ATTR_COMPONENT = "component" def setup_component(hass, domain, config=None): - """ Setup a component for Home Assistant. """ - # Check if already loaded - if domain in hass.components: - return + """ Setup a component and all its dependencies. """ + + if domain in hass.config.components: + return True _ensure_loader_prepared(hass) if config is None: config = defaultdict(dict) + components = loader.load_order_component(domain) + + # OrderedSet is empty if component or dependencies could not be resolved + if not components: + return False + + for component in components: + if component in hass.config.components: + continue + + if not _setup_component(hass, component, config): + return False + + return True + + +def _setup_component(hass, domain, config): + """ Setup a component for Home Assistant. """ component = loader.get_component(domain) + missing_deps = [dep for dep in component.DEPENDENCIES + if dep not in hass.config.components] + + if missing_deps: + _LOGGER.error( + "Not initializing %s because not all dependencies loaded: %s", + domain, ", ".join(missing_deps)) + + return False + try: if component.setup(hass, config): - hass.components.append(component.DOMAIN) + hass.config.components.append(component.DOMAIN) # Assumption: if a component does not depend on groups # it communicates with devices @@ -73,6 +104,8 @@ def from_config_dict(config, hass=None): if hass is None: hass = homeassistant.HomeAssistant() + process_ha_core_config(hass, config.get(homeassistant.DOMAIN, {})) + enable_logging(hass) _ensure_loader_prepared(hass) @@ -97,7 +130,7 @@ def from_config_dict(config, hass=None): # Setup the components for domain in loader.load_order_components(components): - setup_component(hass, domain, config) + _setup_component(hass, domain, config) return hass @@ -111,14 +144,19 @@ def from_config_file(config_path, hass=None): if hass is None: hass = homeassistant.HomeAssistant() - # Set config dir to directory holding config file - hass.config_dir = os.path.abspath(os.path.dirname(config_path)) + # Set config dir to directory holding config file + hass.config.config_dir = os.path.abspath(os.path.dirname(config_path)) config_dict = {} # check config file type if os.path.splitext(config_path)[1] == '.yaml': # Read yaml config_dict = yaml.load(io.open(config_path, 'r')) + + # If YAML file was empty + if config_dict is None: + config_dict = {} + else: # Read config config = configparser.ConfigParser() @@ -138,13 +176,13 @@ def enable_logging(hass): logging.basicConfig(level=logging.INFO) # Log errors to a file if we have write access to file or config dir - err_log_path = hass.get_config_path("home-assistant.log") + err_log_path = hass.config.path("home-assistant.log") err_path_exists = os.path.isfile(err_log_path) # Check if we can write to the error log if it exists or that # we can create files in the containing directory if not. if (err_path_exists and os.access(err_log_path, os.W_OK)) or \ - (not err_path_exists and os.access(hass.config_dir, os.W_OK)): + (not err_path_exists and os.access(hass.config.config_dir, os.W_OK)): err_handler = logging.FileHandler( err_log_path, mode='w', delay=True) @@ -160,6 +198,26 @@ def enable_logging(hass): "Unable to setup error log %s (access denied)", err_log_path) +def process_ha_core_config(hass, config): + """ Processes the [homeassistant] section from the config. """ + for key, attr in ((CONF_LATITUDE, 'latitude'), + (CONF_LONGITUDE, 'longitude'), + (CONF_NAME, 'location_name'), + (CONF_TIME_ZONE, 'time_zone')): + if key in config: + setattr(hass.config, attr, config[key]) + + if CONF_TEMPERATURE_UNIT in config: + unit = config[CONF_TEMPERATURE_UNIT] + + if unit == 'C': + hass.config.temperature_unit = TEMP_CELCIUS + elif unit == 'F': + hass.config.temperature_unit = TEMP_FAHRENHEIT + + hass.config.auto_detect() + + def _ensure_loader_prepared(hass): """ Ensure Home Assistant loader is prepared. """ if not loader.PREPARED: diff --git a/homeassistant/components/api.py b/homeassistant/components/api.py index a29b81e3cba..b5cdb9cae6c 100644 --- a/homeassistant/components/api.py +++ b/homeassistant/components/api.py @@ -10,7 +10,7 @@ import threading import json import homeassistant as ha -from homeassistant.helpers import TrackStates +from homeassistant.helpers.state import TrackStates import homeassistant.remote as rem from homeassistant.const import ( URL_API, URL_API_STATES, URL_API_EVENTS, URL_API_SERVICES, URL_API_STREAM, @@ -32,7 +32,7 @@ _LOGGER = logging.getLogger(__name__) def setup(hass, config): """ Register the API with the HTTP interface. """ - if 'http' not in hass.components: + if 'http' not in hass.config.components: _LOGGER.error('Dependency http is not loaded') return False @@ -311,4 +311,4 @@ def _handle_delete_api_event_forward(handler, path_match, data): def _handle_get_api_components(handler, path_match, data): """ Returns all the loaded components. """ - handler.write_json(handler.server.hass.components) + handler.write_json(handler.server.hass.config.components) diff --git a/homeassistant/components/configurator.py b/homeassistant/components/configurator.py index fdd3c571601..8bec580abf9 100644 --- a/homeassistant/components/configurator.py +++ b/homeassistant/components/configurator.py @@ -83,8 +83,8 @@ def _get_instance(hass): except KeyError: _INSTANCES[hass] = Configurator(hass) - if DOMAIN not in hass.components: - hass.components.append(DOMAIN) + if DOMAIN not in hass.config.components: + hass.config.components.append(DOMAIN) return _INSTANCES[hass] diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index 9c3e699b113..48d8476759f 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -10,15 +10,14 @@ import homeassistant as ha import homeassistant.bootstrap as bootstrap import homeassistant.loader as loader from homeassistant.const import ( - CONF_PLATFORM, ATTR_ENTITY_PICTURE, - CONF_LATITUDE, CONF_LONGITUDE) + CONF_PLATFORM, ATTR_ENTITY_PICTURE, ATTR_ENTITY_ID) DOMAIN = "demo" DEPENDENCIES = [] COMPONENTS_WITH_DEMO_PLATFORM = [ - 'switch', 'light', 'thermostat', 'sensor', 'media_player'] + 'switch', 'light', 'thermostat', 'sensor', 'media_player', 'notify'] def setup(hass, config): @@ -29,16 +28,10 @@ def setup(hass, config): config.setdefault(ha.DOMAIN, {}) config.setdefault(DOMAIN, {}) - if config[DOMAIN].get('hide_demo_state') != '1': + if config[DOMAIN].get('hide_demo_state') != 1: hass.states.set('a.Demo_Mode', 'Enabled') # Setup sun - if CONF_LATITUDE not in config[ha.DOMAIN]: - config[ha.DOMAIN][CONF_LATITUDE] = '32.87336' - - if CONF_LONGITUDE not in config[ha.DOMAIN]: - config[ha.DOMAIN][CONF_LONGITUDE] = '-117.22743' - loader.get_component('sun').setup(hass, config) # Setup demo platforms @@ -52,18 +45,57 @@ def setup(hass, config): group.setup_group(hass, 'living room', [lights[0], lights[1], switches[0]]) group.setup_group(hass, 'bedroom', [lights[2], switches[1]]) - # Setup device tracker - hass.states.set("device_tracker.Paulus", "home", + # Setup scripts + bootstrap.setup_component( + hass, 'script', + {'script': { + 'demo': { + 'alias': 'Demo {}'.format(lights[0]), + 'sequence': [{ + 'execute_service': 'light.turn_off', + 'service_data': {ATTR_ENTITY_ID: lights[0]} + }, { + 'delay': {'seconds': 5} + }, { + 'execute_service': 'light.turn_on', + 'service_data': {ATTR_ENTITY_ID: lights[0]} + }, { + 'delay': {'seconds': 5} + }, { + 'execute_service': 'light.turn_off', + 'service_data': {ATTR_ENTITY_ID: lights[0]} + }] + }}}) + + # Setup scenes + bootstrap.setup_component( + hass, 'scene', + {'scene': [ + {'name': 'Romantic lights', + 'entities': { + lights[0]: True, + lights[1]: {'state': 'on', 'xy_color': [0.33, 0.66], + 'brightness': 200}, + }}, + {'name': 'Switch on and off', + 'entities': { + switches[0]: True, + switches[1]: False, + }}, + ]}) + + # Setup fake device tracker + hass.states.set("device_tracker.paulus", "home", {ATTR_ENTITY_PICTURE: "http://graph.facebook.com/schoutsen/picture"}) - hass.states.set("device_tracker.Anne_Therese", "not_home", + hass.states.set("device_tracker.anne_therese", "not_home", {ATTR_ENTITY_PICTURE: "http://graph.facebook.com/anne.t.frederiksen/picture"}) hass.states.set("group.all_devices", "home", { "auto": True, - "entity_id": [ + ATTR_ENTITY_ID: [ "device_tracker.Paulus", "device_tracker.Anne_Therese" ] diff --git a/homeassistant/components/device_sun_light_trigger.py b/homeassistant/components/device_sun_light_trigger.py index 8def4079d05..4740336767f 100644 --- a/homeassistant/components/device_sun_light_trigger.py +++ b/homeassistant/components/device_sun_light_trigger.py @@ -153,7 +153,7 @@ def setup(hass, config): logger.info( "Everyone has left but there are lights on. Turning them off") - light.turn_off(hass) + light.turn_off(hass, light_ids) # Track home coming of each device hass.states.track_change( diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 4ab72eaba6b..ac0c8d483ff 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -179,7 +179,7 @@ class DeviceTracker(object): # Write new devices to known devices file if not self.invalid_known_devices_file: - known_dev_path = self.hass.get_config_path(KNOWN_DEVICES_FILE) + known_dev_path = self.hass.config.path(KNOWN_DEVICES_FILE) try: # If file does not exist we will write the header too @@ -214,7 +214,7 @@ class DeviceTracker(object): # pylint: disable=too-many-branches def _read_known_devices_file(self): """ Parse and process the known devices file. """ - known_dev_path = self.hass.get_config_path(KNOWN_DEVICES_FILE) + known_dev_path = self.hass.config.path(KNOWN_DEVICES_FILE) # Return if no known devices file exists if not os.path.isfile(known_dev_path): @@ -236,7 +236,7 @@ class DeviceTracker(object): try: for row in csv.DictReader(inp): - device = row['device'] + device = row['device'].upper() if row['track'] == '1': if device in self.tracked: diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index abd2aed6957..2a9cb64f6ec 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -70,12 +70,17 @@ def setup(hass, config): def new_service_listener(service, info): """ Called when a new service is found. """ with lock: - component = SERVICE_HANDLERS.get(service) - logger.info("Found new service: %s %s", service, info) - if component and component not in hass.components: - bootstrap.setup_component(hass, component, config) + component = SERVICE_HANDLERS.get(service) + + # We do not know how to handle this service + if not component: + return + + # This component cannot be setup. + if not bootstrap.setup_component(hass, component, config): + return hass.bus.fire(EVENT_PLATFORM_DISCOVERED, { ATTR_SERVICE: service, diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index e757ac43e69..8ff722e41b2 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -22,7 +22,7 @@ _LOGGER = logging.getLogger(__name__) def setup(hass, config): """ Setup serving the frontend. """ - if 'http' not in hass.components: + if 'http' not in hass.config.components: _LOGGER.error('Dependency http is not loaded') return False diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index f809049ea45..f580952cfeb 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 = "08fb2ffccc72d7bfa0ad3478f2e8cfe7" +VERSION = "a063d1482fd49e9297d64e1329324f1c" diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index b63964b7690..aaf95520da6 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -125,8 +125,8 @@ b.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.loc +}),za=tr(function(t,e,n){Hu.call(t,n)?t[n].push(e):t[n]=[e]}),La=tr(function(t,e,n){t[n]=e}),qa=or(rn),Pa=or(on,!0),Ua=tr(function(t,e,n){t[n?0:1].push(e)},function(){return[[],[]]}),Wa=da||function(){return(new Ru).getTime()},Va=la||function(t){return g(t)&&br(t.length)&&Bu.call(t)==F||!1};Ca.dom||(vo=function(t){return t&&1===t.nodeType&&g(t)&&!Ka(t)||!1});var Ga=ga||function(t){return"number"==typeof t&&pa(t)};(wo(/x/)||sa&&!wo(sa))&&(wo=function(t){return Bu.call(t)==X});var Ka=na?function(t){if(!t||Bu.call(t)!=te)return!1;var e=t.valueOf,n=Oo(e)&&(n=na(e))&&na(n);return n?t==n||na(t)==n:Cr(t)}:Cr,$a=er(ln),Ha=_a?function(t){if(t)var e=t.constructor,n=t.length;return"function"==typeof e&&e.prototype===t||"function"!=typeof t&&n&&br(n)?Dr(t):To(t)?_a(t):[]}:Dr,Fa=er(Ln),Ba=rr(function(t,e,n){return e=e.toLowerCase(),t+(n?e.charAt(0).toUpperCase()+e.slice(1):e)}),Ja=rr(function(t,e,n){return t+(n?"-":"")+e.toLowerCase()});8!=ma(Le+"08")&&(su=function(t,e,n){return(n?Er(t,e,n):null==e)?e=0:e&&(e=+e),t=hu(t),ma(t,e||(Ne.test(t)?16:10))});var Ya=rr(function(t,e,n){return t+(n?"_":"")+e.toLowerCase()}),Xa=rr(function(t,e,n){return t+(n?" ":"")+(e.charAt(0).toUpperCase()+e.slice(1))});return n.prototype=e.prototype,ne.prototype["delete"]=ie,ne.prototype.get=Ge,ne.prototype.has=Ke,ne.prototype.set=$e,He.prototype.push=Je,no.Cache=ne,e.after=Gi,e.ary=Ki,e.assign=$a,e.at=Ti,e.before=$i,e.bind=Hi,e.bindAll=Fi,e.bindKey=Bi,e.callback=mu,e.chain=_i,e.chunk=Mr,e.compact=kr,e.constant=wu,e.countBy=ja,e.create=Mo,e.curry=Ji,e.curryRight=Yi,e.debounce=Xi,e.defaults=ko,e.defer=Zi,e.delay=Qi,e.difference=jr,e.drop=zr,e.dropRight=Lr,e.dropRightWhile=qr,e.dropWhile=Pr,e.filter=Oi,e.flatten=Gr,e.flattenDeep=Kr,e.flow=to,e.flowRight=eo,e.forEach=Ni,e.forEachRight=Ci,e.forIn=Lo,e.forInRight=qo,e.forOwn=Po,e.forOwnRight=Uo,e.functions=Wo,e.groupBy=za,e.indexBy=La,e.initial=Hr,e.intersection=Fr,e.invert=Go,e.invoke=Di,e.keys=Ha,e.keysIn=Ko,e.map=xi,e.mapValues=$o,e.matches=Eu,e.memoize=no,e.merge=Fa,e.mixin=bu,e.negate=ro,e.omit=Ho,e.once=io,e.pairs=Fo,e.partial=oo,e.partialRight=uo,e.partition=Ua,e.pick=Bo,e.pluck=Ri,e.property=Su,e.propertyOf=Au,e.pull=Yr,e.pullAt=Xr,e.range=Nu,e.rearg=ao,e.reject=ji,e.remove=Zr,e.rest=Qr,e.shuffle=Li,e.slice=ti,e.sortBy=Ui,e.sortByAll=Wi,e.take=ri,e.takeRight=ii,e.takeRightWhile=oi,e.takeWhile=ui,e.tap=vi,e.throttle=so,e.thru=yi,e.times=Cu,e.toArray=xo,e.toPlainObject=Ro,e.transform=Yo,e.union=ai,e.uniq=si,e.unzip=ci,e.values=Xo,e.valuesIn=Zo,e.where=Vi,e.without=fi,e.wrap=co,e.xor=li,e.zip=hi,e.zipObject=pi,e.backflow=eo,e.collect=xi,e.compose=eo,e.each=Ni,e.eachRight=Ci,e.extend=$a,e.iteratee=mu,e.methods=Wo,e.object=pi,e.select=Oi,e.tail=Qr,e.unique=si,bu(e,e),e.attempt=gu,e.camelCase=Ba,e.capitalize=tu,e.clone=fo,e.cloneDeep=lo,e.deburr=eu,e.endsWith=nu,e.escape=ru,e.escapeRegExp=iu,e.every=bi,e.find=Ii,e.findIndex=Ur,e.findKey=jo,e.findLast=Si,e.findLastIndex=Wr,e.findLastKey=zo,e.findWhere=Ai,e.first=Vr,e.has=Vo,e.identity=Tu,e.includes=Ei,e.indexOf=$r,e.isArguments=ho,e.isArray=Va,e.isBoolean=po,e.isDate=_o,e.isElement=vo,e.isEmpty=yo,e.isEqual=go,e.isError=mo,e.isFinite=Ga,e.isFunction=wo,e.isMatch=Eo,e.isNaN=bo,e.isNative=Oo,e.isNull=Io,e.isNumber=So,e.isObject=To,e.isPlainObject=Ka,e.isRegExp=Ao,e.isString=No,e.isTypedArray=Co,e.isUndefined=Do,e.kebabCase=Ja,e.last=Br,e.lastIndexOf=Jr,e.max=qa,e.min=Pa,e.noConflict=Ou,e.noop=Iu,e.now=Wa,e.pad=ou,e.padLeft=uu,e.padRight=au,e.parseInt=su,e.random=Qo,e.reduce=Mi,e.reduceRight=ki,e.repeat=cu,e.result=Jo,e.runInContext=I,e.size=qi,e.snakeCase=Ya,e.some=Pi,e.sortedIndex=ei,e.sortedLastIndex=ni,e.startCase=Xa,e.startsWith=fu,e.template=lu,e.trim=hu,e.trimLeft=pu,e.trimRight=_u,e.trunc=vu,e.unescape=yu,e.uniqueId=Du,e.words=du,e.all=bi,e.any=Pi,e.contains=Ei,e.detect=Ii,e.foldl=Mi,e.foldr=ki,e.head=Vr,e.include=Ei,e.inject=Mi,bu(e,function(){var t={};return Nn(e,function(n,r){e.prototype[r]||(t[r]=n)}),t}(),!1),e.sample=zi,e.prototype.sample=function(t){return this.__chain__||null!=t?this.thru(function(e){return zi(e,t)}):zi(this.value())},e.VERSION=A,Xe(["bind","bindKey","curry","curryRight","partial","partialRight"],function(t){e[t].placeholder=e}),Xe(["filter","map","takeWhile"],function(t,e){var n=e==W;r.prototype[t]=function(t,r){var i=this.clone(),o=i.filtered,u=i.iteratees||(i.iteratees=[]);return i.filtered=o||n||e==G&&i.dir<0,u.push({iteratee:_r(t,r,3),type:e}),i}}),Xe(["drop","take"],function(t,e){var n=t+"Count",i=t+"While";r.prototype[t]=function(r){r=null==r?1:va(+r||0,0);var i=this.clone();if(i.filtered){var o=i[n];i[n]=e?ya(o,r):o+r}else{var u=i.views||(i.views=[]);u.push({size:r,type:t+(i.dir<0?"Right":"")})}return i},r.prototype[t+"Right"]=function(e){return this.reverse()[t](e).reverse()},r.prototype[t+"RightWhile"]=function(t,e){return this.reverse()[i](t,e).reverse()}}),Xe(["first","last"],function(t,e){var n="take"+(e?"Right":"");r.prototype[t]=function(){return this[n](1).value()[0]}}),Xe(["initial","rest"],function(t,e){var n="drop"+(e?"":"Right");r.prototype[t]=function(){return this[n](1)}}),Xe(["pluck","where"],function(t,e){var n=e?"filter":"map",i=e?zn:Pn;r.prototype[t]=function(t){return this[n](i(e?t:t+""))}}),r.prototype.dropWhile=function(t,e){var n,r,i=this.dir<0;return t=_r(t,e,3),this.filter(function(e,o,u){return n=n&&(i?r>o:o>r),r=o,n||(n=!t(e,o,u))})},r.prototype.reject=function(t,e){return t=_r(t,e,3),this.filter(function(e,n,r){return!t(e,n,r)})},r.prototype.slice=function(t,e){t=null==t?0:+t||0;var n=0>t?this.takeRight(-t):this.drop(t);return"undefined"!=typeof e&&(e=+e||0,n=0>e?n.dropRight(-e):n.take(e-t)),n},Nn(r.prototype,function(t,i){var o=e[i],u=/^(?:first|last)$/.test(i);e.prototype[i]=function(){var i=this.__wrapped__,a=arguments,s=this.__chain__,c=!!this.__actions__.length,f=i instanceof r,l=f&&!c;if(u&&!s)return l?t.call(i):o.call(e,this.value());var h=function(t){var n=[t];return ra.apply(n,a),o.apply(e,n)};if(f||Va(i)){var p=l?i:new r(this),_=t.apply(p,a);if(!u&&(c||_.actions)){var v=_.actions||(_.actions=[]);v.push({func:yi,args:[h],thisArg:e})}return new n(_,s)}return this.thru(h)}}),Xe(["concat","join","pop","push","shift","sort","splice","unshift"],function(t){var n=Wu[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",i=/^(?:join|pop|shift)$/.test(t);e.prototype[t]=function(){var t=arguments;return i&&!this.__chain__?n.apply(this.value(),t):this[r](function(e){return n.apply(e,t)})}}),r.prototype.clone=i,r.prototype.reverse=m,r.prototype.value=Z,e.prototype.chain=di,e.prototype.reverse=gi,e.prototype.toString=mi,e.prototype.toJSON=e.prototype.valueOf=e.prototype.value=wi,e.prototype.collect=e.prototype.map,e.prototype.head=e.prototype.first,e.prototype.select=e.prototype.filter,e.prototype.tail=e.prototype.rest,e}var S,A="3.1.0",N=1,C=2,D=4,x=8,R=16,M=32,k=64,j=128,z=256,L=30,q="...",P=150,U=16,W=0,V=1,G=2,K="Expected a function",$="__lodash_placeholder__",H="[object Arguments]",F="[object Array]",B="[object Boolean]",J="[object Date]",Y="[object Error]",X="[object Function]",Z="[object Map]",Q="[object Number]",te="[object Object]",ee="[object RegExp]",ne="[object Set]",re="[object String]",ie="[object WeakMap]",oe="[object ArrayBuffer]",ue="[object Float32Array]",ae="[object Float64Array]",se="[object Int8Array]",ce="[object Int16Array]",fe="[object Int32Array]",le="[object Uint8Array]",he="[object Uint8ClampedArray]",pe="[object Uint16Array]",_e="[object Uint32Array]",ve=/\b__p \+= '';/g,ye=/\b(__p \+=) '' \+/g,de=/(__e\(.*?\)|\b__t\)) \+\n'';/g,ge=/&(?:amp|lt|gt|quot|#39|#96);/g,me=/[&<>"'`]/g,we=RegExp(ge.source),Te=RegExp(me.source),Ee=/<%-([\s\S]+?)%>/g,be=/<%([\s\S]+?)%>/g,Oe=/<%=([\s\S]+?)%>/g,Ie=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Se=/\w*$/,Ae=/^\s*function[ \n\r\t]+\w/,Ne=/^0[xX]/,Ce=/^\[object .+?Constructor\]$/,De=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,xe=/($^)/,Re=/[.*+?^${}()|[\]\/\\]/g,Me=RegExp(Re.source),ke=/\bthis\b/,je=/['\n\r\u2028\u2029\\]/g,ze=function(){var t="[A-Z\\xc0-\\xd6\\xd8-\\xde]",e="[a-z\\xdf-\\xf6\\xf8-\\xff]+";return RegExp(t+"{2,}(?="+t+e+")|"+t+"?"+e+"|"+t+"+|[0-9]+","g")}(),Le=" \f \n\r\u2028\u2029 ᠎              ",qe=["Array","ArrayBuffer","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Math","Number","Object","RegExp","Set","String","_","clearTimeout","document","isFinite","parseInt","setTimeout","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","window","WinRTError"],Pe=-1,Ue={};Ue[ue]=Ue[ae]=Ue[se]=Ue[ce]=Ue[fe]=Ue[le]=Ue[he]=Ue[pe]=Ue[_e]=!0,Ue[H]=Ue[F]=Ue[oe]=Ue[B]=Ue[J]=Ue[Y]=Ue[X]=Ue[Z]=Ue[Q]=Ue[te]=Ue[ee]=Ue[ne]=Ue[re]=Ue[ie]=!1;var We={};We[H]=We[F]=We[oe]=We[B]=We[J]=We[ue]=We[ae]=We[se]=We[ce]=We[fe]=We[Q]=We[te]=We[ee]=We[re]=We[le]=We[he]=We[pe]=We[_e]=!0,We[Y]=We[X]=We[Z]=We[ne]=We[ie]=!1;var Ve={leading:!1,maxWait:0,trailing:!1},Ge={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"},Ke={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},$e={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},He={"function":!0,object:!0},Fe={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Be=He[typeof window]&&window!==(this&&this.window)?window:this,Je=He[typeof e]&&e&&!e.nodeType&&e,Ye=He[typeof t]&&t&&!t.nodeType&&t,Xe=Je&&Ye&&"object"==typeof i&&i;!Xe||Xe.global!==Xe&&Xe.window!==Xe&&Xe.self!==Xe||(Be=Xe);var Ze=(Ye&&Ye.exports===Je&&Je,I());Be._=Ze,r=function(){return Ze}.call(e,n,e,t),!(r!==S&&(t.exports=r))}).call(this)}).call(e,n(35)(t),function(){return this}())},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=r(n(1)),s=r(n(2)),c=r(n(3)),f=!1,l=!1,h="",p=!1,_="",v=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{isValidating:{get:function(){return f},configurable:!0},isLoggedIn:{get:function(){return l},configurable:!0},authToken:{get:function(){return h},configurable:!0},lastAttemptInvalid:{get:function(){return p},configurable:!0},lastAttemptMessage:{get:function(){return _},configurable:!0}}),e}(c),y=new v;y.dispatchToken=a.register(function(t){switch(t.actionType){case s.ACTION_VALIDATING_AUTH_TOKEN:f=!0,y.emitChange();break;case s.ACTION_VALID_AUTH_TOKEN:f=!1,l=!0,h=t.authToken,p=!1,_="",y.emitChange();break;case s.ACTION_INVALID_AUTH_TOKEN:f=!1,l=!1,h="",p=!0,_=t.message||"Unexpected result from API",y.emitChange();break;case s.ACTION_LOG_OUT:f=!1,l=!1,h="",p=!1,_="",y.emitChange()}}),t.exports=y},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=n(5),s=a.Map,c=a.List,f=r(n(1)),l=r(n(2)),h=r(n(3)),p=new s,_=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{all:{get:function(){return p},configurable:!0},has:{value:function(t,e){var t=p.get(t);return t&&t.contains(e)},writable:!0,configurable:!0},getServices:{value:function(t){return p.get(t)||new c},writable:!0,configurable:!0}}),e}(h),v=new _;v.dispatchToken=f.register(function(t){switch(t.actionType){case l.ACTION_NEW_SERVICES:p=(new s).withMutations(function(e){t.services.forEach(function(t){e.set(t.domain,new c(t.services))})}),v.emitChange();break;case l.ACTION_REMOTE_EVENT_RECEIVED:if(t.event.event_type!==l.REMOTE_EVENT_SERVICE_REGISTERED)break;var e=t.event.data,n=e.domain,r=e.service;if(v.has(n,r))break;var i=v.getServices(n);p=p.set(n,i.push(r)),v.emitChange();break;case l.ACTION_LOG_OUT:p=new s,v.emitChange()}}),t.exports=v},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=r(n(1)),s=r(n(2)),c=r(n(3)),f="STATE_CONNECTED",l="STATE_DISCONNECTED",h="STATE_ERROR",p=l,_=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{state:{get:function(){return p},configurable:!0},isStreaming:{get:function(){return p===this.STATE_CONNECTED},configurable:!0},hasError:{get:function(){return p===this.STATE_ERROR},configurable:!0}}),e}(c),v=new _;v.STATE_CONNECTED=f,v.STATE_DISCONNECTED=l,v.STATE_ERROR=h,v.dispatchToken=a.register(function(t){switch(t.actionType){case s.ACTION_STREAM_START:p=f,v.emitChange();break;case s.ACTION_STREAM_STOP:p=l,v.emitChange();break;case s.ACTION_STREAM_ERROR:p=h,v.emitChange()}}),t.exports=v},function(t,e,n){"use strict";function r(t){i.dispatch({actionType:u,message:t})}e.notify=r;var i=n(1),o=n(2),u=o.ACTION_NEW_NOTIFICATION;Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(t){t.length>0&&f.dispatch({actionType:l.ACTION_NEW_SERVICES,services:t})}function i(t){return u("homeassistant","turn_on",{entity_id:t})}function o(t){return u("homeassistant","turn_off",{entity_id:t})}function u(t,e){var n=void 0===arguments[2]?{}:arguments[2];return c("POST","services/"+t+"/"+e,n).then(function(r){h("turn_on"==e&&n.entity_id?"Turned on "+n.entity_id+".":"turn_off"==e&&n.entity_id?"Turned off "+n.entity_id+".":"Service "+t+"/"+e+" called."),p(r)})}function a(){return c("GET","services").then(r)}var s=function(t){return t&&t.__esModule?t["default"]:t};e.newServices=r,e.callTurnOn=i,e.callTurnOff=o,e.callService=u,e.fetchAll=a;var c=s(n(4)),f=s(n(1)),l=s(n(2)),h=n(10).notify,p=n(12).newStates;Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(t,e){(t.length>0||e)&&c.dispatch({actionType:f,states:t,replace:!!e})}function i(t,e){var n=void 0===arguments[2]?!1:arguments[2],i={state:e};n&&(i.attributes=n),s("POST","states/"+t,i).then(function(n){l("State of "+t+" set to "+e+"."),r([n])})}function o(t){s("GET","states/"+t).then(function(t){r([t])})}function u(){s("GET","states").then(function(t){r(t,!0)})}var a=function(t){return t&&t.__esModule?t["default"]:t};e.newStates=r,e.set=i,e.fetch=o,e.fetchAll=u;var s=a(n(4)),c=a(n(1)),f=n(2).ACTION_NEW_STATES,l=n(10).notify;Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(){c.dispatch({actionType:f.ACTION_FETCH_ALL}),l.fetchAll(),h.fetchAll(),p.fetchAll(),_.fetchAll(),y&&d()}function i(){y=!0,r()}function o(){y=!1,d.cancel()}var u=function(t){return t&&t.__esModule?t:{"default":t}},a=function(t){return t&&t.__esModule?t["default"]:t};e.fetchAll=r,e.start=i,e.stop=o;var s=a(n(6)),c=a(n(1)),f=a(n(2)),l=u(n(24)),h=u(n(12)),p=u(n(11)),_=u(n(23)),v=3e4,y=!1,d=s.debounce(r,v);Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var n,r=[],i=t[Symbol.iterator]();!(n=i.next()).done&&(r.push(n.value),!e||r.length!==e););return r}throw new TypeError("Invalid attempt to destructure non-iterable instance")},o=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},u=function _(t,e,n){var r=Object.getOwnPropertyDescriptor(t,e);if(void 0===r){var i=Object.getPrototypeOf(t);return null===i?void 0:_(i,e,n)}if("value"in r&&r.writable)return r.value;var o=r.get;return void 0===o?void 0:o.call(n)},a=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},s=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},c=n(5).Record,f=r(n(8)),l=n(26).parseDateTime,h=new c({entityId:null,domain:null,object_id:null,state:null,entityDisplay:null,stateDisplay:null,lastChanged:null,lastChangedAsDate:null,attributes:{},isCustomGroup:null},"State"),p=function(t){function e(t,n,r){var o=void 0===arguments[3]?{}:arguments[3];s(this,e);var a=t.split("."),c=i(a,2),f=c[0],h=c[1],p=n.replace(/_/g," ");o.unit_of_measurement&&(p+=" "+o.unit_of_measurement),u(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,{entityId:t,domain:f,objectId:h,state:n,stateDisplay:p,lastChanged:r,attributes:o,entityDisplay:o.friendly_name||h.replace(/_/g," "),lastChangedAsDate:l(r),isCustomGroup:"group"===f&&!o.auto})}return a(e,t),o(e,{fromJSON:{value:function(t){var n=t.entity_id,r=t.state,i=t.last_changed,o=t.attributes;return new e(n,r,i,o)},writable:!0,configurable:!0}},{canToggle:{get:function(){return"group"===this.domain&&("on"===this.state||"off"===this.state)||f.has(this.domain,"turn_on")},configurable:!0}}),e}(h);t.exports=p},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=n(5).List,s=r(n(1)),c=r(n(2)),f=r(n(3)),l=new a,h=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{loaded:{get:function(){return l},configurable:!0},isLoaded:{value:function(t){return l.contains(t)},writable:!0,configurable:!0}}),e}(f),p=new h;p.dispatchToken=s.register(function(t){switch(t.actionType){case c.ACTION_NEW_LOADED_COMPONENTS:l=new a(t.components),p.emitChange();break;case c.ACTION_REMOTE_EVENT_RECEIVED:if(t.event.event_type!==c.REMOTE_EVENT_COMPONENT_LOADED)break;var e=t.event.data.component;if(p.isLoaded(e))break;l=l.push(e),p.emitChange();break;case c.ACTION_LOG_OUT:l=new a,p.emitChange()}}),t.exports=p},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=n(5).List,s=r(n(1)),c=r(n(2)),f=r(n(3)),l=new a,h=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{all:{get:function(){return l},configurable:!0}}),e}(f),p=new h;p.dispatchToken=s.register(function(t){switch(t.actionType){case c.ACTION_NEW_EVENTS:l=new a(t.events),p.emitChange();break;case c.ACTION_LOG_OUT:l=new a,p.emitChange()}}),t.exports=p},function(t,e,n){"use strict";function r(){return p.size}var i=function(t){return t&&t.__esModule?t["default"]:t},o=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},u=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},a=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},s=n(5).List,c=i(n(1)),f=i(n(2)),l=i(n(3)),h=i(n(31)),p=new s,_=function(t){function e(){a(this,e),null!=t&&t.apply(this,arguments)}return u(e,t),o(e,null,{hasNewNotifications:{value:function(t){return!t||t+1l},writable:!0,configurable:!0},get:{value:function(t){return _[t]||null},writable:!0,configurable:!0},all:{get:function(){return a.values(_)},configurable:!0}}),e}(f),y=new v;y.dispatchToken=s.register(function(t){switch(t.actionType){case c.ACTION_NEW_STATE_HISTORY:a.forEach(t.stateHistory,function(t){if(0!==t.length){var e=t[0].entityId;_[e]=t,p[e]=new Date}}),t.isFetchAll&&(h=new Date),y.emitChange();break;case c.ACTION_LOG_OUT:h=null,p={},_={},y.emitChange()}}),t.exports=y},function(t,e,n){"use strict";function r(t){return-1!==_.indexOf(t)}function i(){return _.length===h}var o=function(t){return t&&t.__esModule?t["default"]:t},u=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},a=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},s=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},c=o(n(1)),f=o(n(2)),l=o(n(3)),h=4,p=!1,_=[],v=function(t){function e(){s(this,e),null!=t&&t.apply(this,arguments)}return a(e,t),u(e,null,{isFetching:{get:function(){return!i()},configurable:!0},initialLoadDone:{get:function(){return p},configurable:!0},componentsLoaded:{get:function(){return r(f.ACTION_NEW_LOADED_COMPONENTS)},configurable:!0},eventsLoaded:{get:function(){return r(f.ACTION_NEW_EVENTS)},configurable:!0},servicesLoaded:{get:function(){return r(f.ACTION_NEW_SERVICES)},configurable:!0},statesLoaded:{get:function(){return r(f.ACTION_NEW_STATES)},configurable:!0}}),e}(l),y=new v;y.dispatchToken=c.register(function(t){switch(t.actionType){case f.ACTION_FETCH_ALL:_=[],y.emitChange();break;case f.ACTION_NEW_LOADED_COMPONENTS:case f.ACTION_NEW_EVENTS:case f.ACTION_NEW_SERVICES:case f.ACTION_NEW_STATES:r(t.actionType)||(_.push(t.actionType),p=p||i(),y.emitChange());break;case f.ACTION_LOG_OUT:p=!1,_=[],y.emitChange()}}),t.exports=y},function(t,e,n){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},o=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.__proto__=e)},u=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=r(n(1)),s=r(n(2)),c=r(n(3)),f="STATE_LISTENING",l="STATE_TRANSMITTING",h="STATE_IDLE",p="STATE_ERROR",_=h,v="",y="",d=function(t){function e(){u(this,e),null!=t&&t.apply(this,arguments)}return o(e,t),i(e,null,{state:{get:function(){return _},configurable:!0},isListening:{get:function(){return _===f},configurable:!0},isTransmitting:{get:function(){return _===l},configurable:!0},hasError:{get:function(){return _===p},configurable:!0},interimTranscript:{get:function(){return v},configurable:!0},finalTranscript:{get:function(){return y},configurable:!0}}),e}(c),g=new d;g.STATE_LISTENING=f,g.STATE_TRANSMITTING=l,g.STATE_IDLE=h,g.STATE_ERROR=p,g.dispatchToken=a.register(function(t){switch(t.actionType){case s.ACTION_LISTENING_START:_=f,v="",y="",g.emitChange();break;case s.ACTION_LISTENING_TRANSMITTING:_=l,v="",y=t.finalTranscript,g.emitChange();break;case s.ACTION_LISTENING_DONE:_=h,g.emitChange();break;case s.ACTION_LISTENING_ERROR:_=p,g.emitChange();break;case s.ACTION_LISTENING_RESULT:v=t.interimTranscript,y=t.finalTranscript,g.emitChange()}}),t.exports=g},function(t,e,n){"use strict";function r(t){a.dispatch({actionType:s.ACTION_NEW_LOADED_COMPONENTS,components:t})}function i(){return u("GET","components").then(r)}var o=function(t){return t&&t.__esModule?t["default"]:t};e.newLoaded=r,e.fetchAll=i;var u=o(n(4)),a=o(n(1)),s=o(n(2));Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(t){s.dispatch({actionType:c.ACTION_NEW_EVENTS,events:t})}function i(){a("GET","events").then(r)}function o(t){var e=void 0===arguments[1]?{}:arguments[1];return a("POST","events/"+t,e).then(function(){f("Event "+t+" successful fired!"),s.dispatch({actionType:c.ACTION_EVENT_FIRED,eventType:t,eventData:e})})}var u=function(t){return t&&t.__esModule?t["default"]:t};e.newEvents=r,e.fetchAll=i,e.fire=o;var a=u(n(4)),s=u(n(1)),c=u(n(2)),f=n(10).notify;Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(){return"EventSource"in window}function i(t){null!==p&&y();var e="/api/stream";t&&(e+="?api_password="+t),p=new EventSource(e),_=t,p.addEventListener("open",function(){v(),c.dispatch({actionType:f.ACTION_STREAM_START}),l.stop(),l.fetchAll()},!1),p.addEventListener("message",function(t){v(),"ping"!==t.data&&c.dispatch({actionType:f.ACTION_REMOTE_EVENT_RECEIVED,event:JSON.parse(t.data)})},!1),p.addEventListener("error",function(){p.readyState!==EventSource.CLOSED&&c.dispatch({actionType:f.ACTION_STREAM_ERROR})},!1)}function o(){y(),c.dispatch({actionType:f.ACTION_STREAM_STOP}),l.start()}var u=function(t){return t&&t.__esModule?t:{"default":t}},a=function(t){return t&&t.__esModule?t["default"]:t};e.isSupported=r,e.start=i,e.stop=o;var s=a(n(6)),c=a(n(1)),f=a(n(2)),l=u(n(13)),h=6e4,p=null,_=null,v=s.debounce(function(){i(_)},h),y=function(){p.close(),p=null,_=null,v.cancel()};Object.defineProperty(e,"__esModule",{value:!0})},function(t,e){"use strict";function n(t){var e=t.split(" "),n=r(e,2),i=n[0],o=n[1],u=i.split(":"),a=r(u,3),s=a[0],c=a[1],f=a[2],l=o.split("-"),h=r(l,3),p=h[0],_=h[1],v=h[2];return new Date(v,parseInt(_)-1,p,s,c,f)}var r=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var n,r=[],i=t[Symbol.iterator]();!(n=i.next()).done&&(r.push(n.value),!e||r.length!==e););return r}throw new TypeError("Invalid attempt to destructure non-iterable instance")};e.parseDateTime=n,Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(t,e){var n=e.useStreaming,r=void 0===n?l.isSupported:n,i=e.rememberLogin,o=void 0===i?!1:i;s.dispatch({actionType:c.ACTION_VALIDATING_AUTH_TOKEN}),a("GET","",!1,{authToken:t}).then(function(){s.dispatch({actionType:c.ACTION_VALID_AUTH_TOKEN,authToken:t,rememberLogin:o}),r?l.start(t):f.start()},function(t){s.dispatch({actionType:c.ACTION_INVALID_AUTH_TOKEN,message:t.message}) +})}function i(){s.dispatch({actionType:c.ACTION_LOG_OUT})}var o=function(t){return t&&t.__esModule?t:{"default":t}},u=function(t){return t&&t.__esModule?t["default"]:t};e.validate=r,e.logOut=i;var a=u(n(4)),s=u(n(1)),c=u(n(2)),f=o(n(13)),l=o(n(25));Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(t,e){(t||e.length>0)&&s.dispatch({actionType:c.ACTION_NEW_STATE_HISTORY,stateHistory:e.map(function(t){return t.map(f.fromJSON)}),isFetchAll:t})}function i(){a("GET","history/period").then(r.bind(null,!0))}function o(t){a("GET","history/period?filter_entity_id="+t).then(this.newStateHistory.bind(null,!1))}var u=function(t){return t&&t.__esModule?t["default"]:t};e.newStateHistory=r,e.fetchAll=i,e.fetch=o;var a=u(n(4)),s=u(n(1)),c=u(n(2)),f=u(n(14));Object.defineProperty(e,"__esModule",{value:!0})},function(t,e,n){"use strict";function r(){return"webkitSpeechRecognition"in window}function i(){var t=v||_;c.dispatch({actionType:f.ACTION_LISTENING_TRANSMITTING,finalTranscript:t}),l("conversation","process",{text:t}).then(function(){c.dispatch({actionType:f.ACTION_LISTENING_DONE,finalTranscript:t})},function(){c.dispatch({actionType:f.ACTION_LISTENING_ERROR})})}function o(){null!==p&&(p.onstart=null,p.onresult=null,p.onerror=null,p.onend=null,p.stop(),p=null,i()),_="",v=""}function u(){o(),window.r=p=new webkitSpeechRecognition,p.interimResults=!0,p.onstart=function(){c.dispatch({actionType:f.ACTION_LISTENING_START})},p.onresult=function(t){_="";for(var e=t.resultIndex;et||isNaN(t))throw TypeError("n must be a positive number");return this._maxListeners=t,this},e.prototype.emit=function(t){var e,r,u,a,s,c;if(this._events||(this._events={}),"error"===t&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(e=arguments[1],e instanceof Error)throw e;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[t],o(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(u=arguments.length,a=new Array(u-1),s=1;u>s;s++)a[s-1]=arguments[s];r.apply(this,a)}else if(i(r)){for(u=arguments.length,a=new Array(u-1),s=1;u>s;s++)a[s-1]=arguments[s];for(c=r.slice(),u=c.length,s=0;u>s;s++)c[s].apply(this,a)}return!0},e.prototype.addListener=function(t,r){var u;if(!n(r))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",t,n(r.listener)?r.listener:r),this._events[t]?i(this._events[t])?this._events[t].push(r):this._events[t]=[this._events[t],r]:this._events[t]=r,i(this._events[t])&&!this._events[t].warned){var u;u=o(this._maxListeners)?e.defaultMaxListeners:this._maxListeners,u&&u>0&&this._events[t].length>u&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())}return this},e.prototype.on=e.prototype.addListener,e.prototype.once=function(t,e){function r(){this.removeListener(t,r),i||(i=!0,e.apply(this,arguments))}if(!n(e))throw TypeError("listener must be a function");var i=!1;return r.listener=e,this.on(t,r),this},e.prototype.removeListener=function(t,e){var r,o,u,a;if(!n(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(r=this._events[t],u=r.length,o=-1,r===e||n(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(r)){for(a=u;a-->0;)if(r[a]===e||r[a].listener&&r[a].listener===e){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},e.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[t],n(r))this.removeListener(t,r);else for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},e.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?n(this._events[t])?[this._events[t]]:this._events[t].slice():[]},e.listenerCount=function(t,e){var r;return r=t._events&&t._events[e]?n(t._events[e])?1:t._events[e].length:0}},function(t,e,n){function r(t){return n(i(t))}function i(t){return o[t]||function(){throw new Error("Cannot find module '"+t+"'.")}()}var o={"./auth":7,"./auth.js":7,"./component":15,"./component.js":15,"./event":16,"./event.js":16,"./notification":17,"./notification.js":17,"./preference":18,"./preference.js":18,"./service":8,"./service.js":8,"./state":19,"./state.js":19,"./state_history":20,"./state_history.js":20,"./store":3,"./store.js":3,"./stream":9,"./stream.js":9,"./sync":21,"./sync.js":21,"./voice":22,"./voice.js":22};r.keys=function(){return Object.keys(o)},r.resolve=i,t.exports=r,r.id=37}]); - diff --git a/homeassistant/components/frontend/www_static/polymer/cards/state-card-configurator.html b/homeassistant/components/frontend/www_static/polymer/cards/state-card-configurator.html index 78b808dfb09..195a9cb1109 100644 --- a/homeassistant/components/frontend/www_static/polymer/cards/state-card-configurator.html +++ b/homeassistant/components/frontend/www_static/polymer/cards/state-card-configurator.html @@ -1,23 +1,11 @@ +