diff --git a/.coveragerc b/.coveragerc index 8f12390556c..80bc6905c21 100644 --- a/.coveragerc +++ b/.coveragerc @@ -16,6 +16,9 @@ omit = homeassistant/components/bloomsky.py homeassistant/components/*/bloomsky.py + homeassistant/components/digital_ocean.py + homeassistant/components/*/digital_ocean.py + homeassistant/components/dweet.py homeassistant/components/*/dweet.py @@ -46,6 +49,9 @@ omit = homeassistant/components/qwikswitch.py homeassistant/components/*/qwikswitch.py + homeassistant/components/rfxtrx.py + homeassistant/components/*/rfxtrx.py + homeassistant/components/rpi_gpio.py homeassistant/components/*/rpi_gpio.py @@ -77,7 +83,7 @@ omit = homeassistant/components/zigbee.py homeassistant/components/*/zigbee.py - homeassistant/components/zwave.py + homeassistant/components/zwave/* homeassistant/components/*/zwave.py homeassistant/components/enocean.py @@ -135,6 +141,7 @@ omit = homeassistant/components/device_tracker/tomato.py homeassistant/components/device_tracker/tplink.py homeassistant/components/device_tracker/ubus.py + homeassistant/components/device_tracker/volvooncall.py homeassistant/components/discovery.py homeassistant/components/downloader.py homeassistant/components/fan/mqtt.py @@ -213,6 +220,7 @@ omit = homeassistant/components/sensor/bom.py homeassistant/components/sensor/coinmarketcap.py homeassistant/components/sensor/cpuspeed.py + homeassistant/components/sensor/darksky.py homeassistant/components/sensor/deutsche_bahn.py homeassistant/components/sensor/dht.py homeassistant/components/sensor/dte_energy_bridge.py @@ -222,7 +230,6 @@ omit = homeassistant/components/sensor/fastdotcom.py homeassistant/components/sensor/fitbit.py homeassistant/components/sensor/fixer.py - homeassistant/components/sensor/forecast.py homeassistant/components/sensor/fritzbox_callmonitor.py homeassistant/components/sensor/glances.py homeassistant/components/sensor/google_travel_time.py @@ -255,17 +262,20 @@ omit = homeassistant/components/sensor/swiss_hydrological_data.py homeassistant/components/sensor/swiss_public_transport.py homeassistant/components/sensor/systemmonitor.py + homeassistant/components/sensor/ted5000.py homeassistant/components/sensor/temper.py homeassistant/components/sensor/time_date.py homeassistant/components/sensor/torque.py homeassistant/components/sensor/transmission.py homeassistant/components/sensor/twitch.py homeassistant/components/sensor/uber.py + homeassistant/components/sensor/vasttrafik.py homeassistant/components/sensor/worldclock.py homeassistant/components/sensor/xbox_live.py homeassistant/components/sensor/yahoo_finance.py homeassistant/components/sensor/yweather.py homeassistant/components/switch/acer_projector.py + homeassistant/components/switch/anel_pwrctrl.py homeassistant/components/switch/arest.py homeassistant/components/switch/dlink.py homeassistant/components/switch/edimax.py diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 72586cc4f21..998905c929b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,7 @@ If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [home-assistant.io](https://github.com/home-assistant/home-assistant.io) -If code communicates with devices, web services, or a: +If the code communicates with devices, web services, or third-party tools: - [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass** - [ ] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]). - [ ] New dependencies are only imported inside functions that use them ([example][ex-import]). diff --git a/docs/source/conf.py b/docs/source/conf.py index 18b14795caa..bcb2699f57b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -340,8 +340,8 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Home-Assistant.tex', 'Home-Assistant Documentation', - 'Home-Assistant Team', 'manual'), + (master_doc, 'home-assistant.tex', 'Home Assistant Documentation', + 'Home Assistant Team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -382,7 +382,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'home-assistant', 'Home-Assistant Documentation', + (master_doc, 'home-assistant', 'Home Assistant Documentation', [author], 1) ] @@ -397,8 +397,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Home-Assistant', 'Home-Assistant Documentation', - author, 'Home-Assistant', 'One line description of project.', + (master_doc, 'Home-Assistant', 'Home Assistant Documentation', + author, 'Home Assistant', 'Open-source home automation platform.', 'Miscellaneous'), ] diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index b65516130d9..355e19f7fa0 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -4,6 +4,7 @@ Allow to setup simple automation rules via the config file. For more details about this component, please refer to the documentation at https://home-assistant.io/components/automation/ """ +import asyncio from functools import partial import logging import os @@ -23,12 +24,15 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.loader import get_platform from homeassistant.util.dt import utcnow import homeassistant.helpers.config_validation as cv +from homeassistant.util.async import run_coroutine_threadsafe DOMAIN = 'automation' ENTITY_ID_FORMAT = DOMAIN + '.{}' DEPENDENCIES = ['group'] +GROUP_NAME_ALL_AUTOMATIONS = 'all automations' + CONF_ALIAS = 'alias' CONF_HIDE_ENTITY = 'hide_entity' @@ -36,6 +40,7 @@ CONF_CONDITION = 'condition' CONF_ACTION = 'action' CONF_TRIGGER = 'trigger' CONF_CONDITION_TYPE = 'condition_type' +CONF_INITIAL_STATE = 'initial_state' CONDITION_USE_TRIGGER_VALUES = 'use_trigger_values' CONDITION_TYPE_AND = 'and' @@ -43,9 +48,7 @@ CONDITION_TYPE_OR = 'or' DEFAULT_CONDITION_TYPE = CONDITION_TYPE_AND DEFAULT_HIDE_ENTITY = False - -METHOD_TRIGGER = 'trigger' -METHOD_IF_ACTION = 'if_action' +DEFAULT_INITIAL_STATE = True ATTR_LAST_TRIGGERED = 'last_triggered' ATTR_VARIABLES = 'variables' @@ -55,21 +58,14 @@ SERVICE_RELOAD = 'reload' _LOGGER = logging.getLogger(__name__) -def _platform_validator(method, schema): - """Generate platform validator for different steps.""" - def validator(config): - """Validate it is a valid platform.""" - platform = get_platform(DOMAIN, config[CONF_PLATFORM]) +def _platform_validator(config): + """Validate it is a valid platform.""" + platform = get_platform(DOMAIN, config[CONF_PLATFORM]) - if not hasattr(platform, method): - raise vol.Invalid('invalid method platform') + if not hasattr(platform, 'TRIGGER_SCHEMA'): + return config - if not hasattr(platform, schema): - return config - - return getattr(platform, schema)(config) - - return validator + return getattr(platform, 'TRIGGER_SCHEMA')(config) _TRIGGER_SCHEMA = vol.All( cv.ensure_list, @@ -78,33 +74,19 @@ _TRIGGER_SCHEMA = vol.All( vol.Schema({ vol.Required(CONF_PLATFORM): cv.platform_validator(DOMAIN) }, extra=vol.ALLOW_EXTRA), - _platform_validator(METHOD_TRIGGER, 'TRIGGER_SCHEMA') + _platform_validator ), ] ) -_CONDITION_SCHEMA = vol.Any( - CONDITION_USE_TRIGGER_VALUES, - vol.All( - cv.ensure_list, - [ - vol.All( - vol.Schema({ - CONF_PLATFORM: str, - CONF_CONDITION: str, - }, extra=vol.ALLOW_EXTRA), - cv.has_at_least_one_key(CONF_PLATFORM, CONF_CONDITION), - ), - ] - ) -) +_CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA]) PLATFORM_SCHEMA = vol.Schema({ CONF_ALIAS: cv.string, + vol.Optional(CONF_INITIAL_STATE, + default=DEFAULT_INITIAL_STATE): cv.boolean, vol.Optional(CONF_HIDE_ENTITY, default=DEFAULT_HIDE_ENTITY): cv.boolean, vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA, - vol.Required(CONF_CONDITION_TYPE, default=DEFAULT_CONDITION_TYPE): - vol.All(vol.Lower, vol.Any(CONDITION_TYPE_AND, CONDITION_TYPE_OR)), vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA, vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA, }) @@ -163,9 +145,11 @@ def reload(hass): def setup(hass, config): """Setup the automation.""" - component = EntityComponent(_LOGGER, DOMAIN, hass) + component = EntityComponent(_LOGGER, DOMAIN, hass, + group_name=GROUP_NAME_ALL_AUTOMATIONS) - success = _process_config(hass, config, component) + success = run_coroutine_threadsafe( + _async_process_config(hass, config, component), hass.loop).result() if not success: return False @@ -173,22 +157,37 @@ def setup(hass, config): descriptions = conf_util.load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) + @asyncio.coroutine def trigger_service_handler(service_call): """Handle automation triggers.""" for entity in component.extract_from_service(service_call): - entity.trigger(service_call.data.get(ATTR_VARIABLES)) + hass.loop.create_task(entity.async_trigger( + service_call.data.get(ATTR_VARIABLES), True)) - def service_handler(service_call): - """Handle automation service calls.""" + @asyncio.coroutine + def turn_onoff_service_handler(service_call): + """Handle automation turn on/off service calls.""" + method = 'async_{}'.format(service_call.service) for entity in component.extract_from_service(service_call): - getattr(entity, service_call.service)() + hass.loop.create_task(getattr(entity, method)()) + @asyncio.coroutine + def toggle_service_handler(service_call): + """Handle automation toggle service calls.""" + for entity in component.extract_from_service(service_call): + if entity.is_on: + hass.loop.create_task(entity.async_turn_off()) + else: + hass.loop.create_task(entity.async_turn_on()) + + @asyncio.coroutine def reload_service_handler(service_call): """Remove all automations and load new ones from config.""" - conf = component.prepare_reload() + conf = yield from hass.loop.run_in_executor( + None, component.prepare_reload) if conf is None: return - _process_config(hass, conf, component) + hass.loop.create_task(_async_process_config(hass, conf, component)) hass.services.register(DOMAIN, SERVICE_TRIGGER, trigger_service_handler, descriptions.get(SERVICE_TRIGGER), @@ -198,8 +197,12 @@ def setup(hass, config): descriptions.get(SERVICE_RELOAD), schema=RELOAD_SERVICE_SCHEMA) - for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE): - hass.services.register(DOMAIN, service, service_handler, + hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service_handler, + descriptions.get(SERVICE_TOGGLE), + schema=SERVICE_SCHEMA) + + for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF): + hass.services.register(DOMAIN, service, turn_onoff_service_handler, descriptions.get(service), schema=SERVICE_SCHEMA) @@ -209,15 +212,17 @@ def setup(hass, config): class AutomationEntity(ToggleEntity): """Entity to show status of entity.""" + # pylint: disable=abstract-method # pylint: disable=too-many-arguments, too-many-instance-attributes - def __init__(self, name, attach_triggers, cond_func, action, hidden): + def __init__(self, name, async_attach_triggers, cond_func, async_action, + hidden): """Initialize an automation entity.""" self._name = name - self._attach_triggers = attach_triggers - self._detach_triggers = attach_triggers(self.trigger) + self._async_attach_triggers = async_attach_triggers + self._async_detach_triggers = None self._cond_func = cond_func - self._action = action - self._enabled = True + self._async_action = async_action + self._enabled = False self._last_triggered = None self._hidden = hidden @@ -248,41 +253,65 @@ class AutomationEntity(ToggleEntity): """Return True if entity is on.""" return self._enabled - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" + @asyncio.coroutine + def async_turn_on(self, **kwargs) -> None: + """Turn the entity on and update the state.""" if self._enabled: return - self._detach_triggers = self._attach_triggers(self.trigger) - self._enabled = True - self.update_ha_state() + yield from self.async_enable() + self.hass.loop.create_task(self.async_update_ha_state()) - def turn_off(self, **kwargs) -> None: + @asyncio.coroutine + def async_turn_off(self, **kwargs) -> None: """Turn the entity off.""" if not self._enabled: return - self._detach_triggers() - self._detach_triggers = None + self._async_detach_triggers() + self._async_detach_triggers = None self._enabled = False - self.update_ha_state() + self.hass.loop.create_task(self.async_update_ha_state()) - def trigger(self, variables): - """Trigger automation.""" - if self._cond_func(variables): - self._action(variables) + @asyncio.coroutine + def async_trigger(self, variables, skip_condition=False): + """Trigger automation. + + This method is a coroutine. + """ + if skip_condition or self._cond_func(variables): + yield from self._async_action(variables) self._last_triggered = utcnow() - self.update_ha_state() + self.hass.loop.create_task(self.async_update_ha_state()) def remove(self): """Remove automation from HASS.""" - self.turn_off() + run_coroutine_threadsafe(self.async_turn_off(), + self.hass.loop).result() super().remove() + @asyncio.coroutine + def async_enable(self): + """Enable this automation entity. -def _process_config(hass, config, component): - """Process config and add automations.""" - success = False + This method is a coroutine. + """ + if self._enabled: + return + + self._async_detach_triggers = yield from self._async_attach_triggers( + self.async_trigger) + self._enabled = True + + +@asyncio.coroutine +def _async_process_config(hass, config, component): + """Process config and add automations. + + This method is a coroutine. + """ + entities = [] + tasks = [] for config_key in extract_domain_configs(config, DOMAIN): conf = config[config_key] @@ -293,10 +322,11 @@ def _process_config(hass, config, component): hidden = config_block[CONF_HIDE_ENTITY] - action = _get_action(hass, config_block.get(CONF_ACTION, {}), name) + action = _async_get_action(hass, config_block.get(CONF_ACTION, {}), + name) if CONF_CONDITION in config_block: - cond_func = _process_if(hass, config, config_block) + cond_func = _async_process_if(hass, config, config_block) if cond_func is None: continue @@ -305,101 +335,78 @@ def _process_config(hass, config, component): """Condition will always pass.""" return True - attach_triggers = partial(_process_trigger, hass, config, - config_block.get(CONF_TRIGGER, []), name) - entity = AutomationEntity(name, attach_triggers, cond_func, action, - hidden) - component.add_entities((entity,)) - success = True + async_attach_triggers = partial( + _async_process_trigger, hass, config, + config_block.get(CONF_TRIGGER, []), name) + entity = AutomationEntity(name, async_attach_triggers, cond_func, + action, hidden) + if config_block[CONF_INITIAL_STATE]: + tasks.append(hass.loop.create_task(entity.async_enable())) + entities.append(entity) - return success + yield from asyncio.gather(*tasks, loop=hass.loop) + yield from hass.loop.run_in_executor( + None, component.add_entities, entities) + + return len(entities) > 0 -def _get_action(hass, config, name): +def _async_get_action(hass, config, name): """Return an action based on a configuration.""" script_obj = script.Script(hass, config, name) + @asyncio.coroutine def action(variables=None): """Action to be executed.""" _LOGGER.info('Executing %s', name) - logbook.log_entry(hass, name, 'has been triggered', DOMAIN) - script_obj.run(variables) + logbook.async_log_entry(hass, name, 'has been triggered', DOMAIN) + hass.loop.create_task(script_obj.async_run(variables)) return action -def _process_if(hass, config, p_config): +def _async_process_if(hass, config, p_config): """Process if checks.""" - cond_type = p_config.get(CONF_CONDITION_TYPE, - DEFAULT_CONDITION_TYPE).lower() - - # Deprecated since 0.19 - 5/5/2016 - if cond_type != DEFAULT_CONDITION_TYPE: - _LOGGER.warning('Using condition_type: "or" is deprecated. Please use ' - '"condition: or" instead.') - if_configs = p_config.get(CONF_CONDITION) - use_trigger = if_configs == CONDITION_USE_TRIGGER_VALUES - - if use_trigger: - if_configs = p_config[CONF_TRIGGER] checks = [] for if_config in if_configs: - # Deprecated except for used by use_trigger_values - # since 0.19 - 5/5/2016 - if CONF_PLATFORM in if_config: - if not use_trigger: - _LOGGER.warning("Please switch your condition configuration " - "to use 'condition' instead of 'platform'.") - if_config = dict(if_config) - if_config[CONF_CONDITION] = if_config.pop(CONF_PLATFORM) - - # To support use_trigger_values with state trigger accepting - # multiple entity_ids to monitor. - if_entity_id = if_config.get(ATTR_ENTITY_ID) - if isinstance(if_entity_id, list) and len(if_entity_id) == 1: - if_config[ATTR_ENTITY_ID] = if_entity_id[0] - try: - checks.append(condition.from_config(if_config)) + checks.append(condition.async_from_config(if_config, False)) except HomeAssistantError as ex: - # Invalid conditions are allowed if we base it on trigger - if use_trigger: - _LOGGER.warning('Ignoring invalid condition: %s', ex) - else: - _LOGGER.warning('Invalid condition: %s', ex) - return None + _LOGGER.warning('Invalid condition: %s', ex) + return None - if cond_type == CONDITION_TYPE_AND: - def if_action(variables=None): - """AND all conditions.""" - return all(check(hass, variables) for check in checks) - else: - def if_action(variables=None): - """OR all conditions.""" - return any(check(hass, variables) for check in checks) + def if_action(variables=None): + """AND all conditions.""" + return all(check(hass, variables) for check in checks) return if_action -def _process_trigger(hass, config, trigger_configs, name, action): - """Setup the triggers.""" +@asyncio.coroutine +def _async_process_trigger(hass, config, trigger_configs, name, action): + """Setup the triggers. + + This method is a coroutine. + """ removes = [] for conf in trigger_configs: - platform = _resolve_platform(METHOD_TRIGGER, hass, config, - conf.get(CONF_PLATFORM)) - if platform is None: - continue + platform = yield from hass.loop.run_in_executor( + None, prepare_setup_platform, hass, config, DOMAIN, + conf.get(CONF_PLATFORM)) - remove = platform.trigger(hass, conf, action) + if platform is None: + return None + + remove = platform.async_trigger(hass, conf, action) if not remove: - _LOGGER.error("Error setting up rule %s", name) + _LOGGER.error("Error setting up trigger %s", name) continue - _LOGGER.info("Initialized rule %s", name) + _LOGGER.info("Initialized trigger %s", name) removes.append(remove) if not removes: @@ -411,17 +418,3 @@ def _process_trigger(hass, config, trigger_configs, name, action): remove() return remove_triggers - - -def _resolve_platform(method, hass, config, platform): - """Find the automation platform.""" - if platform is None: - return None - platform = prepare_setup_platform(hass, config, DOMAIN, platform) - - if platform is None or not hasattr(platform, method): - _LOGGER.error("Unknown automation platform specified for %s: %s", - method, platform) - return None - - return platform diff --git a/homeassistant/components/automation/event.py b/homeassistant/components/automation/event.py index 7b77dd04627..a51f9fa8187 100644 --- a/homeassistant/components/automation/event.py +++ b/homeassistant/components/automation/event.py @@ -4,11 +4,11 @@ Offer event listening automation rules. For more details about this automation rule, please refer to the documentation at https://home-assistant.io/components/automation/#event-trigger """ -import asyncio import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import CONF_PLATFORM from homeassistant.helpers import config_validation as cv @@ -24,21 +24,21 @@ TRIGGER_SCHEMA = vol.Schema({ }) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for events based on configuration.""" event_type = config.get(CONF_EVENT_TYPE) event_data = config.get(CONF_EVENT_DATA) - @asyncio.coroutine + @callback def handle_event(event): """Listen for events and calls the action when data matches.""" if not event_data or all(val == event.data.get(key) for key, val in event_data.items()): - hass.async_add_job(action, { + hass.async_run_job(action, { 'trigger': { 'platform': 'event', 'event': event, }, }) - return hass.bus.listen(event_type, handle_event) + return hass.bus.async_listen(event_type, handle_event) diff --git a/homeassistant/components/automation/mqtt.py b/homeassistant/components/automation/mqtt.py index 6824c32bf07..39deae3d66e 100644 --- a/homeassistant/components/automation/mqtt.py +++ b/homeassistant/components/automation/mqtt.py @@ -6,6 +6,7 @@ at https://home-assistant.io/components/automation/#mqtt-trigger """ import voluptuous as vol +from homeassistant.core import callback import homeassistant.components.mqtt as mqtt from homeassistant.const import (CONF_PLATFORM, CONF_PAYLOAD) import homeassistant.helpers.config_validation as cv @@ -21,15 +22,16 @@ TRIGGER_SCHEMA = vol.Schema({ }) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" topic = config.get(CONF_TOPIC) payload = config.get(CONF_PAYLOAD) + @callback def mqtt_automation_listener(msg_topic, msg_payload, qos): """Listen for MQTT messages.""" if payload is None or payload == msg_payload: - action({ + hass.async_run_job(action, { 'trigger': { 'platform': 'mqtt', 'topic': msg_topic, @@ -38,4 +40,4 @@ def trigger(hass, config, action): } }) - return mqtt.subscribe(hass, topic, mqtt_automation_listener) + return mqtt.async_subscribe(hass, topic, mqtt_automation_listener) diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py index 168ca05b62b..9c3ac7d8396 100644 --- a/homeassistant/components/automation/numeric_state.py +++ b/homeassistant/components/automation/numeric_state.py @@ -8,10 +8,11 @@ import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import ( CONF_VALUE_TEMPLATE, CONF_PLATFORM, CONF_ENTITY_ID, CONF_BELOW, CONF_ABOVE) -from homeassistant.helpers.event import track_state_change +from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers import condition, config_validation as cv TRIGGER_SCHEMA = vol.All(vol.Schema({ @@ -25,7 +26,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({ _LOGGER = logging.getLogger(__name__) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) below = config.get(CONF_BELOW) @@ -34,7 +35,7 @@ def trigger(hass, config, action): if value_template is not None: value_template.hass = hass - # pylint: disable=unused-argument + @callback def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" if to_s is None: @@ -50,19 +51,19 @@ def trigger(hass, config, action): } # If new one doesn't match, nothing to do - if not condition.numeric_state( + if not condition.async_numeric_state( hass, to_s, below, above, value_template, variables): return # Only match if old didn't exist or existed but didn't match # Written as: skip if old one did exist and matched - if from_s is not None and condition.numeric_state( + if from_s is not None and condition.async_numeric_state( hass, from_s, below, above, value_template, variables): return variables['trigger']['from_state'] = from_s variables['trigger']['to_state'] = to_s - action(variables) + hass.async_run_job(action, variables) - return track_state_change(hass, entity_id, state_automation_listener) + return async_track_state_change(hass, entity_id, state_automation_listener) diff --git a/homeassistant/components/automation/state.py b/homeassistant/components/automation/state.py index 8e0eb5231a5..fb146991602 100644 --- a/homeassistant/components/automation/state.py +++ b/homeassistant/components/automation/state.py @@ -6,9 +6,11 @@ at https://home-assistant.io/components/automation/#state-trigger """ import voluptuous as vol +from homeassistant.core import callback import homeassistant.util.dt as dt_util from homeassistant.const import MATCH_ALL, CONF_PLATFORM -from homeassistant.helpers.event import track_state_change, track_point_in_time +from homeassistant.helpers.event import ( + async_track_state_change, async_track_point_in_utc_time) import homeassistant.helpers.config_validation as cv CONF_ENTITY_ID = "entity_id" @@ -32,22 +34,23 @@ TRIGGER_SCHEMA = vol.All( ) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) from_state = config.get(CONF_FROM, MATCH_ALL) to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL time_delta = config.get(CONF_FOR) - remove_state_for_cancel = None - remove_state_for_listener = None + async_remove_state_for_cancel = None + async_remove_state_for_listener = None + @callback def state_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" - nonlocal remove_state_for_cancel, remove_state_for_listener + nonlocal async_remove_state_for_cancel, async_remove_state_for_listener def call_action(): """Call action with right context.""" - action({ + hass.async_run_job(action, { 'trigger': { 'platform': 'state', 'entity_id': entity, @@ -61,35 +64,37 @@ def trigger(hass, config, action): call_action() return + @callback def state_for_listener(now): """Fire on state changes after a delay and calls action.""" - remove_state_for_cancel() + async_remove_state_for_cancel() call_action() + @callback def state_for_cancel_listener(entity, inner_from_s, inner_to_s): """Fire on changes and cancel for listener if changed.""" if inner_to_s.state == to_s.state: return - remove_state_for_listener() - remove_state_for_cancel() + async_remove_state_for_listener() + async_remove_state_for_cancel() - remove_state_for_listener = track_point_in_time( + async_remove_state_for_listener = async_track_point_in_utc_time( hass, state_for_listener, dt_util.utcnow() + time_delta) - remove_state_for_cancel = track_state_change( + async_remove_state_for_cancel = async_track_state_change( hass, entity, state_for_cancel_listener) - unsub = track_state_change(hass, entity_id, state_automation_listener, - from_state, to_state) + unsub = async_track_state_change( + hass, entity_id, state_automation_listener, from_state, to_state) - def remove(): - """Remove state listeners.""" + def async_remove(): + """Remove state listeners async.""" unsub() # pylint: disable=not-callable - if remove_state_for_cancel is not None: - remove_state_for_cancel() + if async_remove_state_for_cancel is not None: + async_remove_state_for_cancel() - if remove_state_for_listener is not None: - remove_state_for_listener() + if async_remove_state_for_listener is not None: + async_remove_state_for_listener() - return remove + return async_remove diff --git a/homeassistant/components/automation/sun.py b/homeassistant/components/automation/sun.py index 991f9b3b385..2baa0726813 100644 --- a/homeassistant/components/automation/sun.py +++ b/homeassistant/components/automation/sun.py @@ -9,9 +9,10 @@ import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import ( CONF_EVENT, CONF_OFFSET, CONF_PLATFORM, SUN_EVENT_SUNRISE) -from homeassistant.helpers.event import track_sunrise, track_sunset +from homeassistant.helpers.event import async_track_sunrise, async_track_sunset import homeassistant.helpers.config_validation as cv DEPENDENCIES = ['sun'] @@ -25,14 +26,15 @@ TRIGGER_SCHEMA = vol.Schema({ }) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for events based on configuration.""" event = config.get(CONF_EVENT) offset = config.get(CONF_OFFSET) + @callback def call_action(): """Call action with right context.""" - action({ + hass.async_run_job(action, { 'trigger': { 'platform': 'sun', 'event': event, @@ -42,6 +44,6 @@ def trigger(hass, config, action): # Do something to call action if event == SUN_EVENT_SUNRISE: - return track_sunrise(hass, call_action, offset) + return async_track_sunrise(hass, call_action, offset) else: - return track_sunset(hass, call_action, offset) + return async_track_sunset(hass, call_action, offset) diff --git a/homeassistant/components/automation/template.py b/homeassistant/components/automation/template.py index 1ca0c679424..90d75d0d982 100644 --- a/homeassistant/components/automation/template.py +++ b/homeassistant/components/automation/template.py @@ -4,14 +4,14 @@ Offer template automation rules. For more details about this automation rule, please refer to the documentation at https://home-assistant.io/components/automation/#template-trigger """ -import asyncio import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import CONF_VALUE_TEMPLATE, CONF_PLATFORM from homeassistant.helpers import condition -from homeassistant.helpers.event import track_state_change +from homeassistant.helpers.event import async_track_state_change import homeassistant.helpers.config_validation as cv @@ -23,7 +23,7 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema({ }) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" value_template = config.get(CONF_VALUE_TEMPLATE) value_template.hass = hass @@ -31,7 +31,7 @@ def trigger(hass, config, action): # Local variable to keep track of if the action has already been triggered already_triggered = False - @asyncio.coroutine + @callback def state_changed_listener(entity_id, from_s, to_s): """Listen for state changes and calls action.""" nonlocal already_triggered @@ -40,7 +40,7 @@ def trigger(hass, config, action): # Check to see if template returns true if template_result and not already_triggered: already_triggered = True - hass.async_add_job(action, { + hass.async_run_job(action, { 'trigger': { 'platform': 'template', 'entity_id': entity_id, @@ -51,5 +51,5 @@ def trigger(hass, config, action): elif not template_result: already_triggered = False - return track_state_change(hass, value_template.extract_entities(), - state_changed_listener) + return async_track_state_change(hass, value_template.extract_entities(), + state_changed_listener) diff --git a/homeassistant/components/automation/time.py b/homeassistant/components/automation/time.py index 0732e2b212c..d0315f26de0 100644 --- a/homeassistant/components/automation/time.py +++ b/homeassistant/components/automation/time.py @@ -8,9 +8,10 @@ import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import CONF_AFTER, CONF_PLATFORM from homeassistant.helpers import config_validation as cv -from homeassistant.helpers.event import track_time_change +from homeassistant.helpers.event import async_track_time_change CONF_HOURS = "hours" CONF_MINUTES = "minutes" @@ -28,7 +29,7 @@ TRIGGER_SCHEMA = vol.All(vol.Schema({ CONF_SECONDS, CONF_AFTER)) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" if CONF_AFTER in config: after = config.get(CONF_AFTER) @@ -38,14 +39,15 @@ def trigger(hass, config, action): minutes = config.get(CONF_MINUTES) seconds = config.get(CONF_SECONDS) + @callback def time_automation_listener(now): """Listen for time changes and calls action.""" - action({ + hass.async_run_job(action, { 'trigger': { 'platform': 'time', 'now': now, }, }) - return track_time_change(hass, time_automation_listener, - hour=hours, minute=minutes, second=seconds) + return async_track_time_change(hass, time_automation_listener, + hour=hours, minute=minutes, second=seconds) diff --git a/homeassistant/components/automation/zone.py b/homeassistant/components/automation/zone.py index ec948684805..935dc3cf24c 100644 --- a/homeassistant/components/automation/zone.py +++ b/homeassistant/components/automation/zone.py @@ -6,9 +6,10 @@ at https://home-assistant.io/components/automation/#zone-trigger """ import voluptuous as vol +from homeassistant.core import callback from homeassistant.const import ( CONF_EVENT, CONF_ENTITY_ID, CONF_ZONE, MATCH_ALL, CONF_PLATFORM) -from homeassistant.helpers.event import track_state_change +from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers import ( condition, config_validation as cv, location) @@ -25,12 +26,13 @@ TRIGGER_SCHEMA = vol.Schema({ }) -def trigger(hass, config, action): +def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) zone_entity_id = config.get(CONF_ZONE) event = config.get(CONF_EVENT) + @callback def zone_automation_listener(entity, from_s, to_s): """Listen for state changes and calls action.""" if from_s and not location.has_location(from_s) or \ @@ -47,7 +49,7 @@ def trigger(hass, config, action): # pylint: disable=too-many-boolean-expressions if event == EVENT_ENTER and not from_match and to_match or \ event == EVENT_LEAVE and from_match and not to_match: - action({ + hass.async_run_job(action, { 'trigger': { 'platform': 'zone', 'entity_id': entity, @@ -58,5 +60,5 @@ def trigger(hass, config, action): }, }) - return track_state_change(hass, entity_id, zone_automation_listener, - MATCH_ALL, MATCH_ALL) + return async_track_state_change(hass, entity_id, zone_automation_listener, + MATCH_ALL, MATCH_ALL) diff --git a/homeassistant/components/binary_sensor/arest.py b/homeassistant/components/binary_sensor/arest.py index 56362611514..02f9d75c404 100644 --- a/homeassistant/components/binary_sensor/arest.py +++ b/homeassistant/components/binary_sensor/arest.py @@ -1,5 +1,5 @@ """ -Support for exposed aREST RESTful API of a device. +Support for an exposed aREST RESTful API of a device. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.arest/ @@ -8,31 +8,32 @@ import logging from datetime import timedelta import requests +import voluptuous as vol from homeassistant.components.binary_sensor import ( - BinarySensorDevice, SENSOR_CLASSES) -from homeassistant.const import CONF_RESOURCE, CONF_PIN + BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) +from homeassistant.const import ( + CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS) from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_NAME): cv.string, + vol.Required(CONF_PIN): cv.string, + vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the aREST binary sensor.""" resource = config.get(CONF_RESOURCE) pin = config.get(CONF_PIN) - - sensor_class = config.get('sensor_class') - if sensor_class not in SENSOR_CLASSES: - _LOGGER.warning('Unknown sensor class: %s', sensor_class) - sensor_class = None - - if None in (resource, pin): - _LOGGER.error('Not all required config keys present: %s', - ', '.join((CONF_RESOURCE, CONF_PIN))) - return False + sensor_class = config.get(CONF_SENSOR_CLASS) try: response = requests.get(resource, timeout=10).json() @@ -49,11 +50,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): arest = ArestData(resource, pin) add_devices([ArestBinarySensor( - arest, - resource, - config.get('name', response['name']), - sensor_class, - pin)]) + arest, resource, config.get(CONF_NAME, response[CONF_NAME]), + sensor_class, pin)]) # pylint: disable=too-many-instance-attributes, too-many-arguments diff --git a/homeassistant/components/binary_sensor/digital_ocean.py b/homeassistant/components/binary_sensor/digital_ocean.py new file mode 100644 index 00000000000..821acb2da95 --- /dev/null +++ b/homeassistant/components/binary_sensor/digital_ocean.py @@ -0,0 +1,91 @@ +""" +Support for monitoring the state of Digital Ocean droplets. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.digital_ocean/ +""" +import logging + +import voluptuous as vol + +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, PLATFORM_SCHEMA) +from homeassistant.components.digital_ocean import ( + CONF_DROPLETS, ATTR_CREATED_AT, ATTR_DROPLET_ID, ATTR_DROPLET_NAME, + ATTR_FEATURES, ATTR_IPV4_ADDRESS, ATTR_IPV6_ADDRESS, ATTR_MEMORY, + ATTR_REGION, ATTR_VCPUS) +from homeassistant.loader import get_component +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'Droplet' +DEFAULT_SENSOR_CLASS = 'motion' +DEPENDENCIES = ['digital_ocean'] + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DROPLETS): vol.All(cv.ensure_list, [cv.string]), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Digital Ocean droplet sensor.""" + digital_ocean = get_component('digital_ocean') + droplets = config.get(CONF_DROPLETS) + + dev = [] + for droplet in droplets: + droplet_id = digital_ocean.DIGITAL_OCEAN.get_droplet_id(droplet) + dev.append(DigitalOceanBinarySensor( + digital_ocean.DIGITAL_OCEAN, droplet_id)) + + add_devices(dev) + + +class DigitalOceanBinarySensor(BinarySensorDevice): + """Representation of a Digital Ocean droplet sensor.""" + + def __init__(self, do, droplet_id): + """Initialize a new Digital Ocean sensor.""" + self._digital_ocean = do + self._droplet_id = droplet_id + self._state = None + self.update() + + @property + def name(self): + """Return the name of the sensor.""" + return self.data.name + + @property + def is_on(self): + """Return true if the binary sensor is on.""" + return self.data.status == 'active' + + @property + def sensor_class(self): + """Return the class of this sensor.""" + return DEFAULT_SENSOR_CLASS + + @property + def state_attributes(self): + """Return the state attributes of the Digital Ocean droplet.""" + return { + ATTR_CREATED_AT: self.data.created_at, + ATTR_DROPLET_ID: self.data.id, + ATTR_DROPLET_NAME: self.data.name, + ATTR_FEATURES: self.data.features, + ATTR_IPV4_ADDRESS: self.data.ip_address, + ATTR_IPV6_ADDRESS: self.data.ip_v6_address, + ATTR_MEMORY: self.data.memory, + ATTR_REGION: self.data.region['name'], + ATTR_VCPUS: self.data.vcpus, + } + + def update(self): + """Update state of sensor.""" + self._digital_ocean.update() + + for droplet in self._digital_ocean.data: + if droplet.id == self._droplet_id: + self.data = droplet diff --git a/homeassistant/components/binary_sensor/homematic.py b/homeassistant/components/binary_sensor/homematic.py index 073f5d7eb6d..35550d15bc8 100644 --- a/homeassistant/components/binary_sensor/homematic.py +++ b/homeassistant/components/binary_sensor/homematic.py @@ -16,6 +16,7 @@ DEPENDENCIES = ['homematic'] SENSOR_TYPES_CLASS = { "Remote": None, "ShutterContact": "opening", + "IPShutterContact": "opening", "Smoke": "smoke", "SmokeV2": "smoke", "Motion": "motion", diff --git a/homeassistant/components/binary_sensor/nx584.py b/homeassistant/components/binary_sensor/nx584.py index 6a287599e69..e158da02f2b 100644 --- a/homeassistant/components/binary_sensor/nx584.py +++ b/homeassistant/components/binary_sensor/nx584.py @@ -1,41 +1,56 @@ """ -Support for exposing nx584 elements as sensors. +Support for exposing NX584 elements as sensors. For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.nx584/ +https://home-assistant.io/components/binary_sensor.nx584/ """ import logging import threading import time import requests +import voluptuous as vol from homeassistant.components.binary_sensor import ( - SENSOR_CLASSES, BinarySensorDevice) + SENSOR_CLASSES, BinarySensorDevice, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_HOST, CONF_PORT) +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['pynx584==0.2'] + _LOGGER = logging.getLogger(__name__) +CONF_EXCLUDE_ZONES = 'exclude_zones' +CONF_ZONE_TYPES = 'zone_types' + +DEFAULT_HOST = 'localhost' +DEFAULT_PORT = '5007' +DEFAULT_SSL = False + +ZONE_TYPES_SCHEMA = vol.Schema({ + cv.positive_int: vol.In(SENSOR_CLASSES), +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_EXCLUDE_ZONES, default=[]): + vol.All(cv.ensure_list, [cv.positive_int]), + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_ZONE_TYPES, default={}): ZONE_TYPES_SCHEMA, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup nx584 binary sensor platform.""" + """Setup the NX584 binary sensor platform.""" from nx584 import client as nx584_client - host = config.get('host', 'localhost:5007') - exclude = config.get('exclude_zones', []) - zone_types = config.get('zone_types', {}) - - if not all(isinstance(zone, int) for zone in exclude): - _LOGGER.error('Invalid excluded zone specified (use zone number)') - return False - - if not all(isinstance(zone, int) and ztype in SENSOR_CLASSES - for zone, ztype in zone_types.items()): - _LOGGER.error('Invalid zone_types entry') - return False + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + exclude = config.get(CONF_EXCLUDE_ZONES) + zone_types = config.get(CONF_ZONE_TYPES) try: - client = nx584_client.Client('http://%s' % host) + client = nx584_client.Client('http://{}:{}'.format(host, port)) zones = client.list_zones() except requests.exceptions.ConnectionError as ex: _LOGGER.error('Unable to connect to NX584: %s', str(ex)) @@ -43,7 +58,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): version = [int(v) for v in client.get_version().split('.')] if version < [1, 1]: - _LOGGER.error('NX584 is too old to use for sensors (>=0.2 required)') + _LOGGER.error("NX584 is too old to use for sensors (>=0.2 required)") return False zone_sensors = { @@ -57,13 +72,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): watcher = NX584Watcher(client, zone_sensors) watcher.start() else: - _LOGGER.warning('No zones found on NX584') - + _LOGGER.warning("No zones found on NX584") return True class NX584ZoneSensor(BinarySensorDevice): - """Represents a NX584 zone as a sensor.""" + """Representation of a NX584 zone as a sensor.""" def __init__(self, zone, zone_type): """Initialize the nx594 binary sensor.""" @@ -96,7 +110,7 @@ class NX584Watcher(threading.Thread): """Event listener thread to process NX584 events.""" def __init__(self, client, zone_sensors): - """Initialize nx584 watcher thread.""" + """Initialize NX584 watcher thread.""" super(NX584Watcher, self).__init__() self.daemon = True self._client = client @@ -130,5 +144,5 @@ class NX584Watcher(threading.Thread): try: self._run() except requests.exceptions.ConnectionError: - _LOGGER.error('Failed to reach NX584 server') + _LOGGER.error("Failed to reach NX584 server") time.sleep(10) diff --git a/homeassistant/components/binary_sensor/rest.py b/homeassistant/components/binary_sensor/rest.py index b8be340d43c..3e22150a4fd 100644 --- a/homeassistant/components/binary_sensor/rest.py +++ b/homeassistant/components/binary_sensor/rest.py @@ -5,15 +5,19 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.rest/ """ import logging +import json import voluptuous as vol +from requests.auth import HTTPBasicAuth, HTTPDigestAuth from homeassistant.components.binary_sensor import ( BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA) from homeassistant.components.sensor.rest import RestData from homeassistant.const import ( CONF_PAYLOAD, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_METHOD, CONF_RESOURCE, - CONF_SENSOR_CLASS, CONF_VERIFY_SSL) + CONF_SENSOR_CLASS, CONF_VERIFY_SSL, CONF_USERNAME, CONF_PASSWORD, + CONF_HEADERS, CONF_AUTHENTICATION, HTTP_BASIC_AUTHENTICATION, + HTTP_DIGEST_AUTHENTICATION) import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) @@ -24,16 +28,21 @@ DEFAULT_VERIFY_SSL = True PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_AUTHENTICATION): + vol.In([HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]), + vol.Optional(CONF_HEADERS): cv.string, vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_PAYLOAD): cv.string, vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, }) -# pylint: disable=unused-variable +# pylint: disable=unused-variable, too-many-locals def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the REST binary sensor.""" name = config.get(CONF_NAME) @@ -41,11 +50,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None): method = config.get(CONF_METHOD) payload = config.get(CONF_PAYLOAD) verify_ssl = config.get(CONF_VERIFY_SSL) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + headers = json.loads(config.get(CONF_HEADERS, '{}')) sensor_class = config.get(CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass - rest = RestData(method, resource, payload, verify_ssl) + + if username and password: + if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION: + auth = HTTPDigestAuth(username, password) + else: + auth = HTTPBasicAuth(username, password) + else: + auth = None + + rest = RestData(method, resource, auth, headers, payload, verify_ssl) rest.update() if rest.data is None: diff --git a/homeassistant/components/binary_sensor/template.py b/homeassistant/components/binary_sensor/template.py index 662a6982a11..d179edfc1d8 100644 --- a/homeassistant/components/binary_sensor/template.py +++ b/homeassistant/components/binary_sensor/template.py @@ -4,10 +4,12 @@ Support for exposing a templated binary sensor. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.template/ """ +import asyncio import logging import voluptuous as vol +from homeassistant.core import callback from homeassistant.components.binary_sensor import ( BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) @@ -81,9 +83,10 @@ class BinarySensorTemplate(BinarySensorDevice): self.update() + @callback def template_bsensor_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" - self.update_ha_state(True) + hass.loop.create_task(self.async_update_ha_state(True)) track_state_change(hass, entity_ids, template_bsensor_state_listener) @@ -107,10 +110,11 @@ class BinarySensorTemplate(BinarySensorDevice): """No polling needed.""" return False - def update(self): + @asyncio.coroutine + def async_update(self): """Get the latest data and update the state.""" try: - self._state = self._template.render().lower() == 'true' + self._state = self._template.async_render().lower() == 'true' except TemplateError as ex: if ex.args and ex.args[0].startswith( "UndefinedError: 'None' has no attribute"): diff --git a/homeassistant/components/binary_sensor/wink.py b/homeassistant/components/binary_sensor/wink.py index 636a5747ed5..9813ca213e6 100644 --- a/homeassistant/components/binary_sensor/wink.py +++ b/homeassistant/components/binary_sensor/wink.py @@ -20,7 +20,10 @@ SENSOR_TYPES = { "vibration": "vibration", "loudness": "sound", "liquid_detected": "moisture", - "motion": "motion" + "motion": "motion", + "presence": "occupancy", + "co_detected": "gas", + "smoke_detected": "smoke" } @@ -35,6 +38,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for key in pywink.get_keys(): add_devices([WinkBinarySensorDevice(key)]) + for sensor in pywink.get_smoke_and_co_detectors(): + add_devices([WinkBinarySensorDevice(sensor)]) + class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): """Representation of a Wink binary sensor.""" @@ -58,17 +64,25 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): def is_on(self): """Return true if the binary sensor is on.""" if self.capability == "loudness": - return self.wink.loudness_boolean() + state = self.wink.loudness_boolean() elif self.capability == "vibration": - return self.wink.vibration_boolean() + state = self.wink.vibration_boolean() elif self.capability == "brightness": - return self.wink.brightness_boolean() + state = self.wink.brightness_boolean() elif self.capability == "liquid_detected": - return self.wink.liquid_boolean() + state = self.wink.liquid_boolean() elif self.capability == "motion": - return self.wink.motion_boolean() + state = self.wink.motion_boolean() + elif self.capability == "presence": + state = self.wink.presence_boolean() + elif self.capability == "co_detected": + state = self.wink.co_detected_boolean() + elif self.capability == "smoke_detected": + state = self.wink.smoke_detected_boolean() else: - return self.wink.state() + state = self.wink.state() + + return state @property def sensor_class(self): diff --git a/homeassistant/components/binary_sensor/zwave.py b/homeassistant/components/binary_sensor/zwave.py index 1b47b98fe9f..69688c7e4f6 100644 --- a/homeassistant/components/binary_sensor/zwave.py +++ b/homeassistant/components/binary_sensor/zwave.py @@ -36,8 +36,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if discovery_info is None or zwave.NETWORK is None: return - node = zwave.NETWORK.nodes[discovery_info[zwave.ATTR_NODE_ID]] - value = node.values[discovery_info[zwave.ATTR_VALUE_ID]] + node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] + value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] value.set_change_verified(False) # Make sure that we have values for the key before converting to int @@ -58,7 +58,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): ]) return - if value.command_class == zwave.COMMAND_CLASS_SENSOR_BINARY: + if value.command_class == zwave.const.COMMAND_CLASS_SENSOR_BINARY: add_devices([ZWaveBinarySensor(value, None)]) diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index 726ed4f674c..e8047093cc8 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -58,6 +58,12 @@ ATTR_OPERATION_LIST = "operation_list" ATTR_SWING_MODE = "swing_mode" ATTR_SWING_LIST = "swing_list" +CONVERTIBLE_ATTRIBUTE = [ + ATTR_TEMPERATURE, + ATTR_TARGET_TEMP_LOW, + ATTR_TARGET_TEMP_HIGH, +] + _LOGGER = logging.getLogger(__name__) SET_AWAY_MODE_SCHEMA = vol.Schema({ @@ -73,6 +79,7 @@ SET_TEMPERATURE_SCHEMA = vol.Schema({ vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float), vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Optional(ATTR_OPERATION_MODE): cv.string, }) SET_FAN_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, @@ -116,8 +123,10 @@ def set_aux_heat(hass, aux_heat, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_AUX_HEAT, data) +# pylint: disable=too-many-arguments def set_temperature(hass, temperature=None, entity_id=None, - target_temp_high=None, target_temp_low=None): + target_temp_high=None, target_temp_low=None, + operation_mode=None): """Set new target temperature.""" kwargs = { key: value for key, value in [ @@ -125,6 +134,7 @@ def set_temperature(hass, temperature=None, entity_id=None, (ATTR_TARGET_TEMP_HIGH, target_temp_high), (ATTR_TARGET_TEMP_LOW, target_temp_low), (ATTR_ENTITY_ID, entity_id), + (ATTR_OPERATION_MODE, operation_mode) ] if value is not None } _LOGGER.debug("set_temperature start data=%s", kwargs) @@ -235,10 +245,20 @@ def setup(hass, config): def temperature_set_service(service): """Set temperature on the target climate devices.""" target_climate = component.extract_from_service(service) - kwargs = service.data - for climate in target_climate: - climate.set_temperature(**kwargs) + for climate in target_climate: + kwargs = {} + for value, temp in service.data.items(): + if value in CONVERTIBLE_ATTRIBUTE: + kwargs[value] = convert_temperature( + temp, + hass.config.units.temperature_unit, + climate.unit_of_measurement + ) + else: + kwargs[value] = temp + + climate.set_temperature(**kwargs) if climate.should_poll: climate.update_ha_state(True) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index 2884f4d2eb2..36be2ca25f5 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -13,7 +13,6 @@ from homeassistant.components.climate import ( ATTR_TEMPERATURE) from homeassistant.const import ( TEMP_CELSIUS, CONF_SCAN_INTERVAL, STATE_ON, STATE_OFF, STATE_UNKNOWN) -from homeassistant.util.temperature import convert as convert_temperature DEPENDENCIES = ['nest'] _LOGGER = logging.getLogger(__name__) @@ -127,12 +126,9 @@ class NestThermostat(ClimateDevice): def set_temperature(self, **kwargs): """Set new target temperature.""" - if kwargs.get(ATTR_TARGET_TEMP_LOW) is not None and \ - kwargs.get(ATTR_TARGET_TEMP_HIGH) is not None: - target_temp_high = convert_temperature(kwargs.get( - ATTR_TARGET_TEMP_HIGH), self._unit, TEMP_CELSIUS) - target_temp_low = convert_temperature(kwargs.get( - ATTR_TARGET_TEMP_LOW), self._unit, TEMP_CELSIUS) + target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) + target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) + if target_temp_low is not None and target_temp_high is not None: if self.device.mode == 'range': temp = (target_temp_low, target_temp_high) diff --git a/homeassistant/components/climate/services.yaml b/homeassistant/components/climate/services.yaml index 3a037d2a48b..d28e8c4dd88 100644 --- a/homeassistant/components/climate/services.yaml +++ b/homeassistant/components/climate/services.yaml @@ -34,6 +34,18 @@ set_temperature: description: New target temperature for hvac example: 25 + target_temp_high: + description: New target high tempereature for hvac + example: 26 + + target_temp_low: + description: New target low temperature for hvac + example: 20 + + operation_mode: + description: Operation mode to set temperature to. This defaults to current_operation mode if not set, or set incorrectly. + example: 'Heat' + set_humidity: description: Set target humidity of climate device diff --git a/homeassistant/components/climate/zwave.py b/homeassistant/components/climate/zwave.py index 4eec1f9c652..767bed6ff94 100755 --- a/homeassistant/components/climate/zwave.py +++ b/homeassistant/components/climate/zwave.py @@ -8,9 +8,9 @@ https://home-assistant.io/components/climate.zwave/ # pylint: disable=import-error import logging from homeassistant.components.climate import DOMAIN -from homeassistant.components.climate import ClimateDevice -from homeassistant.components.zwave import ( - ATTR_NODE_ID, ATTR_VALUE_ID, ZWaveDeviceEntity) +from homeassistant.components.climate import ( + ClimateDevice, ATTR_OPERATION_MODE) +from homeassistant.components.zwave import ZWaveDeviceEntity from homeassistant.components import zwave from homeassistant.const import ( TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE) @@ -28,12 +28,6 @@ HORSTMANN = 0x0059 HORSTMANN_HRT4_ZW = 0x3 HORSTMANN_HRT4_ZW_THERMOSTAT = (HORSTMANN, HORSTMANN_HRT4_ZW) -COMMAND_CLASS_SENSOR_MULTILEVEL = 0x31 -COMMAND_CLASS_THERMOSTAT_MODE = 0x40 -COMMAND_CLASS_THERMOSTAT_SETPOINT = 0x43 -COMMAND_CLASS_THERMOSTAT_FAN_MODE = 0x44 -COMMAND_CLASS_CONFIGURATION = 0x70 - WORKAROUND_ZXT_120 = 'zxt_120' WORKAROUND_HRT4_ZW = 'hrt4_zw' @@ -67,19 +61,19 @@ def setup_platform(hass, config, add_devices, discovery_info=None): discovery_info, zwave.NETWORK) return temp_unit = hass.config.units.temperature_unit - node = zwave.NETWORK.nodes[discovery_info[ATTR_NODE_ID]] - value = node.values[discovery_info[ATTR_VALUE_ID]] + node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] + value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] value.set_change_verified(False) add_devices([ZWaveClimate(value, temp_unit)]) _LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s", discovery_info, zwave.NETWORK) -# pylint: disable=too-many-arguments, abstract-method +# pylint: disable=abstract-method class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): """Represents a ZWave Climate device.""" - # pylint: disable=too-many-public-methods, too-many-instance-attributes + # pylint: disable=too-many-instance-attributes def __init__(self, value, temp_unit): """Initialize the zwave climate device.""" from openzwave.network import ZWaveNetwork @@ -130,7 +124,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): """Callback on data change for the registered node/value pair.""" # Operation Mode for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_MODE).values(): + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_MODE).values(): self._current_operation = value.data self._index_operation = SET_TEMP_TO_INDEX.get( self._current_operation) @@ -139,14 +133,16 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): _LOGGER.debug("self._current_operation=%s", self._current_operation) # Current Temp - for value in self._node.get_values( - class_id=COMMAND_CLASS_SENSOR_MULTILEVEL).values(): + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_SENSOR_MULTILEVEL) + .values()): if value.label == 'Temperature': self._current_temperature = int(value.data) self._unit = value.units # Fan Mode - for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_FAN_MODE).values(): + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_MODE) + .values()): self._current_fan_mode = value.data self._fan_list = list(value.data_items) _LOGGER.debug("self._fan_list=%s", self._fan_list) @@ -154,17 +150,27 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): self._current_fan_mode) # Swing mode if self._zxt_120 == 1: - for value in self._node.get_values( - class_id=COMMAND_CLASS_CONFIGURATION).values(): - if value.command_class == 112 and value.index == 33: + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_CONFIGURATION) + .values()): + if value.command_class == \ + zwave.const.COMMAND_CLASS_CONFIGURATION and \ + value.index == 33: self._current_swing_mode = value.data self._swing_list = list(value.data_items) _LOGGER.debug("self._swing_list=%s", self._swing_list) _LOGGER.debug("self._current_swing_mode=%s", self._current_swing_mode) # Set point - for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT) + .values()): + if value.data == 0: + _LOGGER.debug("Setpoint is 0, setting default to " + "current_temperature=%s", + self._current_temperature) + self._target_temperature = int(self._current_temperature) + break if self.current_operation is not None and \ self.current_operation != 'Off': if self._index_operation != value.index: @@ -232,16 +238,26 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): """Return the temperature we try to reach.""" return self._target_temperature -# pylint: disable=too-many-branches, too-many-statements def set_temperature(self, **kwargs): """Set new target temperature.""" if kwargs.get(ATTR_TEMPERATURE) is not None: temperature = kwargs.get(ATTR_TEMPERATURE) else: return + operation_mode = kwargs.get(ATTR_OPERATION_MODE) + _LOGGER.debug("set_temperature operation_mode=%s", operation_mode) + + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_SETPOINT) + .values()): + if operation_mode is not None: + setpoint_mode = SET_TEMP_TO_INDEX.get(operation_mode) + if value.index != setpoint_mode: + continue + _LOGGER.debug("setpoint_mode=%s", setpoint_mode) + value.data = temperature + break - for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): if self.current_operation is not None: if self._hrt4_zw and self.current_operation == 'Off': # HRT4-ZW can change setpoint when off. @@ -279,17 +295,21 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): def set_fan_mode(self, fan): """Set new target fan mode.""" - for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_FAN_MODE).values(): - if value.command_class == 68 and value.index == 0: + for value in (self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_MODE). + values()): + if value.command_class == \ + zwave.const.COMMAND_CLASS_THERMOSTAT_FAN_MODE and \ + value.index == 0: value.data = bytes(fan, 'utf-8') break def set_operation_mode(self, operation_mode): """Set new target operation mode.""" for value in self._node.get_values( - class_id=COMMAND_CLASS_THERMOSTAT_MODE).values(): - if value.command_class == 64 and value.index == 0: + class_id=zwave.const.COMMAND_CLASS_THERMOSTAT_MODE).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_THERMOSTAT_MODE and value.index == 0: value.data = bytes(operation_mode, 'utf-8') break @@ -297,7 +317,9 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): """Set new target swing mode.""" if self._zxt_120 == 1: for value in self._node.get_values( - class_id=COMMAND_CLASS_CONFIGURATION).values(): - if value.command_class == 112 and value.index == 33: + class_id=zwave.const.COMMAND_CLASS_CONFIGURATION).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_CONFIGURATION and \ + value.index == 33: value.data = bytes(swing_mode, 'utf-8') break diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index 2a9a55d289a..b688e3d7082 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -29,6 +29,10 @@ SERVICE_PROCESS_SCHEMA = vol.Schema({ vol.Required(ATTR_TEXT): vol.All(cv.string, vol.Lower), }) +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({}), +}, extra=vol.ALLOW_EXTRA) + def setup(hass, config): """Register the process service.""" @@ -48,8 +52,8 @@ def setup(hass, config): name, command = match.groups() entities = {state.entity_id: state.name for state in hass.states.all()} - entity_ids = fuzzyExtract.extractOne(name, entities, - score_cutoff=65)[2] + entity_ids = fuzzyExtract.extractOne( + name, entities, score_cutoff=65)[2] if not entity_ids: logger.error( @@ -70,6 +74,7 @@ def setup(hass, config): logger.error('Got unsupported command %s from text %s', command, text) - hass.services.register(DOMAIN, SERVICE_PROCESS, process, - schema=SERVICE_PROCESS_SCHEMA) + hass.services.register( + DOMAIN, SERVICE_PROCESS, process, schema=SERVICE_PROCESS_SCHEMA) + return True diff --git a/homeassistant/components/cover/mysensors.py b/homeassistant/components/cover/mysensors.py new file mode 100644 index 00000000000..aa3d866bcd6 --- /dev/null +++ b/homeassistant/components/cover/mysensors.py @@ -0,0 +1,103 @@ +""" +Support for MySensors covers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.mysensors/ +""" +import logging + +from homeassistant.components import mysensors +from homeassistant.components.cover import CoverDevice, ATTR_POSITION +from homeassistant.const import STATE_ON, STATE_OFF + +_LOGGER = logging.getLogger(__name__) +DEPENDENCIES = [] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the mysensors platform for covers.""" + if discovery_info is None: + return + for gateway in mysensors.GATEWAYS.values(): + pres = gateway.const.Presentation + set_req = gateway.const.SetReq + map_sv_types = { + pres.S_COVER: [set_req.V_DIMMER, set_req.V_LIGHT], + } + if float(gateway.protocol_version) >= 1.5: + map_sv_types.update({ + pres.S_COVER: [set_req.V_PERCENTAGE, set_req.V_STATUS], + }) + devices = {} + gateway.platform_callbacks.append(mysensors.pf_callback_factory( + map_sv_types, devices, add_devices, MySensorsCover)) + + +class MySensorsCover(mysensors.MySensorsDeviceEntity, CoverDevice): + """Representation of the value of a MySensors Cover child node.""" + + @property + def assumed_state(self): + """Return True if unable to access real state of entity.""" + return self.gateway.optimistic + + @property + def is_closed(self): + """Return True if cover is closed.""" + set_req = self.gateway.const.SetReq + if set_req.V_DIMMER in self._values: + return self._values.get(set_req.V_DIMMER) == 0 + else: + return self._values.get(set_req.V_LIGHT) == STATE_OFF + + @property + def current_cover_position(self): + """Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + set_req = self.gateway.const.SetReq + return self._values.get(set_req.V_DIMMER) + + def open_cover(self, **kwargs): + """Move the cover up.""" + set_req = self.gateway.const.SetReq + self.gateway.set_child_value( + self.node_id, self.child_id, set_req.V_UP, 1) + if self.gateway.optimistic: + # Optimistically assume that cover has changed state. + if set_req.V_DIMMER in self._values: + self._values[set_req.V_DIMMER] = 100 + else: + self._values[set_req.V_LIGHT] = STATE_ON + self.update_ha_state() + + def close_cover(self, **kwargs): + """Move the cover down.""" + set_req = self.gateway.const.SetReq + self.gateway.set_child_value( + self.node_id, self.child_id, set_req.V_DOWN, 1) + if self.gateway.optimistic: + # Optimistically assume that cover has changed state. + if set_req.V_DIMMER in self._values: + self._values[set_req.V_DIMMER] = 0 + else: + self._values[set_req.V_LIGHT] = STATE_OFF + self.update_ha_state() + + def set_cover_position(self, **kwargs): + """Move the cover to a specific position.""" + position = kwargs.get(ATTR_POSITION) + set_req = self.gateway.const.SetReq + self.gateway.set_child_value( + self.node_id, self.child_id, set_req.V_DIMMER, position) + if self.gateway.optimistic: + # Optimistically assume that cover has changed state. + self._values[set_req.V_DIMMER] = position + self.update_ha_state() + + def stop_cover(self, **kwargs): + """Stop the device.""" + set_req = self.gateway.const.SetReq + self.gateway.set_child_value( + self.node_id, self.child_id, set_req.V_STOP, 1) diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py index df7b2e14cb5..a3db374ddf1 100644 --- a/homeassistant/components/cover/zwave.py +++ b/homeassistant/components/cover/zwave.py @@ -12,9 +12,6 @@ from homeassistant.components.zwave import ZWaveDeviceEntity from homeassistant.components import zwave from homeassistant.components.cover import CoverDevice -COMMAND_CLASS_SWITCH_MULTILEVEL = 0x26 # 38 -COMMAND_CLASS_SWITCH_BINARY = 0x25 # 37 - SOMFY = 0x47 SOMFY_ZRTSI = 0x5a52 SOMFY_ZRTSI_CONTROLLER = (SOMFY, SOMFY_ZRTSI) @@ -32,17 +29,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if discovery_info is None or zwave.NETWORK is None: return - node = zwave.NETWORK.nodes[discovery_info[zwave.ATTR_NODE_ID]] - value = node.values[discovery_info[zwave.ATTR_VALUE_ID]] + node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] + value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] - if (value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL and - value.index == 0): + if node.has_command_class(zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL) \ + and value.index == 0: value.set_change_verified(False) add_devices([ZwaveRollershutter(value)]) - elif (value.command_class == zwave.COMMAND_CLASS_SWITCH_BINARY or - value.command_class == zwave.COMMAND_CLASS_BARRIER_OPERATOR): - if value.type != zwave.TYPE_BOOL and \ - value.genre != zwave.GENRE_USER: + elif node.has_command_class(zwave.const.COMMAND_CLASS_SWITCH_BINARY) or \ + node.has_command_class(zwave.const.COMMAND_CLASS_BARRIER_OPERATOR): + if value.type != zwave.const.TYPE_BOOL and \ + value.genre != zwave.const.GENRE_USER: return value.set_change_verified(False) add_devices([ZwaveGarageDoor(value)]) @@ -59,6 +56,7 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): from openzwave.network import ZWaveNetwork from pydispatch import dispatcher ZWaveDeviceEntity.__init__(self, value, DOMAIN) + # pylint: disable=no-member self._lozwmgr = libopenzwave.PyManager() self._lozwmgr.create() self._node = value.node @@ -88,9 +86,10 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): """Callback on data change for the registered node/value pair.""" # Position value for value in self._node.get_values( - class_id=COMMAND_CLASS_SWITCH_MULTILEVEL).values(): - if value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Level': + class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and \ + value.label == 'Level': self._current_position = value.data @property @@ -118,22 +117,24 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): def open_cover(self, **kwargs): """Move the roller shutter up.""" for value in self._node.get_values( - class_id=COMMAND_CLASS_SWITCH_MULTILEVEL).values(): - if value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Open' or \ - value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Down': + class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Open' or value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Down': self._lozwmgr.pressButton(value.value_id) break def close_cover(self, **kwargs): """Move the roller shutter down.""" for value in self._node.get_values( - class_id=COMMAND_CLASS_SWITCH_MULTILEVEL).values(): - if value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Up' or \ - value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Close': + class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Up' or value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Close': self._lozwmgr.pressButton(value.value_id) break @@ -144,11 +145,12 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): def stop_cover(self, **kwargs): """Stop the roller shutter.""" for value in self._node.get_values( - class_id=COMMAND_CLASS_SWITCH_MULTILEVEL).values(): - if value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Open' or \ - value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ - and value.label == 'Down': + class_id=zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL).values(): + if value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Open' or value.command_class == \ + zwave.const.COMMAND_CLASS_SWITCH_MULTILEVEL and value.label == \ + 'Down': self._lozwmgr.releaseButton(value.value_id) break diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 236fde6fb3f..a05b57cff33 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -46,7 +46,6 @@ CONF_TRACK_NEW = 'track_new_devices' DEFAULT_TRACK_NEW = True CONF_CONSIDER_HOME = 'consider_home' -DEFAULT_CONSIDER_HOME = 180 # seconds CONF_SCAN_INTERVAL = 'interval_seconds' DEFAULT_SCAN_INTERVAL = 12 @@ -70,8 +69,10 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ _CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.All(cv.ensure_list, [ vol.Schema({ - vol.Optional(CONF_TRACK_NEW): cv.boolean, - vol.Optional(CONF_CONSIDER_HOME): cv.positive_int # seconds + vol.Optional(CONF_TRACK_NEW, default=DEFAULT_TRACK_NEW): cv.boolean, + vol.Optional( + CONF_CONSIDER_HOME, default=timedelta(seconds=180)): vol.All( + cv.time_period, cv.positive_timedelta) }, extra=vol.ALLOW_EXTRA)])}, extra=vol.ALLOW_EXTRA) DISCOVERY_PLATFORMS = { @@ -118,9 +119,8 @@ def setup(hass: HomeAssistantType, config: ConfigType): return False else: conf = conf[0] if len(conf) > 0 else {} - consider_home = timedelta( - seconds=conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME)) - track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) + consider_home = conf[CONF_CONSIDER_HOME] + track_new = conf[CONF_TRACK_NEW] devices = load_config(yaml_path, hass, consider_home) @@ -282,7 +282,7 @@ class Device(Entity): def __init__(self, hass: HomeAssistantType, consider_home: timedelta, track: bool, dev_id: str, mac: str, name: str=None, picture: str=None, gravatar: str=None, - away_hide: bool=False) -> None: + hide_if_away: bool=False) -> None: """Initialize a device.""" self.hass = hass self.entity_id = ENTITY_ID_FORMAT.format(dev_id) @@ -307,7 +307,7 @@ class Device(Entity): else: self.config_picture = picture - self.away_hide = away_hide + self.away_hide = hide_if_away @property def name(self): @@ -398,15 +398,29 @@ class Device(Entity): def load_config(path: str, hass: HomeAssistantType, consider_home: timedelta): """Load devices from YAML configuration file.""" + dev_schema = vol.Schema({ + vol.Required('name'): cv.string, + vol.Optional('track', default=False): cv.boolean, + vol.Optional('mac', default=None): vol.Any(None, vol.All(cv.string, + vol.Upper)), + vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, + vol.Optional('gravatar', default=None): vol.Any(None, cv.string), + vol.Optional('picture', default=None): vol.Any(None, cv.string), + vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All( + cv.time_period, cv.positive_timedelta) + }) try: - return [ - Device(hass, consider_home, device.get('track', False), - str(dev_id).lower(), None if device.get('mac') is None - else str(device.get('mac')).upper(), - device.get('name'), device.get('picture'), - device.get('gravatar'), - device.get(CONF_AWAY_HIDE, DEFAULT_AWAY_HIDE)) - for dev_id, device in load_yaml_config_file(path).items()] + result = [] + devices = load_yaml_config_file(path) + for dev_id, device in devices.items(): + try: + device = dev_schema(device) + device['dev_id'] = cv.slug(dev_id) + except vol.Invalid as exp: + log_exception(exp, dev_id, devices) + else: + result.append(Device(hass, **device)) + return result except (HomeAssistantError, FileNotFoundError): # When YAML file could not be loaded/did not contain a dict return [] diff --git a/homeassistant/components/device_tracker/fritz.py b/homeassistant/components/device_tracker/fritz.py index 202919871ad..0e8ed512072 100644 --- a/homeassistant/components/device_tracker/fritz.py +++ b/homeassistant/components/device_tracker/fritz.py @@ -85,7 +85,9 @@ class FritzBoxScanner(object): def get_device_name(self, mac): """Return the name of the given device or None if is not known.""" - ret = self.fritz_box.get_specific_host_entry(mac)['NewHostName'] + ret = self.fritz_box.get_specific_host_entry(mac).get( + 'NewHostName' + ) if ret == {}: return None return ret diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index 1395f2940fe..d903c25a5c8 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -7,6 +7,7 @@ https://home-assistant.io/components/device_tracker.owntracks/ import json import logging import threading +import base64 from collections import defaultdict import voluptuous as vol @@ -18,53 +19,121 @@ from homeassistant.util import convert, slugify from homeassistant.components import zone as zone_comp from homeassistant.components.device_tracker import PLATFORM_SCHEMA -DEPENDENCIES = ['mqtt'] - -REGIONS_ENTERED = defaultdict(list) -MOBILE_BEACONS_ACTIVE = defaultdict(list) - -BEACON_DEV_ID = 'beacon' - -LOCATION_TOPIC = 'owntracks/+/+' -EVENT_TOPIC = 'owntracks/+/+/event' -WAYPOINT_TOPIC = 'owntracks/{}/{}/waypoint' +REQUIREMENTS = ['libnacl==1.5.0'] _LOGGER = logging.getLogger(__name__) -LOCK = threading.Lock() +BEACON_DEV_ID = 'beacon' CONF_MAX_GPS_ACCURACY = 'max_gps_accuracy' +CONF_SECRET = 'secret' CONF_WAYPOINT_IMPORT = 'waypoints' CONF_WAYPOINT_WHITELIST = 'waypoint_whitelist' +DEPENDENCIES = ['mqtt'] + +EVENT_TOPIC = 'owntracks/+/+/event' + +LOCATION_TOPIC = 'owntracks/+/+' +LOCK = threading.Lock() + +MOBILE_BEACONS_ACTIVE = defaultdict(list) + +REGIONS_ENTERED = defaultdict(list) + VALIDATE_LOCATION = 'location' VALIDATE_TRANSITION = 'transition' VALIDATE_WAYPOINTS = 'waypoints' WAYPOINT_LAT_KEY = 'lat' WAYPOINT_LON_KEY = 'lon' +WAYPOINT_TOPIC = 'owntracks/{}/{}/waypoint' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_MAX_GPS_ACCURACY): vol.Coerce(float), vol.Optional(CONF_WAYPOINT_IMPORT, default=True): cv.boolean, - vol.Optional(CONF_WAYPOINT_WHITELIST): vol.All(cv.ensure_list, [cv.string]) + vol.Optional(CONF_WAYPOINT_WHITELIST): vol.All( + cv.ensure_list, [cv.string]), + vol.Optional(CONF_SECRET): vol.Any( + vol.Schema({vol.Optional(cv.string): cv.string}), + cv.string) }) +def get_cipher(): + """Return decryption function and length of key.""" + from libnacl import crypto_secretbox_KEYBYTES as KEYLEN + from libnacl.secret import SecretBox + + def decrypt(ciphertext, key): + """Decrypt ciphertext using key.""" + return SecretBox(key).decrypt(ciphertext) + return (KEYLEN, decrypt) + + def setup_scanner(hass, config, see): - """Setup an OwnTracks tracker.""" + """Set up an OwnTracks tracker.""" max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY) waypoint_import = config.get(CONF_WAYPOINT_IMPORT) waypoint_whitelist = config.get(CONF_WAYPOINT_WHITELIST) + secret = config.get(CONF_SECRET) + + def decrypt_payload(topic, ciphertext): + """Decrypt encrypted payload.""" + try: + keylen, decrypt = get_cipher() + except OSError: + _LOGGER.warning('Ignoring encrypted payload ' + 'because libsodium not installed.') + return None + + if isinstance(secret, dict): + key = secret.get(topic) + else: + key = secret + + if key is None: + _LOGGER.warning('Ignoring encrypted payload ' + 'because no decryption key known ' + 'for topic %s.', topic) + return None + + key = key.encode("utf-8") + key = key[:keylen] + key = key.ljust(keylen, b'\0') + + try: + ciphertext = base64.b64decode(ciphertext) + message = decrypt(ciphertext, key) + message = message.decode("utf-8") + _LOGGER.debug("Decrypted payload: %s", message) + return message + except ValueError: + _LOGGER.warning('Ignoring encrypted payload ' + 'because unable to decrypt using key ' + 'for topic %s.', topic) + return None + + def validate_payload(topic, payload, data_type): + """Validate the OwnTracks payload.""" + # pylint: disable=too-many-return-statements - def validate_payload(payload, data_type): - """Validate OwnTracks payload.""" try: data = json.loads(payload) except ValueError: # If invalid JSON _LOGGER.error('Unable to parse payload as JSON: %s', payload) return None + + if isinstance(data, dict) and \ + data.get('_type') == 'encrypted' and \ + 'data' in data: + plaintext_payload = decrypt_payload(topic, data['data']) + if plaintext_payload is None: + return None + else: + return validate_payload(topic, plaintext_payload, data_type) + if not isinstance(data, dict) or data.get('_type') != data_type: _LOGGER.debug('Skipping %s update for following data ' 'because of missing or malformatted data: %s', @@ -90,7 +159,7 @@ def setup_scanner(hass, config, see): """MQTT message received.""" # Docs on available data: # http://owntracks.org/booklet/tech/json/#_typelocation - data = validate_payload(payload, VALIDATE_LOCATION) + data = validate_payload(topic, payload, VALIDATE_LOCATION) if not data: return @@ -111,7 +180,7 @@ def setup_scanner(hass, config, see): """MQTT event (geofences) received.""" # Docs on available data: # http://owntracks.org/booklet/tech/json/#_typetransition - data = validate_payload(payload, VALIDATE_TRANSITION) + data = validate_payload(topic, payload, VALIDATE_TRANSITION) if not data: return @@ -206,7 +275,7 @@ def setup_scanner(hass, config, see): """List of waypoints published by a user.""" # Docs on available data: # http://owntracks.org/booklet/tech/json/#_typewaypoints - data = validate_payload(payload, VALIDATE_WAYPOINTS) + data = validate_payload(topic, payload, VALIDATE_WAYPOINTS) if not data: return diff --git a/homeassistant/components/device_tracker/volvooncall.py b/homeassistant/components/device_tracker/volvooncall.py new file mode 100644 index 00000000000..8f5cf5fff7a --- /dev/null +++ b/homeassistant/components/device_tracker/volvooncall.py @@ -0,0 +1,100 @@ +""" +Support for Volvo On Call. + +http://www.volvocars.com/intl/own/owner-info/volvo-on-call +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/device_tracker.volvooncall/ +""" +import logging +from datetime import timedelta +from urllib.parse import urljoin +import voluptuous as vol +import requests + +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.event import track_point_in_utc_time +from homeassistant.util.dt import utcnow +from homeassistant.const import ( + CONF_PASSWORD, + CONF_SCAN_INTERVAL, + CONF_USERNAME) +from homeassistant.components.device_tracker import ( + DEFAULT_SCAN_INTERVAL, + PLATFORM_SCHEMA) + +MIN_TIME_BETWEEN_SCANS = timedelta(minutes=1) + +_LOGGER = logging.getLogger(__name__) + +SERVICE_URL = 'https://vocapi.wirelesscar.net/customerapi/rest/v3.0/' +HEADERS = {"X-Device-Id": "Device", + "X-OS-Type": "Android", + "X-Originator-Type": "App"} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, +}) + + +def setup_scanner(hass, config, see): + """Validate the configuration and return a scanner.""" + session = requests.Session() + session.headers.update(HEADERS) + session.auth = (config.get(CONF_USERNAME), + config.get(CONF_PASSWORD)) + + interval = max(MIN_TIME_BETWEEN_SCANS.seconds, + config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)) + + def query(ref, rel=SERVICE_URL): + """Perform a query to the online service.""" + url = urljoin(rel, ref) + _LOGGER.debug("Request for %s", url) + res = session.get(url, timeout=15) + res.raise_for_status() + _LOGGER.debug("Received %s", res.json()) + return res.json() + + def update(now): + """Update status from the online service.""" + try: + _LOGGER.debug("Updating") + status = query("status", vehicle_url) + position = query("position", vehicle_url) + see(dev_id=dev_id, + host_name=host_name, + gps=(position["position"]["latitude"], + position["position"]["longitude"]), + attributes=dict( + tank_volume=attributes["fuelTankVolume"], + washer_fluid=status["washerFluidLevel"], + brake_fluid=status["brakeFluid"], + service_warning=status["serviceWarningStatus"], + fuel=status["fuelAmount"], + odometer=status["odometer"], + range=status["distanceToEmpty"])) + except requests.exceptions.RequestException as error: + _LOGGER.error("Could not query server: %s", error) + finally: + track_point_in_utc_time(hass, update, + now + timedelta(seconds=interval)) + + try: + _LOGGER.info('Logging in to service') + user = query("customeraccounts") + rel = query(user["accountVehicleRelations"][0]) + vehicle_url = rel["vehicle"] + '/' + attributes = query("attributes", vehicle_url) + + dev_id = "volvo_" + attributes["registrationNumber"] + host_name = "%s %s/%s" % (attributes["registrationNumber"], + attributes["vehicleType"], + attributes["modelYear"]) + update(utcnow()) + return True + except requests.exceptions.RequestException as error: + _LOGGER.error("Could not log in to service. " + "Please check configuration: " + "%s", error) + return False diff --git a/homeassistant/components/digital_ocean.py b/homeassistant/components/digital_ocean.py new file mode 100644 index 00000000000..b91ec2672af --- /dev/null +++ b/homeassistant/components/digital_ocean.py @@ -0,0 +1,86 @@ +""" +Support for Digital Ocean. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/digital_ocean/ +""" +import logging +from datetime import timedelta + +import voluptuous as vol + +from homeassistant.const import CONF_ACCESS_TOKEN +from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['python-digitalocean==1.9.0'] + +_LOGGER = logging.getLogger(__name__) + +ATTR_CREATED_AT = 'created_at' +ATTR_DROPLET_ID = 'droplet_id' +ATTR_DROPLET_NAME = 'droplet_name' +ATTR_FEATURES = 'features' +ATTR_IPV4_ADDRESS = 'ipv4_address' +ATTR_IPV6_ADDRESS = 'ipv6_address' +ATTR_MEMORY = 'memory' +ATTR_REGION = 'region' +ATTR_VCPUS = 'vcpus' + +CONF_DROPLETS = 'droplets' + +DIGITAL_OCEAN = None +DIGITAL_OCEAN_PLATFORMS = ['switch', 'binary_sensor'] +DOMAIN = 'digital_ocean' + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_ACCESS_TOKEN): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + + +# pylint: disable=unused-argument,too-few-public-methods +def setup(hass, config): + """Setup the Digital Ocean component.""" + conf = config[DOMAIN] + access_token = conf.get(CONF_ACCESS_TOKEN) + + global DIGITAL_OCEAN + DIGITAL_OCEAN = DigitalOcean(access_token) + + if not DIGITAL_OCEAN.manager.get_account(): + _LOGGER.error("No Digital Ocean account found for the given API Token") + return False + + return True + + +class DigitalOcean(object): + """Handle all communication with the Digital Ocean API.""" + + def __init__(self, access_token): + """Initialize the Digital Ocean connection.""" + import digitalocean + + self._access_token = access_token + self.data = None + self.manager = digitalocean.Manager(token=self._access_token) + + def get_droplet_id(self, droplet_name): + """Get the status of a Digital Ocean droplet.""" + droplet_id = None + + all_droplets = self.manager.get_all_droplets() + for droplet in all_droplets: + if droplet_name == droplet.name: + droplet_id = droplet.id + + return droplet_id + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Use the data from Digital Ocean API.""" + self.data = self.manager.get_all_droplets() diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 0ac40c00f90..fa48be04e74 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -9,6 +9,8 @@ loaded before the EVENT_PLATFORM_DISCOVERED is fired. import logging import threading +import voluptuous as vol + from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.helpers.discovery import load_platform, discover @@ -33,6 +35,10 @@ SERVICE_HANDLERS = { 'directv': ('media_player', 'directv'), } +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({}), +}, extra=vol.ALLOW_EXTRA) + def setup(hass, config): """Start a discovery service.""" diff --git a/homeassistant/components/emulated_hue.py b/homeassistant/components/emulated_hue.py index 3c7f81b2ed9..88a5ff58fe5 100644 --- a/homeassistant/components/emulated_hue.py +++ b/homeassistant/components/emulated_hue.py @@ -25,6 +25,8 @@ from homeassistant.components.light import ( from homeassistant.components.http import ( HomeAssistantView, HomeAssistantWSGI ) +# pylint: disable=unused-import +from homeassistant.components.http import REQUIREMENTS # noqa import homeassistant.helpers.config_validation as cv DOMAIN = 'emulated_hue' diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 151bc954cfa..2c8b0cc8bed 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,14 +1,14 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "78862c0984279b6876f594ffde45177c", - "frontend.html": "c1753e1ce530f978036742477c96d2fd", - "mdi.html": "6bd013a8252e19b3c1f1de52994cfbe4", - "panels/ha-panel-dev-event.html": "c4a5f70eece9f92616a65e8d26be803e", - "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", - "panels/ha-panel-dev-service.html": "07e83c6b7f79d78a59258f6dba477b54", - "panels/ha-panel-dev-state.html": "fd8eb946856b1346a87a51d0c86854ff", - "panels/ha-panel-dev-template.html": "7cff8a2ef3f44fdaf357a0d41696bf6d", + "core.js": "9b3e5ab4eac7e3b074e0daf3f619a638", + "frontend.html": "5854807d361de26fe93ad474010f19d2", + "mdi.html": "46a76f877ac9848899b8ed382427c16f", + "panels/ha-panel-dev-event.html": "550bf85345c454274a40d15b2795a002", + "panels/ha-panel-dev-info.html": "ec613406ce7e20d93754233d55625c8a", + "panels/ha-panel-dev-service.html": "c7974458ebc33412d95497e99b785e12", + "panels/ha-panel-dev-state.html": "4be627b74e683af14ef779d8203ec674", + "panels/ha-panel-dev-template.html": "d23943fa0370f168714da407c90091a2", "panels/ha-panel-history.html": "efe1bcdd7733b09e55f4f965d171c295", "panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab", "panels/ha-panel-logbook.html": "66108d82763359a218c9695f0553de40", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index d6ab58ba0ef..862449055fb 100644 --- a/homeassistant/components/frontend/www_static/core.js +++ b/homeassistant/components/frontend/www_static/core.js @@ -1,4 +1,4 @@ -!(function(){"use strict";function t(t){return t&&t.__esModule?t.default:t}function e(t,e){return e={exports:{}},t(e,e.exports),e.exports}function n(t,e){var n=e.authToken,r=e.host;return Ne({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return ke.getInitialState()}function i(t,e){var n=e.errorMessage;return t.withMutations((function(t){return t.set("isValidating",!1).set("isInvalid",!0).set("errorMessage",n)}))}function o(t,e){var n=e.authToken,r=e.host;return Pe({authToken:n,host:r})}function u(){return He.getInitialState()}function a(t,e){var n=e.rememberAuth;return n}function s(t){return t.withMutations((function(t){t.set("isStreaming",!0).set("useStreaming",!0).set("hasError",!1)}))}function c(t){return t.withMutations((function(t){t.set("isStreaming",!1).set("useStreaming",!1).set("hasError",!1)}))}function f(t){return t.withMutations((function(t){t.set("isStreaming",!1).set("hasError",!0)}))}function h(){return Ye.getInitialState()}function l(t,e){var n=e.model,r=e.result,i=e.params,o=n.entity;if(!r)return t;var u=i.replace?tn({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||tn;return t.set(o,u.withMutations((function(t){for(var e=0;e199&&u.status<300?t(e):n(e)},u.onerror=function(){return n({})},r?(u.setRequestHeader("Content-Type","application/json;charset=UTF-8"),u.send(JSON.stringify(r))):u.send()})}function C(t,e){var n=e.message;return t.set(t.size,n)}function z(){return zn.getInitialState()}function R(t,e){t.dispatch(An.NOTIFICATION_CREATED,{message:e})}function M(t){t.registerStores({notifications:zn})}function L(t,e){if("lock"===t)return!0;if("garage_door"===t)return!0;var n=e.get(t);return!!n&&n.services.has("turn_on")}function j(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:L(t.domain,e))}function N(t,e){return[rr(t),function(t){return!!t&&t.services.has(e)}]}function k(t){return[wn.byId(t),nr,j]}function U(t,e,n){function r(){var c=(new Date).getTime()-a;c0?i=setTimeout(r,e-c):(i=null,n||(s=t.apply(u,o),i||(u=o=null)))}var i,o,u,a,s;null==e&&(e=100);var c=function(){u=this,o=arguments,a=(new Date).getTime();var c=n&&!i;return i||(i=setTimeout(r,e)),c&&(s=t.apply(u,o),u=o=null),s};return c.clear=function(){i&&(clearTimeout(i),i=null)},c}function P(t,e){var n=e.component;return t.push(n)}function H(t,e){var n=e.components;return dr(n)}function x(){return vr.getInitialState()}function V(t,e){var n=e.latitude,r=e.longitude,i=e.location_name,o=e.temperature_unit,u=e.time_zone,a=e.version;return Sr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function q(){return gr.getInitialState()}function F(t,e){t.dispatch(pr.SERVER_CONFIG_LOADED,e)}function G(t){ln(t,"GET","config").then((function(e){return F(t,e)}))}function K(t,e){t.dispatch(pr.COMPONENT_LOADED,{component:e})}function Y(t){return[["serverComponent"],function(e){return e.contains(t)}]}function B(t){t.registerStores({serverComponent:vr,serverConfig:gr})}function J(t,e){var n=e.pane;return n}function W(){return zr.getInitialState()}function X(t,e){var n=e.panels;return Mr(n)}function Q(){return Lr.getInitialState()}function Z(t,e){var n=e.show;return!!n}function $(){return Nr.getInitialState()}function tt(t,e){t.dispatch(Dr.SHOW_SIDEBAR,{show:e})}function et(t,e){t.dispatch(Dr.NAVIGATE,{pane:e})}function nt(t,e){t.dispatch(Dr.PANELS_LOADED,{panels:e})}function rt(t,e){var n=e.entityId;return n}function it(){return Gr.getInitialState()}function ot(t,e){t.dispatch(qr.SELECT_ENTITY,{entityId:e})}function ut(t){t.dispatch(qr.SELECT_ENTITY,{entityId:null})}function at(t){return!t||(new Date).getTime()-t>6e4}function st(t,e){var n=e.date;return n.toISOString()}function ct(){return Jr.getInitialState()}function ft(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Xr({})):t.withMutations((function(t){r.forEach((function(e){return t.setIn([n,e[0].entity_id],Xr(e.map(yn.fromJSON)))}))}))}function ht(){return Qr.getInitialState()}function lt(t,e){var n=e.stateHistory;return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,ei(e.map(yn.fromJSON)))}))}))}function pt(){return ni.getInitialState()}function _t(t,e){var n=e.stateHistory,r=(new Date).getTime();return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,r)})),history.length>1&&t.set(oi,r)}))}function dt(){return ui.getInitialState()}function vt(t,e){t.dispatch(Yr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function yt(t,e){void 0===e&&(e=null),t.dispatch(Yr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),ln(t,"GET",n).then((function(e){return t.dispatch(Yr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})}),(function(){return t.dispatch(Yr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})}))}function St(t,e){return t.dispatch(Yr.ENTITY_HISTORY_FETCH_START,{date:e}),ln(t,"GET","history/period/"+e).then((function(n){return t.dispatch(Yr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})}),(function(){return t.dispatch(Yr.ENTITY_HISTORY_FETCH_ERROR,{})}))}function gt(t){var e=t.evaluate(ci);return St(t,e)}function mt(t){t.registerStores({currentEntityHistoryDate:Jr,entityHistory:Qr,isLoadingEntityHistory:$r,recentEntityHistory:ni,recentEntityHistoryUpdated:ui})}function Et(t){t.registerStores({moreInfoEntityId:Gr})}function It(t,e){var n=e.model,r=e.result,i=e.params;if(null===t||"entity"!==n.entity||!i.replace)return t;for(var o=0;ouu}function se(t){t.registerStores({currentLogbookDate:Yo,isLoadingLogbookEntries:Jo,logbookEntries:tu,logbookEntriesUpdated:ru})}function ce(t){return t.set("active",!0)}function fe(t){return t.set("active",!1)}function he(){return Su.getInitialState()}function le(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered.");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){var n;return n=navigator.userAgent.toLowerCase().indexOf("firefox")>-1?"firefox":"chrome",ln(t,"POST","notify.html5",{subscription:e,browser:n}).then((function(){return t.dispatch(du.PUSH_NOTIFICATIONS_SUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n;return n=e.message&&e.message.indexOf("gcm_sender_id")!==-1?"Please setup the notify.html5 platform.":"Notification registration failed.",console.error(e),Nn.createNotification(t,n),!1}))}function pe(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){return ln(t,"DELETE","notify.html5",{subscription:e}).then((function(){return e.unsubscribe()})).then((function(){return t.dispatch(du.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Nn.createNotification(t,n),!1}))}function _e(t){t.registerStores({pushNotifications:Su})}function de(t,e){return ln(t,"POST","template",{template:e})}function ve(t){return t.set("isListening",!0)}function ye(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)}))}function Se(t,e){var n=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)}))}function ge(){return ju.getInitialState()}function me(){return ju.getInitialState()}function Ee(){return ju.getInitialState()}function Ie(t){return Nu[t.hassId]}function be(t){var e=Ie(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Ru.VOICE_TRANSMITTING,{finalTranscript:n}),ur.callService(t,"conversation","process",{text:n}).then((function(){t.dispatch(Ru.VOICE_DONE)}),(function(){t.dispatch(Ru.VOICE_ERROR)}))}}function Oe(t){var e=Ie(t);e&&(e.recognition.stop(),Nu[t.hassId]=!1)}function we(t){be(t),Oe(t)}function Te(t){var e=we.bind(null,t);e();var n=new webkitSpeechRecognition;Nu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Ru.VOICE_START)},n.onerror=function(){return t.dispatch(Ru.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ie(t);if(n){for(var r="",i="",o=e.resultIndex;o=n)}function c(t,e){return h(t,e,0)}function f(t,e){return h(t,e,e)}function h(t,e,n){return void 0===t?n:t<0?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function l(t){return v(t)?t:C(t)}function p(t){return y(t)?t:z(t)}function _(t){return S(t)?t:R(t)}function d(t){return v(t)&&!g(t)?t:M(t)}function v(t){return!(!t||!t[dn])}function y(t){return!(!t||!t[vn])}function S(t){return!(!t||!t[yn])}function g(t){return y(t)||S(t)}function m(t){return!(!t||!t[Sn])}function E(t){this.next=t}function I(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function b(){return{value:void 0,done:!0}}function O(t){return!!A(t)}function w(t){return t&&"function"==typeof t.next}function T(t){var e=A(t);return e&&e.call(t)}function A(t){var e=t&&(In&&t[In]||t[bn]);if("function"==typeof e)return e}function D(t){return t&&"number"==typeof t.length}function C(t){return null===t||void 0===t?P():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?P().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():H(t)}function R(t){return null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function M(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function L(t){this._array=t,this.size=t.length}function j(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function N(t){this._iterable=t,this.size=t.length||t.size}function k(t){this._iterator=t,this._iteratorCache=[]}function U(t){return!(!t||!t[wn])}function P(){return Tn||(Tn=new L([]))}function H(t){var e=Array.isArray(t)?new L(t).fromEntrySeq():w(t)?new k(t).fromEntrySeq():O(t)?new N(t).fromEntrySeq():"object"==typeof t?new j(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function x(t){var e=q(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function V(t){var e=q(t)||"object"==typeof t&&new j(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function q(t){return D(t)?new L(t):w(t)?new k(t):O(t)?new N(t):void 0}function F(t,e,n,r){var i=t._cache;if(i){for(var o=i.length-1,u=0;u<=o;u++){var a=i[n?o-u:u];if(e(a[1],r?a[0]:u,t)===!1)return u+1}return u}return t.__iterateUncached(e,n)}function G(t,e,n,r){var i=t._cache;if(i){var o=i.length-1,u=0;return new E(function(){var t=i[n?o-u:u];return u++>o?b():I(e,r?t[0]:u-1,t[1])})}return t.__iteratorUncached(e,n)}function K(){throw TypeError("Abstract")}function Y(){}function B(){}function J(){}function W(t,e){if(t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if(t=t.valueOf(),e=e.valueOf(),t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1}return!("function"!=typeof t.equals||"function"!=typeof e.equals||!t.equals(e))}function X(t,e){return e?Q(e,t,"",{"":t}):Z(t)}function Q(t,e,n,r){return Array.isArray(e)?t.call(r,n,R(e).map((function(n,r){return Q(t,n,r,e)}))):$(e)?t.call(r,n,z(e).map((function(n,r){return Q(t,n,r,e)}))):e}function Z(t){return Array.isArray(t)?R(t).map(Z).toList():$(t)?z(t).map(Z).toMap():t}function $(t){return t&&(t.constructor===Object||void 0===t.constructor)}function tt(t){return t>>>1&1073741824|3221225471&t}function et(t){if(t===!1||null===t||void 0===t)return 0;if("function"==typeof t.valueOf&&(t=t.valueOf(),t===!1||null===t||void 0===t))return 0;if(t===!0)return 1;var e=typeof t;if("number"===e){var n=0|t;for(n!==t&&(n^=4294967295*t);t>4294967295;)t/=4294967295,n^=t;return tt(n)}return"string"===e?t.length>jn?nt(t):rt(t):"function"==typeof t.hashCode?t.hashCode():it(t)}function nt(t){var e=Un[t];return void 0===e&&(e=rt(t),kn===Nn&&(kn=0,Un={}),kn++,Un[t]=e),e}function rt(t){for(var e=0,n=0;n0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}function ut(t,e){if(!t)throw new Error(e)}function at(t){ut(t!==1/0,"Cannot perform this action with an infinite size.")}function st(t,e){this._iter=t,this._useKeys=e,this.size=t.size}function ct(t){this._iter=t,this.size=t.size}function ft(t){this._iter=t,this.size=t.size}function ht(t){this._iter=t,this.size=t.size}function lt(t){var e=Lt(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=jt,e.__iterateUncached=function(e,n){var r=this;return t.__iterate((function(t,n){return e(n,t,r)!==!1}),n)},e.__iteratorUncached=function(e,n){if(e===En){var r=t.__iterator(e,n);return new E(function(){var t=r.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t})}return t.__iterator(e===mn?gn:mn,n)},e}function pt(t,e,n){var r=Lt(t);return r.size=t.size,r.has=function(e){return t.has(e)},r.get=function(r,i){var o=t.get(r,ln);return o===ln?i:e.call(n,o,r,t)},r.__iterateUncached=function(r,i){var o=this;return t.__iterate((function(t,i,u){return r(e.call(n,t,i,u),i,o)!==!1}),i)},r.__iteratorUncached=function(r,i){var o=t.__iterator(En,i);return new E(function(){var i=o.next();if(i.done)return i;var u=i.value,a=u[0];return I(r,a,e.call(n,u[1],a,t),i)})},r}function _t(t,e){var n=Lt(t);return n._iter=t,n.size=t.size,n.reverse=function(){return t},t.flip&&(n.flip=function(){var e=lt(t);return e.reverse=function(){return t.flip()},e}),n.get=function(n,r){return t.get(e?n:-1-n,r)},n.has=function(n){return t.has(e?n:-1-n)},n.includes=function(e){return t.includes(e)},n.cacheResult=jt,n.__iterate=function(e,n){var r=this;return t.__iterate((function(t,n){return e(t,n,r)}),!n)},n.__iterator=function(e,n){return t.__iterator(e,!n)},n}function dt(t,e,n,r){var i=Lt(t);return r&&(i.has=function(r){var i=t.get(r,ln);return i!==ln&&!!e.call(n,i,r,t)},i.get=function(r,i){var o=t.get(r,ln);return o!==ln&&e.call(n,o,r,t)?o:i}),i.__iterateUncached=function(i,o){var u=this,a=0;return t.__iterate((function(t,o,s){if(e.call(n,t,o,s))return a++,i(t,r?o:a-1,u)}),o),a},i.__iteratorUncached=function(i,o){var u=t.__iterator(En,o),a=0;return new E(function(){for(;;){var o=u.next();if(o.done)return o;var s=o.value,c=s[0],f=s[1];if(e.call(n,f,c,t))return I(i,r?c:a++,f,o)}})},i}function vt(t,e,n){var r=Ut().asMutable();return t.__iterate((function(i,o){r.update(e.call(n,i,o,t),0,(function(t){return t+1}))})),r.asImmutable()}function yt(t,e,n){var r=y(t),i=(m(t)?be():Ut()).asMutable();t.__iterate((function(o,u){i.update(e.call(n,o,u,t),(function(t){return t=t||[],t.push(r?[u,o]:o),t}))}));var o=Mt(t);return i.map((function(e){return Ct(t,o(e))}))}function St(t,e,n,r){var i=t.size;if(void 0!==e&&(e=0|e),void 0!==n&&(n=0|n),s(e,n,i))return t;var o=c(e,i),a=f(n,i);if(o!==o||a!==a)return St(t.toSeq().cacheResult(),e,n,r);var h,l=a-o;l===l&&(h=l<0?0:l);var p=Lt(t);return p.size=0===h?h:t.size&&h||void 0,!r&&U(t)&&h>=0&&(p.get=function(e,n){return e=u(this,e),e>=0&&eh)return b();var t=i.next();return r||e===mn?t:e===gn?I(e,a-1,void 0,t):I(e,a-1,t.value[1],t)})},p}function gt(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterate(r,i);var u=0;return t.__iterate((function(t,i,a){return e.call(n,t,i,a)&&++u&&r(t,i,o)})),u},r.__iteratorUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterator(r,i);var u=t.__iterator(En,i),a=!0;return new E(function(){if(!a)return b();var t=u.next();if(t.done)return t;var i=t.value,s=i[0],c=i[1];return e.call(n,c,s,o)?r===En?t:I(r,s,c,t):(a=!1,b())})},r}function mt(t,e,n,r){var i=Lt(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var a=!0,s=0;return t.__iterate((function(t,o,c){if(!a||!(a=e.call(n,t,o,c)))return s++,i(t,r?o:s-1,u)})),s},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var a=t.__iterator(En,o),s=!0,c=0;return new E(function(){var t,o,f;do{if(t=a.next(),t.done)return r||i===mn?t:i===gn?I(i,c++,void 0,t):I(i,c++,t.value[1],t);var h=t.value;o=h[0],f=h[1],s&&(s=e.call(n,f,o,u))}while(s);return i===En?t:I(i,o,f,t)})},i}function Et(t,e){var n=y(t),r=[t].concat(e).map((function(t){return v(t)?n&&(t=p(t)):t=n?H(t):x(Array.isArray(t)?t:[t]),t})).filter((function(t){return 0!==t.size}));if(0===r.length)return t;if(1===r.length){var i=r[0];if(i===t||n&&y(i)||S(t)&&S(i))return i}var o=new L(r);return n?o=o.toKeyedSeq():S(t)||(o=o.toSetSeq()),o=o.flatten(!0),o.size=r.reduce((function(t,e){if(void 0!==t){var n=e.size;if(void 0!==n)return t+n}}),0),o}function It(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){function o(t,s){var c=this;t.__iterate((function(t,i){return(!e||s0}function Dt(t,e,n){var r=Lt(t);return r.size=new L(n).map((function(t){return t.size})).min(),r.__iterate=function(t,e){for(var n,r=this,i=this.__iterator(mn,e),o=0;!(n=i.next()).done&&t(n.value,o++,r)!==!1;);return o},r.__iteratorUncached=function(t,r){var i=n.map((function(t){return t=l(t),T(r?t.reverse():t)})),o=0,u=!1;return new E(function(){var n;return u||(n=i.map((function(t){return t.next()})),u=n.some((function(t){ -return t.done}))),u?b():I(t,o++,e.apply(null,n.map((function(t){return t.value}))))})},r}function Ct(t,e){return U(t)?e:t.constructor(e)}function zt(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function Rt(t){return at(t.size),o(t)}function Mt(t){return y(t)?p:S(t)?_:d}function Lt(t){return Object.create((y(t)?z:S(t)?R:M).prototype)}function jt(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):C.prototype.cacheResult.call(this)}function Nt(t,e){return t>e?1:t>>n)&hn,a=(0===n?r:r>>>n)&hn,s=u===a?[Zt(t,e,n+cn,r,i)]:(o=new Ft(e,r,i),u>>=1)u[a]=1&n?e[o++]:void 0;return u[r]=i,new Vt(t,o+1,u)}function ne(t,e,n){for(var r=[],i=0;i>1&1431655765,t=(858993459&t)+(t>>2&858993459),t=t+(t>>4)&252645135,t+=t>>8,t+=t>>16,127&t}function ae(t,e,n,r){var o=r?t:i(t);return o[e]=n,o}function se(t,e,n,r){var i=t.length+1;if(r&&e+1===i)return t[e]=n,t;for(var o=new Array(i),u=0,a=0;a0&&ro?0:o-n,c=u-n;return c>fn&&(c=fn),function(){if(i===c)return Bn;var t=e?--c:i++;return r&&r[t]}}function i(t,r,i){var a,s=t&&t.array,c=i>o?0:o-i>>r,f=(u-i>>r)+1;return f>fn&&(f=fn),function(){for(;;){if(a){var t=a();if(t!==Bn)return t;a=null}if(c===f)return Bn;var o=e?--f:c++;a=n(s&&s[o],r-cn,i+(o<=t.size||n<0)return t.withMutations((function(t){n<0?me(t,n).set(0,r):me(t,0,n+1).set(n,r)}));n+=t._origin;var i=t._tail,o=t._root,a=e(_n);return n>=Ie(t._capacity)?i=ye(i,t.__ownerID,0,n,r,a):o=ye(o,t.__ownerID,t._level,n,r,a),a.value?t.__ownerID?(t._root=o,t._tail=i,t.__hash=void 0,t.__altered=!0,t):_e(t._origin,t._capacity,t._level,o,i):t}function ye(t,e,r,i,o,u){var a=i>>>r&hn,s=t&&a0){var f=t&&t.array[a],h=ye(f,e,r-cn,i,o,u);return h===f?t:(c=Se(t,e),c.array[a]=h,c)}return s&&t.array[a]===o?t:(n(u),c=Se(t,e),void 0===o&&a===c.array.length-1?c.array.pop():c.array[a]=o,c)}function Se(t,e){return e&&t&&e===t.ownerID?t:new le(t?t.array.slice():[],e)}function ge(t,e){if(e>=Ie(t._capacity))return t._tail;if(e<1<0;)n=n.array[e>>>r&hn],r-=cn;return n}}function me(t,e,n){void 0!==e&&(e=0|e),void 0!==n&&(n=0|n);var i=t.__ownerID||new r,o=t._origin,u=t._capacity,a=o+e,s=void 0===n?u:n<0?u+n:o+n;if(a===o&&s===u)return t;if(a>=s)return t.clear();for(var c=t._level,f=t._root,h=0;a+h<0;)f=new le(f&&f.array.length?[void 0,f]:[],i),c+=cn,h+=1<=1<l?new le([],i):_;if(_&&p>l&&acn;y-=cn){var S=l>>>y&hn;v=v.array[S]=Se(v.array[S],i)}v.array[l>>>cn&hn]=_}if(s=p)a-=p,s-=p,c=cn,f=null,d=d&&d.removeBefore(i,0,a);else if(a>o||p>>c&hn;if(g!==p>>>c&hn)break;g&&(h+=(1<o&&(f=f.removeBefore(i,c,a-h)),f&&pi&&(i=a.size),v(u)||(a=a.map((function(t){return X(t)}))),r.push(a)}return i>t.size&&(t=t.setSize(i)),ie(t,e,r)}function Ie(t){return t>>cn<=fn&&u.size>=2*o.size?(i=u.filter((function(t,e){return void 0!==t&&a!==e})),r=i.toKeyedSeq().map((function(t){return t[0]})).flip().toMap(),t.__ownerID&&(r.__ownerID=i.__ownerID=t.__ownerID)):(r=o.remove(e),i=a===u.size-1?u.pop():u.set(a,void 0))}else if(s){if(n===u.get(a)[1])return t;r=o,i=u.set(a,[e,n])}else r=o.set(e,u.size),i=u.set(u.size,[e,n]);return t.__ownerID?(t.size=r.size,t._map=r,t._list=i,t.__hash=void 0,t):we(r,i)}function De(t){return null===t||void 0===t?Re():Ce(t)?t:Re().unshiftAll(t)}function Ce(t){return!(!t||!t[Wn])}function ze(t,e,n,r){var i=Object.create(Xn);return i.size=t,i._head=e,i.__ownerID=n,i.__hash=r,i.__altered=!1,i}function Re(){return Qn||(Qn=ze(0))}function Me(t){return null===t||void 0===t?ke():Le(t)&&!m(t)?t:ke().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Le(t){return!(!t||!t[Zn])}function je(t,e){return t.__ownerID?(t.size=e.size,t._map=e,t):e===t._map?t:0===e.size?t.__empty():t.__make(e)}function Ne(t,e){var n=Object.create($n);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function ke(){return tr||(tr=Ne(Jt()))}function Ue(t){return null===t||void 0===t?xe():Pe(t)?t:xe().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Pe(t){return Le(t)&&m(t)}function He(t,e){var n=Object.create(er);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function xe(){return nr||(nr=He(Te()))}function Ve(t,e){var n,r=function(o){if(o instanceof r)return o;if(!(this instanceof r))return new r(o);if(!n){n=!0;var u=Object.keys(t);Ge(i,u),i.size=u.length,i._name=e,i._keys=u,i._defaultValues=t}this._map=Ut(o)},i=r.prototype=Object.create(rr);return i.constructor=r,r}function qe(t,e,n){var r=Object.create(Object.getPrototypeOf(t));return r._map=e,r.__ownerID=n,r}function Fe(t){return t._name||t.constructor.name||"Record"}function Ge(t,e){try{e.forEach(Ke.bind(void 0,t))}catch(t){}}function Ke(t,e){Object.defineProperty(t,e,{get:function(){return this.get(e)},set:function(t){ut(this.__ownerID,"Cannot set on an immutable record."),this.set(e,t)}})}function Ye(t,e){if(t===e)return!0;if(!v(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||y(t)!==y(e)||S(t)!==S(e)||m(t)!==m(e))return!1;if(0===t.size&&0===e.size)return!0;var n=!g(t);if(m(t)){var r=t.entries();return e.every((function(t,e){var i=r.next().value;return i&&W(i[1],t)&&(n||W(i[0],e))}))&&r.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var o=t;t=e,e=o}var u=!0,a=e.__iterate((function(e,r){if(n?!t.has(e):i?!W(e,t.get(r,ln)):!W(t.get(r,ln),e))return u=!1,!1}));return u&&t.size===a}function Be(t,e,n){if(!(this instanceof Be))return new Be(t,e,n);if(ut(0!==n,"Cannot step a Range by 0"),t=t||0,void 0===e&&(e=1/0),n=void 0===n?1:Math.abs(n),ee?-1:0}function rn(t){if(t.size===1/0)return 0;var e=m(t),n=y(t),r=e?1:0,i=t.__iterate(n?e?function(t,e){r=31*r+un(et(t),et(e))|0}:function(t,e){r=r+un(et(t),et(e))|0}:e?function(t){r=31*r+et(t)|0}:function(t){r=r+et(t)|0});return on(i,r)}function on(t,e){return e=Dn(e,3432918353),e=Dn(e<<15|e>>>-15,461845907),e=Dn(e<<13|e>>>-13,5),e=(e+3864292196|0)^t,e=Dn(e^e>>>16,2246822507),e=Dn(e^e>>>13,3266489909),e=tt(e^e>>>16)}function un(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}var an=Array.prototype.slice,sn="delete",cn=5,fn=1<r?b():I(t,i,n[e?r-i++:i++])})},t(j,z),j.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},j.prototype.has=function(t){return this._object.hasOwnProperty(t)},j.prototype.__iterate=function(t,e){for(var n=this,r=this._object,i=this._keys,o=i.length-1,u=0;u<=o;u++){var a=i[e?o-u:u];if(t(r[a],a,n)===!1)return u+1}return u},j.prototype.__iterator=function(t,e){var n=this._object,r=this._keys,i=r.length-1,o=0;return new E(function(){var u=r[e?i-o:o];return o++>i?b():I(t,u,n[u])})},j.prototype[Sn]=!0,t(N,R),N.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);var r=this._iterable,i=T(r),o=0;if(w(i))for(var u;!(u=i.next()).done&&t(u.value,o++,n)!==!1;);return o},N.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var n=this._iterable,r=T(n);if(!w(r))return new E(b);var i=0;return new E(function(){var e=r.next();return e.done?e:I(t,i++,e.value)})},t(k,R),k.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);for(var r=this._iterator,i=this._iteratorCache,o=0;o=r.length){var e=n.next();if(e.done)return e;r[i]=e.value}return I(t,i,r[i++])})};var Tn;t(K,l),t(Y,K),t(B,K),t(J,K),K.Keyed=Y,K.Indexed=B,K.Set=J;var An,Dn="function"==typeof Math.imul&&Math.imul(4294967295,2)===-2?Math.imul:function(t,e){t=0|t,e=0|e;var n=65535&t,r=65535&e;return n*r+((t>>>16)*r+n*(e>>>16)<<16>>>0)|0},Cn=Object.isExtensible,zn=(function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}})(),Rn="function"==typeof WeakMap;Rn&&(An=new WeakMap);var Mn=0,Ln="__immutablehash__";"function"==typeof Symbol&&(Ln=Symbol(Ln));var jn=16,Nn=255,kn=0,Un={};t(st,z),st.prototype.get=function(t,e){return this._iter.get(t,e)},st.prototype.has=function(t){return this._iter.has(t)},st.prototype.valueSeq=function(){return this._iter.valueSeq()},st.prototype.reverse=function(){var t=this,e=_t(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},st.prototype.map=function(t,e){var n=this,r=pt(this,t,e);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(t,e)}),r},st.prototype.__iterate=function(t,e){var n,r=this;return this._iter.__iterate(this._useKeys?function(e,n){return t(e,n,r)}:(n=e?Rt(this):0,function(i){return t(i,e?--n:n++,r)}),e)},st.prototype.__iterator=function(t,e){if(this._useKeys)return this._iter.__iterator(t,e);var n=this._iter.__iterator(mn,e),r=e?Rt(this):0;return new E(function(){var i=n.next();return i.done?i:I(t,e?--r:r++,i.value,i)})},st.prototype[Sn]=!0,t(ct,R),ct.prototype.includes=function(t){return this._iter.includes(t)},ct.prototype.__iterate=function(t,e){var n=this,r=0;return this._iter.__iterate((function(e){return t(e,r++,n)}),e)},ct.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e),r=0;return new E(function(){var e=n.next();return e.done?e:I(t,r++,e.value,e)})},t(ft,M),ft.prototype.has=function(t){return this._iter.includes(t)},ft.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){return t(e,e,n)}),e)},ft.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e);return new E(function(){var e=n.next();return e.done?e:I(t,e.value,e.value,e)})},t(ht,z),ht.prototype.entrySeq=function(){return this._iter.toSeq()},ht.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){if(e){zt(e);var r=v(e);return t(r?e.get(1):e[1],r?e.get(0):e[0],n)}}),e)},ht.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e);return new E(function(){for(;;){var e=n.next();if(e.done)return e;var r=e.value;if(r){zt(r);var i=v(r);return I(t,i?r.get(0):r[0],i?r.get(1):r[1],e)}}})},ct.prototype.cacheResult=st.prototype.cacheResult=ft.prototype.cacheResult=ht.prototype.cacheResult=jt,t(Ut,Y),Ut.prototype.toString=function(){return this.__toString("Map {","}")},Ut.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},Ut.prototype.set=function(t,e){return Wt(this,t,e)},Ut.prototype.setIn=function(t,e){return this.updateIn(t,ln,(function(){return e}))},Ut.prototype.remove=function(t){return Wt(this,t,ln)},Ut.prototype.deleteIn=function(t){return this.updateIn(t,(function(){return ln}))},Ut.prototype.update=function(t,e,n){return 1===arguments.length?t(this):this.updateIn([t],e,n)},Ut.prototype.updateIn=function(t,e,n){n||(n=e,e=void 0);var r=oe(this,kt(t),e,n);return r===ln?void 0:r},Ut.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Jt()},Ut.prototype.merge=function(){return ne(this,void 0,arguments)},Ut.prototype.mergeWith=function(t){var e=an.call(arguments,1);return ne(this,t,e)},Ut.prototype.mergeIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]}))},Ut.prototype.mergeDeep=function(){return ne(this,re(void 0),arguments)},Ut.prototype.mergeDeepWith=function(t){var e=an.call(arguments,1);return ne(this,re(t),e)},Ut.prototype.mergeDeepIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]}))},Ut.prototype.sort=function(t){return be(wt(this,t))},Ut.prototype.sortBy=function(t,e){return be(wt(this,e,t))},Ut.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},Ut.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new r)},Ut.prototype.asImmutable=function(){return this.__ensureOwner()},Ut.prototype.wasAltered=function(){return this.__altered},Ut.prototype.__iterator=function(t,e){return new Gt(this,t,e)},Ut.prototype.__iterate=function(t,e){var n=this,r=0;return this._root&&this._root.iterate((function(e){return r++,t(e[1],e[0],n)}),e),r},Ut.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Bt(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Ut.isMap=Pt;var Pn="@@__IMMUTABLE_MAP__@@",Hn=Ut.prototype;Hn[Pn]=!0,Hn[sn]=Hn.remove,Hn.removeIn=Hn.deleteIn,Ht.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;o=Vn)return $t(t,f,o,u);var _=t&&t===this.ownerID,d=_?f:i(f);return p?c?h===l-1?d.pop():d[h]=d.pop():d[h]=[o,u]:d.push([o,u]),_?(this.entries=d,this):new Ht(t,d)}},xt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=1<<((0===t?e:e>>>t)&hn),o=this.bitmap;return 0===(o&i)?r:this.nodes[ue(o&i-1)].get(t+cn,e,n,r)},xt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=1<=qn)return ee(t,l,c,a,_);if(f&&!_&&2===l.length&&Qt(l[1^h]))return l[1^h];if(f&&_&&1===l.length&&Qt(_))return _;var d=t&&t===this.ownerID,v=f?_?c:c^s:c|s,y=f?_?ae(l,h,_,d):ce(l,h,d):se(l,h,_,d);return d?(this.bitmap=v,this.nodes=y,this):new xt(t,v,y)},Vt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=(0===t?e:e>>>t)&hn,o=this.nodes[i];return o?o.get(t+cn,e,n,r):r},Vt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=i===ln,c=this.nodes,f=c[a];if(s&&!f)return this;var h=Xt(f,t,e+cn,n,r,i,o,u);if(h===f)return this;var l=this.count;if(f){if(!h&&(l--,l=0&&t>>e&hn;if(r>=this.array.length)return new le([],t);var i,o=0===r;if(e>0){var u=this.array[r];if(i=u&&u.removeBefore(t,e-cn,n),i===u&&o)return this}if(o&&!i)return this;var a=Se(this,t);if(!o)for(var s=0;s>>e&hn;if(r>=this.array.length)return this;var i;if(e>0){var o=this.array[r];if(i=o&&o.removeAfter(t,e-cn,n),i===o&&r===this.array.length-1)return this}var u=Se(this,t);return u.array.splice(r+1),i&&(u.array[r]=i),u};var Yn,Bn={};t(be,Ut),be.of=function(){return this(arguments)},be.prototype.toString=function(){return this.__toString("OrderedMap {","}")},be.prototype.get=function(t,e){var n=this._map.get(t);return void 0!==n?this._list.get(n)[1]:e},be.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):Te()},be.prototype.set=function(t,e){return Ae(this,t,e)},be.prototype.remove=function(t){return Ae(this,t,ln)},be.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},be.prototype.__iterate=function(t,e){var n=this;return this._list.__iterate((function(e){return e&&t(e[1],e[0],n)}),e)},be.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},be.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),n=this._list.__ensureOwner(t);return t?we(e,n,t,this.__hash):(this.__ownerID=t,this._map=e,this._list=n,this)},be.isOrderedMap=Oe,be.prototype[Sn]=!0,be.prototype[sn]=be.prototype.remove;var Jn;t(De,B),De.of=function(){return this(arguments)},De.prototype.toString=function(){return this.__toString("Stack [","]")},De.prototype.get=function(t,e){var n=this._head;for(t=u(this,t);n&&t--;)n=n.next;return n?n.value:e},De.prototype.peek=function(){return this._head&&this._head.value},De.prototype.push=function(){var t=arguments;if(0===arguments.length)return this;for(var e=this.size+arguments.length,n=this._head,r=arguments.length-1;r>=0;r--)n={value:t[r],next:n};return this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pushAll=function(t){if(t=_(t),0===t.size)return this;at(t.size);var e=this.size,n=this._head;return t.reverse().forEach((function(t){e++,n={value:t,next:n}})),this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pop=function(){return this.slice(1)},De.prototype.unshift=function(){return this.push.apply(this,arguments)},De.prototype.unshiftAll=function(t){return this.pushAll(t)},De.prototype.shift=function(){return this.pop.apply(this,arguments)},De.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Re()},De.prototype.slice=function(t,e){if(s(t,e,this.size))return this;var n=c(t,this.size),r=f(e,this.size);if(r!==this.size)return B.prototype.slice.call(this,t,e);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):ze(i,o)},De.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?ze(this.size,this._head,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},De.prototype.__iterate=function(t,e){var n=this;if(e)return this.reverse().__iterate(t);for(var r=0,i=this._head;i&&t(i.value,r++,n)!==!1;)i=i.next;return r},De.prototype.__iterator=function(t,e){if(e)return this.reverse().__iterator(t);var n=0,r=this._head;return new E(function(){if(r){var e=r.value;return r=r.next,I(t,n++,e)}return b()})},De.isStack=Ce;var Wn="@@__IMMUTABLE_STACK__@@",Xn=De.prototype;Xn[Wn]=!0,Xn.withMutations=Hn.withMutations,Xn.asMutable=Hn.asMutable,Xn.asImmutable=Hn.asImmutable,Xn.wasAltered=Hn.wasAltered;var Qn;t(Me,J),Me.of=function(){return this(arguments)},Me.fromKeys=function(t){return this(p(t).keySeq())},Me.prototype.toString=function(){return this.__toString("Set {","}")},Me.prototype.has=function(t){return this._map.has(t)},Me.prototype.add=function(t){return je(this,this._map.set(t,!0))},Me.prototype.remove=function(t){return je(this,this._map.remove(t))},Me.prototype.clear=function(){return je(this,this._map.clear())},Me.prototype.union=function(){var t=an.call(arguments,0);return t=t.filter((function(t){return 0!==t.size})),0===t.length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations((function(e){for(var n=0;n1?" by "+this._step:"")+" ]"},Be.prototype.get=function(t,e){return this.has(t)?this._start+u(this,t)*this._step:e},Be.prototype.includes=function(t){var e=(t-this._start)/this._step;return e>=0&&e=0&&nn?b():I(t,o++,u)})},Be.prototype.equals=function(t){return t instanceof Be?this._start===t._start&&this._end===t._end&&this._step===t._step:Ye(this,t)};var ir;t(Je,R),Je.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Je.prototype.get=function(t,e){return this.has(t)?this._value:e},Je.prototype.includes=function(t){return W(this._value,t)},Je.prototype.slice=function(t,e){var n=this.size;return s(t,e,n)?this:new Je(this._value,f(e,n)-c(t,n))},Je.prototype.reverse=function(){return this},Je.prototype.indexOf=function(t){return W(this._value,t)?0:-1},Je.prototype.lastIndexOf=function(t){return W(this._value,t)?this.size:-1},Je.prototype.__iterate=function(t,e){for(var n=this,r=0;rthis.size?e:this.find((function(e,n){return n===t}),void 0,e)},has:function(t){return t=u(this,t),t>=0&&(void 0!==this.size?this.size===1/0||t-1&&t%1===0&&t<=Number.MAX_VALUE}var i=Function.prototype.bind;e.isString=function(t){return"string"==typeof t||"[object String]"===n(t)},e.isArray=Array.isArray||function(t){return"[object Array]"===n(t)},"function"!=typeof/./&&"object"!=typeof Int8Array?e.isFunction=function(t){return"function"==typeof t||!1}:e.isFunction=function(t){return"[object Function]"===toString.call(t)},e.isObject=function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},e.extend=function(t){var e=arguments,n=arguments.length;if(!t||n<2)return t||{};for(var r=1;r0)){var e=this.reactorState.get("dirtyStores");if(0!==e.size){var n=c.default.Set().withMutations((function(n){n.union(t.observerState.get("any")),e.forEach((function(e){var r=t.observerState.getIn(["stores",e]);r&&n.union(r)}))}));n.forEach((function(e){var n=t.observerState.getIn(["observersMap",e]);if(n){var r=n.get("getter"),i=n.get("handler"),o=p.evaluate(t.prevReactorState,r),u=p.evaluate(t.reactorState,r);t.prevReactorState=o.reactorState,t.reactorState=u.reactorState;var a=o.result,s=u.result;c.default.is(a,s)||i.call(null,s)}}));var r=p.resetDirtyStores(this.reactorState);this.prevReactorState=r,this.reactorState=r}}}},{key:"batchStart",value:function(){this.__batchDepth++}},{key:"batchEnd",value:function(){if(this.__batchDepth--,this.__batchDepth<=0){this.__isDispatching=!0;try{this.__notify()}catch(t){throw this.__isDispatching=!1,t}this.__isDispatching=!1}}}]),t})();e.default=(0,y.toFactory)(g),t.exports=e.default},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n={};return(0,o.each)(e,(function(e,r){n[r]=t.evaluate(e)})),n}Object.defineProperty(e,"__esModule",{value:!0});var o=n(4);e.default=function(t){return{getInitialState:function(){return i(t,this.getDataBindings())},componentDidMount:function(){var e=this;this.__unwatchFns=[],(0,o.each)(this.getDataBindings(),(function(n,i){var o=t.observe(n,(function(t){e.setState(r({},i,t))}));e.__unwatchFns.push(o)}))},componentWillUnmount:function(){for(var t=this;this.__unwatchFns.length;)t.__unwatchFns.shift()()}}},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t,e){return new M({result:t,reactorState:e})}function o(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.getIn(["stores",n])&&console.warn("Store already defined for id = "+n);var r=e.getInitialState();if(void 0===r&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store getInitialState() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(r))throw new Error("Store getInitialState() must return an immutable value, did you forget to call toImmutable");t.update("stores",(function(t){return t.set(n,e)})).update("state",(function(t){return t.set(n,r)})).update("dirtyStores",(function(t){return t.add(n)})).update("storeStates",(function(t){return b(t,[n])}))})),I(t)}))}function u(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.update("stores",(function(t){return t.set(n,e)}))}))}))}function a(t,e,n){if(void 0===e&&f(t,"throwOnUndefinedActionType"))throw new Error("`dispatch` cannot be called with an `undefined` action type.");var r=t.get("state"),i=t.get("dirtyStores"),o=r.withMutations((function(r){A.default.dispatchStart(t,e,n),t.get("stores").forEach((function(o,u){var a=r.get(u),s=void 0;try{s=o.handle(a,e,n)}catch(e){throw A.default.dispatchError(t,e.message),e}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var c="Store handler must return a value, did you forget a return statement";throw A.default.dispatchError(t,c),new Error(c)}r.set(u,s),a!==s&&(i=i.add(u))})),A.default.dispatchEnd(t,r,i)})),u=t.set("state",o).set("dirtyStores",i).update("storeStates",(function(t){return b(t,i)}));return I(u)}function s(t,e){var n=[],r=(0,D.toImmutable)({}).withMutations((function(r){(0,R.each)(e,(function(e,i){var o=t.getIn(["stores",i]);if(o){var u=o.deserialize(e);void 0!==u&&(r.set(i,u),n.push(i))}}))})),i=w.default.Set(n);return t.update("state",(function(t){return t.merge(r)})).update("dirtyStores",(function(t){return t.union(i)})).update("storeStates",(function(t){return b(t,n)}))}function c(t,e,n){var r=e;(0,z.isKeyPath)(e)&&(e=(0,C.fromKeyPath)(e));var i=t.get("nextId"),o=(0,C.getStoreDeps)(e),u=w.default.Map({id:i,storeDeps:o,getterKey:r,getter:e,handler:n}),a=void 0;return a=0===o.size?t.update("any",(function(t){return t.add(i)})):t.withMutations((function(t){o.forEach((function(e){var n=["stores",e];t.hasIn(n)||t.setIn(n,w.default.Set()),t.updateIn(["stores",e],(function(t){return t.add(i)}))}))})),a=a.set("nextId",i+1).setIn(["observersMap",i],u),{observerState:a,entry:u}}function f(t,e){var n=t.getIn(["options",e]);if(void 0===n)throw new Error("Invalid option: "+e);return n}function h(t,e,n){var r=t.get("observersMap").filter((function(t){var r=t.get("getterKey"),i=!n||t.get("handler")===n;return!!i&&((0,z.isKeyPath)(e)&&(0,z.isKeyPath)(r)?(0,z.isEqual)(e,r):e===r)}));return t.withMutations((function(t){r.forEach((function(e){return l(t,e)}))}))}function l(t,e){return t.withMutations((function(t){var n=e.get("id"),r=e.get("storeDeps");0===r.size?t.update("any",(function(t){return t.remove(n)})):r.forEach((function(e){t.updateIn(["stores",e],(function(t){return t?t.remove(n):t}))})),t.removeIn(["observersMap",n])}))}function p(t){var e=t.get("state");return t.withMutations((function(t){var n=t.get("stores"),r=n.keySeq().toJS();n.forEach((function(n,r){var i=e.get(r),o=n.handleReset(i);if(void 0===o&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store handleReset() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(o))throw new Error("Store reset state must be an immutable value, did you forget to call toImmutable");t.setIn(["state",r],o)})),t.update("storeStates",(function(t){return b(t,r)})),v(t)}))}function _(t,e){var n=t.get("state");if((0,z.isKeyPath)(e))return i(n.getIn(e),t);if(!(0,C.isGetter)(e))throw new Error("evaluate must be passed a keyPath or Getter");if(g(t,e))return i(E(t,e),t);var r=(0,C.getDeps)(e).map((function(e){return _(t,e).result})),o=(0,C.getComputeFn)(e).apply(null,r);return i(o,m(t,e,o))}function d(t){var e={};return t.get("stores").forEach((function(n,r){var i=t.getIn(["state",r]),o=n.serialize(i);void 0!==o&&(e[r]=o)})),e}function v(t){return t.set("dirtyStores",w.default.Set())}function y(t){return t}function S(t,e){var n=y(e);return t.getIn(["cache",n])}function g(t,e){var n=S(t,e);if(!n)return!1;var r=n.get("storeStates");return 0!==r.size&&r.every((function(e,n){return t.getIn(["storeStates",n])===e}))}function m(t,e,n){var r=y(e),i=t.get("dispatchId"),o=(0,C.getStoreDeps)(e),u=(0,D.toImmutable)({}).withMutations((function(e){o.forEach((function(n){var r=t.getIn(["storeStates",n]);e.set(n,r)}))}));return t.setIn(["cache",r],w.default.Map({value:n,storeStates:u,dispatchId:i}))}function E(t,e){var n=y(e);return t.getIn(["cache",n,"value"])}function I(t){return t.update("dispatchId",(function(t){return t+1}))}function b(t,e){return t.withMutations((function(t){e.forEach((function(e){var n=t.has(e)?t.get(e)+1:1;t.set(e,n)}))}))}Object.defineProperty(e,"__esModule",{value:!0}),e.registerStores=o,e.replaceStores=u,e.dispatch=a,e.loadState=s,e.addObserver=c,e.getOption=f,e.removeObserver=h,e.removeObserverByEntry=l,e.reset=p,e.evaluate=_,e.serialize=d,e.resetDirtyStores=v;var O=n(3),w=r(O),T=n(9),A=r(T),D=n(5),C=n(10),z=n(11),R=n(4),M=w.default.Record({result:null,reactorState:null})},function(t,e,n){var r=n(8);e.dispatchStart=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.groupCollapsed("Dispatch: %s",e),console.group("payload"),console.debug(n),console.groupEnd())},e.dispatchError=function(t,e){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.debug("Dispatch error: "+e),console.groupEnd())},e.dispatchEnd=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&((0,r.getOption)(t,"logDirtyStores")&&console.log("Stores updated:",n.toList().toJS()),(0,r.getOption)(t,"logAppState")&&console.debug("Dispatch done, new state: ",e.toJS()),console.groupEnd())}},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,l.isArray)(t)&&(0,l.isFunction)(t[t.length-1])}function o(t){return t[t.length-1]}function u(t){return t.slice(0,t.length-1)}function a(t,e){e||(e=h.default.Set());var n=h.default.Set().withMutations((function(e){if(!i(t))throw new Error("getFlattenedDeps must be passed a Getter");u(t).forEach((function(t){if((0,p.isKeyPath)(t))e.add((0,f.List)(t));else{if(!i(t))throw new Error("Invalid getter, each dependency must be a KeyPath or Getter");e.union(a(t))}}))}));return e.union(n)}function s(t){if(!(0,p.isKeyPath)(t))throw new Error("Cannot create Getter from KeyPath: "+t);return[t,_]}function c(t){if(t.hasOwnProperty("__storeDeps"))return t.__storeDeps;var e=a(t).map((function(t){return t.first()})).filter((function(t){return!!t}));return Object.defineProperty(t,"__storeDeps",{enumerable:!1,configurable:!1,writable:!1,value:e}),e}Object.defineProperty(e,"__esModule",{value:!0});var f=n(3),h=r(f),l=n(4),p=n(11),_=function(t){return t};e.default={isGetter:i,getComputeFn:o,getFlattenedDeps:a,getStoreDeps:c,getDeps:u,fromKeyPath:s},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,s.isArray)(t)&&!(0,s.isFunction)(t[t.length-1])}function o(t,e){var n=a.default.List(t),r=a.default.List(e);return a.default.is(n,r)}Object.defineProperty(e,"__esModule",{value:!0}),e.isKeyPath=i,e.isEqual=o;var u=n(3),a=r(u),s=n(4)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=(0,r.Map)({logDispatches:!1,logAppState:!1,logDirtyStores:!1,throwOnUndefinedActionType:!1,throwOnUndefinedStoreReturnValue:!1,throwOnNonImmutableStore:!1,throwOnDispatchInDispatch:!1});e.PROD_OPTIONS=i;var o=(0,r.Map)({logDispatches:!0,logAppState:!0,logDirtyStores:!0,throwOnUndefinedActionType:!0,throwOnUndefinedStoreReturnValue:!0,throwOnNonImmutableStore:!0,throwOnDispatchInDispatch:!0});e.DEBUG_OPTIONS=o;var u=(0,r.Record)({dispatchId:0,state:(0,r.Map)(),stores:(0,r.Map)(),cache:(0,r.Map)(),storeStates:(0,r.Map)(),dirtyStores:(0,r.Set)(),debug:!1,options:i});e.ReactorState=u;var a=(0,r.Record)({any:(0,r.Set)(),stores:(0,r.Map)({}),observersMap:(0,r.Map)({}),nextId:1});e.ObserverState=a}])}))})),ze=t(Ce),Re=function(t){var e,n={};if(!(t instanceof Object)||Array.isArray(t))throw new Error("keyMirror(...): Argument must be an object.");for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n},Me=Re,Le=Me({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),je=ze.Store,Ne=ze.toImmutable,ke=new je({getInitialState:function(){return Ne({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Le.VALIDATING_AUTH_TOKEN,n),this.on(Le.VALID_AUTH_TOKEN,r),this.on(Le.INVALID_AUTH_TOKEN,i)}}),Ue=ze.Store,Pe=ze.toImmutable,He=new Ue({getInitialState:function(){return Pe({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),xe=ze.Store,Ve=new xe({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),qe=Me({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),Fe="object"==typeof window&&"EventSource"in window,Ge=ze.Store,Ke=ze.toImmutable,Ye=new Ge({getInitialState:function(){return Ke({isSupported:Fe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(qe.STREAM_START,s),this.on(qe.STREAM_STOP,c),this.on(qe.STREAM_ERROR,f),this.on(qe.LOG_OUT,h)}}),Be=Me({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Je=ze.Store,We=new Je({getInitialState:function(){return!0},initialize:function(){this.on(Be.API_FETCH_ALL_START,(function(){return!0})),this.on(Be.API_FETCH_ALL_SUCCESS,(function(){return!1})),this.on(Be.API_FETCH_ALL_FAIL,(function(){return!1})),this.on(Be.LOG_OUT,(function(){return!1}))}}),Xe=ze.Store,Qe=new Xe({getInitialState:function(){return!1},initialize:function(){this.on(Be.SYNC_SCHEDULED,(function(){return!0})),this.on(Be.SYNC_SCHEDULE_CANCELLED,(function(){return!1})),this.on(Be.LOG_OUT,(function(){return!1}))}}),Ze=Me({API_FETCH_SUCCESS:null,API_FETCH_START:null,API_FETCH_FAIL:null,API_SAVE_SUCCESS:null,API_SAVE_START:null,API_SAVE_FAIL:null,API_DELETE_SUCCESS:null,API_DELETE_START:null,API_DELETE_FAIL:null,LOG_OUT:null}),$e=ze.Store,tn=ze.toImmutable,en=new $e({getInitialState:function(){return tn({})},initialize:function(){var t=this;this.on(Ze.API_FETCH_SUCCESS,l),this.on(Ze.API_SAVE_SUCCESS,l),this.on(Ze.API_DELETE_SUCCESS,p),this.on(Ze.LOG_OUT,(function(){return t.getInitialState()}))}}),nn=Object.prototype.hasOwnProperty,rn=Object.prototype.propertyIsEnumerable,on=d()?Object.assign:function(t,e){for(var n,r,i=arguments,o=_(t),u=1;u199&&u.status<300?t(e):n(e)},u.onerror=function(){return n({})},r?(u.setRequestHeader("Content-Type","application/json;charset=UTF-8"),u.send(JSON.stringify(r))):u.send()})}function C(t,e){var n=e.message;return t.set(t.size,n)}function z(){return zn.getInitialState()}function R(t,e){t.dispatch(An.NOTIFICATION_CREATED,{message:e})}function M(t){t.registerStores({notifications:zn})}function L(t,e){if("lock"===t)return!0;if("garage_door"===t)return!0;var n=e.get(t);return!!n&&n.services.has("turn_on")}function j(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:L(t.domain,e))}function N(t,e){return[rr(t),function(t){return!!t&&t.services.has(e)}]}function k(t){return[wn.byId(t),nr,j]}function U(t,e,n){function r(){var c=(new Date).getTime()-a;c0?i=setTimeout(r,e-c):(i=null,n||(s=t.apply(u,o),i||(u=o=null)))}var i,o,u,a,s;null==e&&(e=100);var c=function(){u=this,o=arguments,a=(new Date).getTime();var c=n&&!i;return i||(i=setTimeout(r,e)),c&&(s=t.apply(u,o),u=o=null),s};return c.clear=function(){i&&(clearTimeout(i),i=null)},c}function P(t,e){var n=e.component;return t.push(n)}function H(t,e){var n=e.components;return dr(n)}function x(){return vr.getInitialState()}function V(t,e){var n=e.latitude,r=e.longitude,i=e.location_name,o=e.unit_system,u=e.time_zone,a=e.config_dir,s=e.version;return Sr({latitude:n,longitude:r,location_name:i,unit_system:o,time_zone:u,config_dir:a,serverVersion:s})}function q(){return gr.getInitialState()}function F(t,e){t.dispatch(pr.SERVER_CONFIG_LOADED,e)}function G(t){ln(t,"GET","config").then((function(e){return F(t,e)}))}function K(t,e){t.dispatch(pr.COMPONENT_LOADED,{component:e})}function Y(t){return[["serverComponent"],function(e){return e.contains(t)}]}function B(t){t.registerStores({serverComponent:vr,serverConfig:gr})}function J(t,e){var n=e.pane;return n}function W(){return Rr.getInitialState()}function X(t,e){var n=e.panels;return Lr(n)}function Q(){return jr.getInitialState()}function Z(t,e){var n=e.show;return!!n}function $(){return kr.getInitialState()}function tt(t,e){t.dispatch(Cr.SHOW_SIDEBAR,{show:e})}function et(t,e){t.dispatch(Cr.NAVIGATE,{pane:e})}function nt(t,e){t.dispatch(Cr.PANELS_LOADED,{panels:e})}function rt(t,e){var n=e.entityId;return n}function it(){return Kr.getInitialState()}function ot(t,e){t.dispatch(Fr.SELECT_ENTITY,{entityId:e})}function ut(t){t.dispatch(Fr.SELECT_ENTITY,{entityId:null})}function at(t){return!t||(new Date).getTime()-t>6e4}function st(t,e){var n=e.date;return n.toISOString()}function ct(){return Wr.getInitialState()}function ft(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Qr({})):t.withMutations((function(t){r.forEach((function(e){return t.setIn([n,e[0].entity_id],Qr(e.map(yn.fromJSON)))}))}))}function ht(){return Zr.getInitialState()}function lt(t,e){var n=e.stateHistory;return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,ni(e.map(yn.fromJSON)))}))}))}function pt(){return ri.getInitialState()}function _t(t,e){var n=e.stateHistory,r=(new Date).getTime();return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,r)})),history.length>1&&t.set(ui,r)}))}function dt(){return ai.getInitialState()}function vt(t,e){t.dispatch(Br.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function yt(t,e){void 0===e&&(e=null),t.dispatch(Br.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),ln(t,"GET",n).then((function(e){return t.dispatch(Br.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})}),(function(){return t.dispatch(Br.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})}))}function St(t,e){return t.dispatch(Br.ENTITY_HISTORY_FETCH_START,{date:e}),ln(t,"GET","history/period/"+e).then((function(n){return t.dispatch(Br.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})}),(function(){return t.dispatch(Br.ENTITY_HISTORY_FETCH_ERROR,{})}))}function gt(t){var e=t.evaluate(fi);return St(t,e)}function mt(t){t.registerStores({currentEntityHistoryDate:Wr,entityHistory:Zr,isLoadingEntityHistory:ti,recentEntityHistory:ri,recentEntityHistoryUpdated:ai})}function Et(t){t.registerStores({moreInfoEntityId:Kr})}function It(t,e){var n=e.model,r=e.result,i=e.params;if(null===t||"entity"!==n.entity||!i.replace)return t;for(var o=0;oau}function se(t){t.registerStores({currentLogbookDate:Bo,isLoadingLogbookEntries:Wo,logbookEntries:eu,logbookEntriesUpdated:iu})}function ce(t){return t.set("active",!0)}function fe(t){return t.set("active",!1)}function he(){return gu.getInitialState()}function le(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered.");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){var n;return n=navigator.userAgent.toLowerCase().indexOf("firefox")>-1?"firefox":"chrome",ln(t,"POST","notify.html5",{subscription:e,browser:n}).then((function(){return t.dispatch(vu.PUSH_NOTIFICATIONS_SUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n;return n=e.message&&e.message.indexOf("gcm_sender_id")!==-1?"Please setup the notify.html5 platform.":"Notification registration failed.",console.error(e),Nn.createNotification(t,n),!1}))}function pe(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){return ln(t,"DELETE","notify.html5",{subscription:e}).then((function(){return e.unsubscribe()})).then((function(){return t.dispatch(vu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Nn.createNotification(t,n),!1}))}function _e(t){t.registerStores({pushNotifications:gu})}function de(t,e){return ln(t,"POST","template",{template:e})}function ve(t){return t.set("isListening",!0)}function ye(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)}))}function Se(t,e){var n=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)}))}function ge(){return Nu.getInitialState()}function me(){return Nu.getInitialState()}function Ee(){return Nu.getInitialState()}function Ie(t){return ku[t.hassId]}function be(t){var e=Ie(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Mu.VOICE_TRANSMITTING,{finalTranscript:n}),ur.callService(t,"conversation","process",{text:n}).then((function(){t.dispatch(Mu.VOICE_DONE)}),(function(){t.dispatch(Mu.VOICE_ERROR)}))}}function Oe(t){var e=Ie(t);e&&(e.recognition.stop(),ku[t.hassId]=!1)}function we(t){be(t),Oe(t)}function Te(t){var e=we.bind(null,t);e();var n=new webkitSpeechRecognition;ku[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Mu.VOICE_START)},n.onerror=function(){return t.dispatch(Mu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ie(t);if(n){for(var r="",i="",o=e.resultIndex;o=n)}function c(t,e){return h(t,e,0)}function f(t,e){return h(t,e,e)}function h(t,e,n){return void 0===t?n:t<0?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function l(t){return v(t)?t:C(t)}function p(t){return y(t)?t:z(t)}function _(t){return S(t)?t:R(t)}function d(t){return v(t)&&!g(t)?t:M(t)}function v(t){return!(!t||!t[dn])}function y(t){return!(!t||!t[vn])}function S(t){return!(!t||!t[yn])}function g(t){return y(t)||S(t)}function m(t){return!(!t||!t[Sn])}function E(t){this.next=t}function I(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function b(){return{value:void 0,done:!0}}function O(t){return!!A(t)}function w(t){return t&&"function"==typeof t.next}function T(t){var e=A(t);return e&&e.call(t)}function A(t){var e=t&&(In&&t[In]||t[bn]);if("function"==typeof e)return e}function D(t){return t&&"number"==typeof t.length}function C(t){return null===t||void 0===t?P():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?P().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():H(t)}function R(t){return null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function M(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function L(t){this._array=t,this.size=t.length}function j(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function N(t){this._iterable=t,this.size=t.length||t.size}function k(t){this._iterator=t,this._iteratorCache=[]}function U(t){return!(!t||!t[wn])}function P(){return Tn||(Tn=new L([]))}function H(t){var e=Array.isArray(t)?new L(t).fromEntrySeq():w(t)?new k(t).fromEntrySeq():O(t)?new N(t).fromEntrySeq():"object"==typeof t?new j(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function x(t){var e=q(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function V(t){var e=q(t)||"object"==typeof t&&new j(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function q(t){return D(t)?new L(t):w(t)?new k(t):O(t)?new N(t):void 0}function F(t,e,n,r){var i=t._cache;if(i){for(var o=i.length-1,u=0;u<=o;u++){var a=i[n?o-u:u];if(e(a[1],r?a[0]:u,t)===!1)return u+1}return u}return t.__iterateUncached(e,n)}function G(t,e,n,r){var i=t._cache;if(i){var o=i.length-1,u=0;return new E(function(){var t=i[n?o-u:u];return u++>o?b():I(e,r?t[0]:u-1,t[1])})}return t.__iteratorUncached(e,n)}function K(){throw TypeError("Abstract")}function Y(){}function B(){}function J(){}function W(t,e){if(t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if(t=t.valueOf(),e=e.valueOf(),t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1}return!("function"!=typeof t.equals||"function"!=typeof e.equals||!t.equals(e))}function X(t,e){return e?Q(e,t,"",{"":t}):Z(t)}function Q(t,e,n,r){return Array.isArray(e)?t.call(r,n,R(e).map((function(n,r){return Q(t,n,r,e)}))):$(e)?t.call(r,n,z(e).map((function(n,r){return Q(t,n,r,e)}))):e}function Z(t){return Array.isArray(t)?R(t).map(Z).toList():$(t)?z(t).map(Z).toMap():t}function $(t){return t&&(t.constructor===Object||void 0===t.constructor)}function tt(t){return t>>>1&1073741824|3221225471&t}function et(t){if(t===!1||null===t||void 0===t)return 0;if("function"==typeof t.valueOf&&(t=t.valueOf(),t===!1||null===t||void 0===t))return 0;if(t===!0)return 1;var e=typeof t;if("number"===e){var n=0|t;for(n!==t&&(n^=4294967295*t);t>4294967295;)t/=4294967295,n^=t;return tt(n)}return"string"===e?t.length>jn?nt(t):rt(t):"function"==typeof t.hashCode?t.hashCode():it(t)}function nt(t){var e=Un[t];return void 0===e&&(e=rt(t),kn===Nn&&(kn=0,Un={}),kn++,Un[t]=e),e}function rt(t){for(var e=0,n=0;n0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}function ut(t,e){if(!t)throw new Error(e)}function at(t){ut(t!==1/0,"Cannot perform this action with an infinite size.")}function st(t,e){this._iter=t,this._useKeys=e,this.size=t.size}function ct(t){this._iter=t,this.size=t.size}function ft(t){this._iter=t,this.size=t.size}function ht(t){this._iter=t,this.size=t.size}function lt(t){var e=Lt(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=jt,e.__iterateUncached=function(e,n){var r=this;return t.__iterate((function(t,n){return e(n,t,r)!==!1}),n)},e.__iteratorUncached=function(e,n){if(e===En){var r=t.__iterator(e,n);return new E(function(){var t=r.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t})}return t.__iterator(e===mn?gn:mn,n)},e}function pt(t,e,n){var r=Lt(t);return r.size=t.size,r.has=function(e){return t.has(e)},r.get=function(r,i){var o=t.get(r,ln);return o===ln?i:e.call(n,o,r,t)},r.__iterateUncached=function(r,i){var o=this;return t.__iterate((function(t,i,u){return r(e.call(n,t,i,u),i,o)!==!1}),i)},r.__iteratorUncached=function(r,i){var o=t.__iterator(En,i);return new E(function(){var i=o.next();if(i.done)return i;var u=i.value,a=u[0];return I(r,a,e.call(n,u[1],a,t),i)})},r}function _t(t,e){var n=Lt(t);return n._iter=t,n.size=t.size,n.reverse=function(){return t},t.flip&&(n.flip=function(){var e=lt(t);return e.reverse=function(){return t.flip()},e}),n.get=function(n,r){return t.get(e?n:-1-n,r)},n.has=function(n){return t.has(e?n:-1-n)},n.includes=function(e){return t.includes(e)},n.cacheResult=jt,n.__iterate=function(e,n){var r=this;return t.__iterate((function(t,n){return e(t,n,r)}),!n)},n.__iterator=function(e,n){return t.__iterator(e,!n)},n}function dt(t,e,n,r){var i=Lt(t);return r&&(i.has=function(r){var i=t.get(r,ln);return i!==ln&&!!e.call(n,i,r,t)},i.get=function(r,i){var o=t.get(r,ln);return o!==ln&&e.call(n,o,r,t)?o:i}),i.__iterateUncached=function(i,o){var u=this,a=0;return t.__iterate((function(t,o,s){if(e.call(n,t,o,s))return a++,i(t,r?o:a-1,u)}),o),a},i.__iteratorUncached=function(i,o){var u=t.__iterator(En,o),a=0;return new E(function(){for(;;){var o=u.next();if(o.done)return o;var s=o.value,c=s[0],f=s[1];if(e.call(n,f,c,t))return I(i,r?c:a++,f,o)}})},i}function vt(t,e,n){var r=Ut().asMutable();return t.__iterate((function(i,o){r.update(e.call(n,i,o,t),0,(function(t){return t+1}))})),r.asImmutable()}function yt(t,e,n){var r=y(t),i=(m(t)?be():Ut()).asMutable();t.__iterate((function(o,u){i.update(e.call(n,o,u,t),(function(t){return t=t||[],t.push(r?[u,o]:o),t}))}));var o=Mt(t);return i.map((function(e){return Ct(t,o(e))}))}function St(t,e,n,r){var i=t.size;if(void 0!==e&&(e=0|e),void 0!==n&&(n=0|n),s(e,n,i))return t;var o=c(e,i),a=f(n,i);if(o!==o||a!==a)return St(t.toSeq().cacheResult(),e,n,r);var h,l=a-o;l===l&&(h=l<0?0:l);var p=Lt(t);return p.size=0===h?h:t.size&&h||void 0,!r&&U(t)&&h>=0&&(p.get=function(e,n){return e=u(this,e),e>=0&&eh)return b();var t=i.next();return r||e===mn?t:e===gn?I(e,a-1,void 0,t):I(e,a-1,t.value[1],t)})},p}function gt(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterate(r,i);var u=0;return t.__iterate((function(t,i,a){return e.call(n,t,i,a)&&++u&&r(t,i,o)})),u},r.__iteratorUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterator(r,i);var u=t.__iterator(En,i),a=!0;return new E(function(){if(!a)return b();var t=u.next();if(t.done)return t;var i=t.value,s=i[0],c=i[1];return e.call(n,c,s,o)?r===En?t:I(r,s,c,t):(a=!1,b())})},r}function mt(t,e,n,r){var i=Lt(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var a=!0,s=0;return t.__iterate((function(t,o,c){if(!a||!(a=e.call(n,t,o,c)))return s++,i(t,r?o:s-1,u)})),s},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var a=t.__iterator(En,o),s=!0,c=0;return new E(function(){var t,o,f;do{if(t=a.next(),t.done)return r||i===mn?t:i===gn?I(i,c++,void 0,t):I(i,c++,t.value[1],t);var h=t.value;o=h[0],f=h[1],s&&(s=e.call(n,f,o,u))}while(s);return i===En?t:I(i,o,f,t)})},i}function Et(t,e){var n=y(t),r=[t].concat(e).map((function(t){return v(t)?n&&(t=p(t)):t=n?H(t):x(Array.isArray(t)?t:[t]),t})).filter((function(t){return 0!==t.size}));if(0===r.length)return t;if(1===r.length){var i=r[0];if(i===t||n&&y(i)||S(t)&&S(i))return i}var o=new L(r);return n?o=o.toKeyedSeq():S(t)||(o=o.toSetSeq()),o=o.flatten(!0),o.size=r.reduce((function(t,e){if(void 0!==t){var n=e.size;if(void 0!==n)return t+n}}),0),o}function It(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){function o(t,s){var c=this;t.__iterate((function(t,i){return(!e||s0}function Dt(t,e,n){var r=Lt(t);return r.size=new L(n).map((function(t){return t.size})).min(),r.__iterate=function(t,e){for(var n,r=this,i=this.__iterator(mn,e),o=0;!(n=i.next()).done&&t(n.value,o++,r)!==!1;);return o},r.__iteratorUncached=function(t,r){var i=n.map((function(t){return t=l(t),T(r?t.reverse():t)})),o=0,u=!1;return new E(function(){var n;return u||(n=i.map((function(t){ +return t.next()})),u=n.some((function(t){return t.done}))),u?b():I(t,o++,e.apply(null,n.map((function(t){return t.value}))))})},r}function Ct(t,e){return U(t)?e:t.constructor(e)}function zt(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function Rt(t){return at(t.size),o(t)}function Mt(t){return y(t)?p:S(t)?_:d}function Lt(t){return Object.create((y(t)?z:S(t)?R:M).prototype)}function jt(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):C.prototype.cacheResult.call(this)}function Nt(t,e){return t>e?1:t>>n)&hn,a=(0===n?r:r>>>n)&hn,s=u===a?[Zt(t,e,n+cn,r,i)]:(o=new Ft(e,r,i),u>>=1)u[a]=1&n?e[o++]:void 0;return u[r]=i,new Vt(t,o+1,u)}function ne(t,e,n){for(var r=[],i=0;i>1&1431655765,t=(858993459&t)+(t>>2&858993459),t=t+(t>>4)&252645135,t+=t>>8,t+=t>>16,127&t}function ae(t,e,n,r){var o=r?t:i(t);return o[e]=n,o}function se(t,e,n,r){var i=t.length+1;if(r&&e+1===i)return t[e]=n,t;for(var o=new Array(i),u=0,a=0;a0&&ro?0:o-n,c=u-n;return c>fn&&(c=fn),function(){if(i===c)return Bn;var t=e?--c:i++;return r&&r[t]}}function i(t,r,i){var a,s=t&&t.array,c=i>o?0:o-i>>r,f=(u-i>>r)+1;return f>fn&&(f=fn),function(){for(;;){if(a){var t=a();if(t!==Bn)return t;a=null}if(c===f)return Bn;var o=e?--f:c++;a=n(s&&s[o],r-cn,i+(o<=t.size||n<0)return t.withMutations((function(t){n<0?me(t,n).set(0,r):me(t,0,n+1).set(n,r)}));n+=t._origin;var i=t._tail,o=t._root,a=e(_n);return n>=Ie(t._capacity)?i=ye(i,t.__ownerID,0,n,r,a):o=ye(o,t.__ownerID,t._level,n,r,a),a.value?t.__ownerID?(t._root=o,t._tail=i,t.__hash=void 0,t.__altered=!0,t):_e(t._origin,t._capacity,t._level,o,i):t}function ye(t,e,r,i,o,u){var a=i>>>r&hn,s=t&&a0){var f=t&&t.array[a],h=ye(f,e,r-cn,i,o,u);return h===f?t:(c=Se(t,e),c.array[a]=h,c)}return s&&t.array[a]===o?t:(n(u),c=Se(t,e),void 0===o&&a===c.array.length-1?c.array.pop():c.array[a]=o,c)}function Se(t,e){return e&&t&&e===t.ownerID?t:new le(t?t.array.slice():[],e)}function ge(t,e){if(e>=Ie(t._capacity))return t._tail;if(e<1<0;)n=n.array[e>>>r&hn],r-=cn;return n}}function me(t,e,n){void 0!==e&&(e=0|e),void 0!==n&&(n=0|n);var i=t.__ownerID||new r,o=t._origin,u=t._capacity,a=o+e,s=void 0===n?u:n<0?u+n:o+n;if(a===o&&s===u)return t;if(a>=s)return t.clear();for(var c=t._level,f=t._root,h=0;a+h<0;)f=new le(f&&f.array.length?[void 0,f]:[],i),c+=cn,h+=1<=1<l?new le([],i):_;if(_&&p>l&&acn;y-=cn){var S=l>>>y&hn;v=v.array[S]=Se(v.array[S],i)}v.array[l>>>cn&hn]=_}if(s=p)a-=p,s-=p,c=cn,f=null,d=d&&d.removeBefore(i,0,a);else if(a>o||p>>c&hn;if(g!==p>>>c&hn)break;g&&(h+=(1<o&&(f=f.removeBefore(i,c,a-h)),f&&pi&&(i=a.size),v(u)||(a=a.map((function(t){return X(t)}))),r.push(a)}return i>t.size&&(t=t.setSize(i)),ie(t,e,r)}function Ie(t){return t>>cn<=fn&&u.size>=2*o.size?(i=u.filter((function(t,e){return void 0!==t&&a!==e})),r=i.toKeyedSeq().map((function(t){return t[0]})).flip().toMap(),t.__ownerID&&(r.__ownerID=i.__ownerID=t.__ownerID)):(r=o.remove(e),i=a===u.size-1?u.pop():u.set(a,void 0))}else if(s){if(n===u.get(a)[1])return t;r=o,i=u.set(a,[e,n])}else r=o.set(e,u.size),i=u.set(u.size,[e,n]);return t.__ownerID?(t.size=r.size,t._map=r,t._list=i,t.__hash=void 0,t):we(r,i)}function De(t){return null===t||void 0===t?Re():Ce(t)?t:Re().unshiftAll(t)}function Ce(t){return!(!t||!t[Wn])}function ze(t,e,n,r){var i=Object.create(Xn);return i.size=t,i._head=e,i.__ownerID=n,i.__hash=r,i.__altered=!1,i}function Re(){return Qn||(Qn=ze(0))}function Me(t){return null===t||void 0===t?ke():Le(t)&&!m(t)?t:ke().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Le(t){return!(!t||!t[Zn])}function je(t,e){return t.__ownerID?(t.size=e.size,t._map=e,t):e===t._map?t:0===e.size?t.__empty():t.__make(e)}function Ne(t,e){var n=Object.create($n);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function ke(){return tr||(tr=Ne(Jt()))}function Ue(t){return null===t||void 0===t?xe():Pe(t)?t:xe().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Pe(t){return Le(t)&&m(t)}function He(t,e){var n=Object.create(er);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function xe(){return nr||(nr=He(Te()))}function Ve(t,e){var n,r=function(o){if(o instanceof r)return o;if(!(this instanceof r))return new r(o);if(!n){n=!0;var u=Object.keys(t);Ge(i,u),i.size=u.length,i._name=e,i._keys=u,i._defaultValues=t}this._map=Ut(o)},i=r.prototype=Object.create(rr);return i.constructor=r,r}function qe(t,e,n){var r=Object.create(Object.getPrototypeOf(t));return r._map=e,r.__ownerID=n,r}function Fe(t){return t._name||t.constructor.name||"Record"}function Ge(t,e){try{e.forEach(Ke.bind(void 0,t))}catch(t){}}function Ke(t,e){Object.defineProperty(t,e,{get:function(){return this.get(e)},set:function(t){ut(this.__ownerID,"Cannot set on an immutable record."),this.set(e,t)}})}function Ye(t,e){if(t===e)return!0;if(!v(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||y(t)!==y(e)||S(t)!==S(e)||m(t)!==m(e))return!1;if(0===t.size&&0===e.size)return!0;var n=!g(t);if(m(t)){var r=t.entries();return e.every((function(t,e){var i=r.next().value;return i&&W(i[1],t)&&(n||W(i[0],e))}))&&r.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var o=t;t=e,e=o}var u=!0,a=e.__iterate((function(e,r){if(n?!t.has(e):i?!W(e,t.get(r,ln)):!W(t.get(r,ln),e))return u=!1,!1}));return u&&t.size===a}function Be(t,e,n){if(!(this instanceof Be))return new Be(t,e,n);if(ut(0!==n,"Cannot step a Range by 0"),t=t||0,void 0===e&&(e=1/0),n=void 0===n?1:Math.abs(n),ee?-1:0}function rn(t){if(t.size===1/0)return 0;var e=m(t),n=y(t),r=e?1:0,i=t.__iterate(n?e?function(t,e){r=31*r+un(et(t),et(e))|0}:function(t,e){r=r+un(et(t),et(e))|0}:e?function(t){r=31*r+et(t)|0}:function(t){r=r+et(t)|0});return on(i,r)}function on(t,e){return e=Dn(e,3432918353),e=Dn(e<<15|e>>>-15,461845907),e=Dn(e<<13|e>>>-13,5),e=(e+3864292196|0)^t,e=Dn(e^e>>>16,2246822507),e=Dn(e^e>>>13,3266489909),e=tt(e^e>>>16)}function un(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}var an=Array.prototype.slice,sn="delete",cn=5,fn=1<r?b():I(t,i,n[e?r-i++:i++])})},t(j,z),j.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},j.prototype.has=function(t){return this._object.hasOwnProperty(t)},j.prototype.__iterate=function(t,e){for(var n=this,r=this._object,i=this._keys,o=i.length-1,u=0;u<=o;u++){var a=i[e?o-u:u];if(t(r[a],a,n)===!1)return u+1}return u},j.prototype.__iterator=function(t,e){var n=this._object,r=this._keys,i=r.length-1,o=0;return new E(function(){var u=r[e?i-o:o];return o++>i?b():I(t,u,n[u])})},j.prototype[Sn]=!0,t(N,R),N.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);var r=this._iterable,i=T(r),o=0;if(w(i))for(var u;!(u=i.next()).done&&t(u.value,o++,n)!==!1;);return o},N.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var n=this._iterable,r=T(n);if(!w(r))return new E(b);var i=0;return new E(function(){var e=r.next();return e.done?e:I(t,i++,e.value)})},t(k,R),k.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);for(var r=this._iterator,i=this._iteratorCache,o=0;o=r.length){var e=n.next();if(e.done)return e;r[i]=e.value}return I(t,i,r[i++])})};var Tn;t(K,l),t(Y,K),t(B,K),t(J,K),K.Keyed=Y,K.Indexed=B,K.Set=J;var An,Dn="function"==typeof Math.imul&&Math.imul(4294967295,2)===-2?Math.imul:function(t,e){t=0|t,e=0|e;var n=65535&t,r=65535&e;return n*r+((t>>>16)*r+n*(e>>>16)<<16>>>0)|0},Cn=Object.isExtensible,zn=(function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}})(),Rn="function"==typeof WeakMap;Rn&&(An=new WeakMap);var Mn=0,Ln="__immutablehash__";"function"==typeof Symbol&&(Ln=Symbol(Ln));var jn=16,Nn=255,kn=0,Un={};t(st,z),st.prototype.get=function(t,e){return this._iter.get(t,e)},st.prototype.has=function(t){return this._iter.has(t)},st.prototype.valueSeq=function(){return this._iter.valueSeq()},st.prototype.reverse=function(){var t=this,e=_t(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},st.prototype.map=function(t,e){var n=this,r=pt(this,t,e);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(t,e)}),r},st.prototype.__iterate=function(t,e){var n,r=this;return this._iter.__iterate(this._useKeys?function(e,n){return t(e,n,r)}:(n=e?Rt(this):0,function(i){return t(i,e?--n:n++,r)}),e)},st.prototype.__iterator=function(t,e){if(this._useKeys)return this._iter.__iterator(t,e);var n=this._iter.__iterator(mn,e),r=e?Rt(this):0;return new E(function(){var i=n.next();return i.done?i:I(t,e?--r:r++,i.value,i)})},st.prototype[Sn]=!0,t(ct,R),ct.prototype.includes=function(t){return this._iter.includes(t)},ct.prototype.__iterate=function(t,e){var n=this,r=0;return this._iter.__iterate((function(e){return t(e,r++,n)}),e)},ct.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e),r=0;return new E(function(){var e=n.next();return e.done?e:I(t,r++,e.value,e)})},t(ft,M),ft.prototype.has=function(t){return this._iter.includes(t)},ft.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){return t(e,e,n)}),e)},ft.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e);return new E(function(){var e=n.next();return e.done?e:I(t,e.value,e.value,e)})},t(ht,z),ht.prototype.entrySeq=function(){return this._iter.toSeq()},ht.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){if(e){zt(e);var r=v(e);return t(r?e.get(1):e[1],r?e.get(0):e[0],n)}}),e)},ht.prototype.__iterator=function(t,e){var n=this._iter.__iterator(mn,e);return new E(function(){for(;;){var e=n.next();if(e.done)return e;var r=e.value;if(r){zt(r);var i=v(r);return I(t,i?r.get(0):r[0],i?r.get(1):r[1],e)}}})},ct.prototype.cacheResult=st.prototype.cacheResult=ft.prototype.cacheResult=ht.prototype.cacheResult=jt,t(Ut,Y),Ut.prototype.toString=function(){return this.__toString("Map {","}")},Ut.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},Ut.prototype.set=function(t,e){return Wt(this,t,e)},Ut.prototype.setIn=function(t,e){return this.updateIn(t,ln,(function(){return e}))},Ut.prototype.remove=function(t){return Wt(this,t,ln)},Ut.prototype.deleteIn=function(t){return this.updateIn(t,(function(){return ln}))},Ut.prototype.update=function(t,e,n){return 1===arguments.length?t(this):this.updateIn([t],e,n)},Ut.prototype.updateIn=function(t,e,n){n||(n=e,e=void 0);var r=oe(this,kt(t),e,n);return r===ln?void 0:r},Ut.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Jt()},Ut.prototype.merge=function(){return ne(this,void 0,arguments)},Ut.prototype.mergeWith=function(t){var e=an.call(arguments,1);return ne(this,t,e)},Ut.prototype.mergeIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]}))},Ut.prototype.mergeDeep=function(){return ne(this,re(void 0),arguments)},Ut.prototype.mergeDeepWith=function(t){var e=an.call(arguments,1);return ne(this,re(t),e)},Ut.prototype.mergeDeepIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]}))},Ut.prototype.sort=function(t){return be(wt(this,t))},Ut.prototype.sortBy=function(t,e){return be(wt(this,e,t))},Ut.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},Ut.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new r)},Ut.prototype.asImmutable=function(){return this.__ensureOwner()},Ut.prototype.wasAltered=function(){return this.__altered},Ut.prototype.__iterator=function(t,e){return new Gt(this,t,e)},Ut.prototype.__iterate=function(t,e){var n=this,r=0;return this._root&&this._root.iterate((function(e){return r++,t(e[1],e[0],n)}),e),r},Ut.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Bt(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Ut.isMap=Pt;var Pn="@@__IMMUTABLE_MAP__@@",Hn=Ut.prototype;Hn[Pn]=!0,Hn[sn]=Hn.remove,Hn.removeIn=Hn.deleteIn,Ht.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;o=Vn)return $t(t,f,o,u);var _=t&&t===this.ownerID,d=_?f:i(f);return p?c?h===l-1?d.pop():d[h]=d.pop():d[h]=[o,u]:d.push([o,u]),_?(this.entries=d,this):new Ht(t,d)}},xt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=1<<((0===t?e:e>>>t)&hn),o=this.bitmap;return 0===(o&i)?r:this.nodes[ue(o&i-1)].get(t+cn,e,n,r)},xt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=1<=qn)return ee(t,l,c,a,_);if(f&&!_&&2===l.length&&Qt(l[1^h]))return l[1^h];if(f&&_&&1===l.length&&Qt(_))return _;var d=t&&t===this.ownerID,v=f?_?c:c^s:c|s,y=f?_?ae(l,h,_,d):ce(l,h,d):se(l,h,_,d);return d?(this.bitmap=v,this.nodes=y,this):new xt(t,v,y)},Vt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=(0===t?e:e>>>t)&hn,o=this.nodes[i];return o?o.get(t+cn,e,n,r):r},Vt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=i===ln,c=this.nodes,f=c[a];if(s&&!f)return this;var h=Xt(f,t,e+cn,n,r,i,o,u);if(h===f)return this;var l=this.count;if(f){if(!h&&(l--,l=0&&t>>e&hn;if(r>=this.array.length)return new le([],t);var i,o=0===r;if(e>0){var u=this.array[r];if(i=u&&u.removeBefore(t,e-cn,n),i===u&&o)return this}if(o&&!i)return this;var a=Se(this,t);if(!o)for(var s=0;s>>e&hn;if(r>=this.array.length)return this;var i;if(e>0){var o=this.array[r];if(i=o&&o.removeAfter(t,e-cn,n),i===o&&r===this.array.length-1)return this}var u=Se(this,t);return u.array.splice(r+1),i&&(u.array[r]=i),u};var Yn,Bn={};t(be,Ut),be.of=function(){return this(arguments)},be.prototype.toString=function(){return this.__toString("OrderedMap {","}")},be.prototype.get=function(t,e){var n=this._map.get(t);return void 0!==n?this._list.get(n)[1]:e},be.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):Te()},be.prototype.set=function(t,e){return Ae(this,t,e)},be.prototype.remove=function(t){return Ae(this,t,ln)},be.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},be.prototype.__iterate=function(t,e){var n=this;return this._list.__iterate((function(e){return e&&t(e[1],e[0],n)}),e)},be.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},be.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),n=this._list.__ensureOwner(t);return t?we(e,n,t,this.__hash):(this.__ownerID=t,this._map=e,this._list=n,this)},be.isOrderedMap=Oe,be.prototype[Sn]=!0,be.prototype[sn]=be.prototype.remove;var Jn;t(De,B),De.of=function(){return this(arguments)},De.prototype.toString=function(){return this.__toString("Stack [","]")},De.prototype.get=function(t,e){var n=this._head;for(t=u(this,t);n&&t--;)n=n.next;return n?n.value:e},De.prototype.peek=function(){return this._head&&this._head.value},De.prototype.push=function(){var t=arguments;if(0===arguments.length)return this;for(var e=this.size+arguments.length,n=this._head,r=arguments.length-1;r>=0;r--)n={value:t[r],next:n};return this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pushAll=function(t){if(t=_(t),0===t.size)return this;at(t.size);var e=this.size,n=this._head;return t.reverse().forEach((function(t){e++,n={value:t,next:n}})),this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pop=function(){return this.slice(1)},De.prototype.unshift=function(){return this.push.apply(this,arguments)},De.prototype.unshiftAll=function(t){return this.pushAll(t)},De.prototype.shift=function(){return this.pop.apply(this,arguments)},De.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Re()},De.prototype.slice=function(t,e){if(s(t,e,this.size))return this;var n=c(t,this.size),r=f(e,this.size);if(r!==this.size)return B.prototype.slice.call(this,t,e);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):ze(i,o)},De.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?ze(this.size,this._head,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},De.prototype.__iterate=function(t,e){var n=this;if(e)return this.reverse().__iterate(t);for(var r=0,i=this._head;i&&t(i.value,r++,n)!==!1;)i=i.next;return r},De.prototype.__iterator=function(t,e){if(e)return this.reverse().__iterator(t);var n=0,r=this._head;return new E(function(){if(r){var e=r.value;return r=r.next,I(t,n++,e)}return b()})},De.isStack=Ce;var Wn="@@__IMMUTABLE_STACK__@@",Xn=De.prototype;Xn[Wn]=!0,Xn.withMutations=Hn.withMutations,Xn.asMutable=Hn.asMutable,Xn.asImmutable=Hn.asImmutable,Xn.wasAltered=Hn.wasAltered;var Qn;t(Me,J),Me.of=function(){return this(arguments)},Me.fromKeys=function(t){return this(p(t).keySeq())},Me.prototype.toString=function(){return this.__toString("Set {","}")},Me.prototype.has=function(t){return this._map.has(t)},Me.prototype.add=function(t){return je(this,this._map.set(t,!0))},Me.prototype.remove=function(t){return je(this,this._map.remove(t))},Me.prototype.clear=function(){return je(this,this._map.clear())},Me.prototype.union=function(){var t=an.call(arguments,0);return t=t.filter((function(t){return 0!==t.size})),0===t.length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations((function(e){for(var n=0;n1?" by "+this._step:"")+" ]"},Be.prototype.get=function(t,e){return this.has(t)?this._start+u(this,t)*this._step:e},Be.prototype.includes=function(t){var e=(t-this._start)/this._step;return e>=0&&e=0&&nn?b():I(t,o++,u)})},Be.prototype.equals=function(t){return t instanceof Be?this._start===t._start&&this._end===t._end&&this._step===t._step:Ye(this,t)};var ir;t(Je,R),Je.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Je.prototype.get=function(t,e){return this.has(t)?this._value:e},Je.prototype.includes=function(t){return W(this._value,t)},Je.prototype.slice=function(t,e){var n=this.size;return s(t,e,n)?this:new Je(this._value,f(e,n)-c(t,n))},Je.prototype.reverse=function(){return this},Je.prototype.indexOf=function(t){return W(this._value,t)?0:-1},Je.prototype.lastIndexOf=function(t){return W(this._value,t)?this.size:-1},Je.prototype.__iterate=function(t,e){for(var n=this,r=0;rthis.size?e:this.find((function(e,n){return n===t}),void 0,e)},has:function(t){return t=u(this,t),t>=0&&(void 0!==this.size?this.size===1/0||t-1&&t%1===0&&t<=Number.MAX_VALUE}var i=Function.prototype.bind;e.isString=function(t){return"string"==typeof t||"[object String]"===n(t)},e.isArray=Array.isArray||function(t){return"[object Array]"===n(t)},"function"!=typeof/./&&"object"!=typeof Int8Array?e.isFunction=function(t){return"function"==typeof t||!1}:e.isFunction=function(t){return"[object Function]"===toString.call(t)},e.isObject=function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},e.extend=function(t){var e=arguments,n=arguments.length;if(!t||n<2)return t||{};for(var r=1;r0)){var e=this.reactorState.get("dirtyStores");if(0!==e.size){var n=c.default.Set().withMutations((function(n){n.union(t.observerState.get("any")),e.forEach((function(e){var r=t.observerState.getIn(["stores",e]);r&&n.union(r)}))}));n.forEach((function(e){var n=t.observerState.getIn(["observersMap",e]);if(n){var r=n.get("getter"),i=n.get("handler"),o=p.evaluate(t.prevReactorState,r),u=p.evaluate(t.reactorState,r);t.prevReactorState=o.reactorState,t.reactorState=u.reactorState;var a=o.result,s=u.result;c.default.is(a,s)||i.call(null,s)}}));var r=p.resetDirtyStores(this.reactorState);this.prevReactorState=r,this.reactorState=r}}}},{key:"batchStart",value:function(){this.__batchDepth++}},{key:"batchEnd",value:function(){if(this.__batchDepth--,this.__batchDepth<=0){this.__isDispatching=!0;try{this.__notify()}catch(t){throw this.__isDispatching=!1,t}this.__isDispatching=!1}}}]),t})();e.default=(0,y.toFactory)(g),t.exports=e.default},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n={};return(0,o.each)(e,(function(e,r){n[r]=t.evaluate(e)})),n}Object.defineProperty(e,"__esModule",{value:!0});var o=n(4);e.default=function(t){return{getInitialState:function(){return i(t,this.getDataBindings())},componentDidMount:function(){var e=this;this.__unwatchFns=[],(0,o.each)(this.getDataBindings(),(function(n,i){var o=t.observe(n,(function(t){e.setState(r({},i,t))}));e.__unwatchFns.push(o)}))},componentWillUnmount:function(){for(var t=this;this.__unwatchFns.length;)t.__unwatchFns.shift()()}}},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t,e){return new M({result:t,reactorState:e})}function o(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.getIn(["stores",n])&&console.warn("Store already defined for id = "+n);var r=e.getInitialState();if(void 0===r&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store getInitialState() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(r))throw new Error("Store getInitialState() must return an immutable value, did you forget to call toImmutable");t.update("stores",(function(t){return t.set(n,e)})).update("state",(function(t){return t.set(n,r)})).update("dirtyStores",(function(t){return t.add(n)})).update("storeStates",(function(t){return b(t,[n])}))})),I(t)}))}function u(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.update("stores",(function(t){return t.set(n,e)}))}))}))}function a(t,e,n){if(void 0===e&&f(t,"throwOnUndefinedActionType"))throw new Error("`dispatch` cannot be called with an `undefined` action type.");var r=t.get("state"),i=t.get("dirtyStores"),o=r.withMutations((function(r){A.default.dispatchStart(t,e,n),t.get("stores").forEach((function(o,u){var a=r.get(u),s=void 0;try{s=o.handle(a,e,n)}catch(e){throw A.default.dispatchError(t,e.message),e}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var c="Store handler must return a value, did you forget a return statement";throw A.default.dispatchError(t,c),new Error(c)}r.set(u,s),a!==s&&(i=i.add(u))})),A.default.dispatchEnd(t,r,i)})),u=t.set("state",o).set("dirtyStores",i).update("storeStates",(function(t){return b(t,i)}));return I(u)}function s(t,e){var n=[],r=(0,D.toImmutable)({}).withMutations((function(r){(0,R.each)(e,(function(e,i){var o=t.getIn(["stores",i]);if(o){var u=o.deserialize(e);void 0!==u&&(r.set(i,u),n.push(i))}}))})),i=w.default.Set(n);return t.update("state",(function(t){return t.merge(r)})).update("dirtyStores",(function(t){return t.union(i)})).update("storeStates",(function(t){return b(t,n)}))}function c(t,e,n){var r=e;(0,z.isKeyPath)(e)&&(e=(0,C.fromKeyPath)(e));var i=t.get("nextId"),o=(0,C.getStoreDeps)(e),u=w.default.Map({id:i,storeDeps:o,getterKey:r,getter:e,handler:n}),a=void 0;return a=0===o.size?t.update("any",(function(t){return t.add(i)})):t.withMutations((function(t){o.forEach((function(e){var n=["stores",e];t.hasIn(n)||t.setIn(n,w.default.Set()),t.updateIn(["stores",e],(function(t){return t.add(i)}))}))})),a=a.set("nextId",i+1).setIn(["observersMap",i],u),{observerState:a,entry:u}}function f(t,e){var n=t.getIn(["options",e]);if(void 0===n)throw new Error("Invalid option: "+e);return n}function h(t,e,n){var r=t.get("observersMap").filter((function(t){var r=t.get("getterKey"),i=!n||t.get("handler")===n;return!!i&&((0,z.isKeyPath)(e)&&(0,z.isKeyPath)(r)?(0,z.isEqual)(e,r):e===r)}));return t.withMutations((function(t){r.forEach((function(e){return l(t,e)}))}))}function l(t,e){return t.withMutations((function(t){var n=e.get("id"),r=e.get("storeDeps");0===r.size?t.update("any",(function(t){return t.remove(n)})):r.forEach((function(e){t.updateIn(["stores",e],(function(t){return t?t.remove(n):t}))})),t.removeIn(["observersMap",n])}))}function p(t){var e=t.get("state");return t.withMutations((function(t){var n=t.get("stores"),r=n.keySeq().toJS();n.forEach((function(n,r){var i=e.get(r),o=n.handleReset(i);if(void 0===o&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store handleReset() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(o))throw new Error("Store reset state must be an immutable value, did you forget to call toImmutable");t.setIn(["state",r],o)})),t.update("storeStates",(function(t){return b(t,r)})),v(t)}))}function _(t,e){var n=t.get("state");if((0,z.isKeyPath)(e))return i(n.getIn(e),t);if(!(0,C.isGetter)(e))throw new Error("evaluate must be passed a keyPath or Getter");if(g(t,e))return i(E(t,e),t);var r=(0,C.getDeps)(e).map((function(e){return _(t,e).result})),o=(0,C.getComputeFn)(e).apply(null,r);return i(o,m(t,e,o))}function d(t){var e={};return t.get("stores").forEach((function(n,r){var i=t.getIn(["state",r]),o=n.serialize(i);void 0!==o&&(e[r]=o)})),e}function v(t){return t.set("dirtyStores",w.default.Set())}function y(t){return t}function S(t,e){var n=y(e);return t.getIn(["cache",n])}function g(t,e){var n=S(t,e);if(!n)return!1;var r=n.get("storeStates");return 0!==r.size&&r.every((function(e,n){return t.getIn(["storeStates",n])===e}))}function m(t,e,n){var r=y(e),i=t.get("dispatchId"),o=(0,C.getStoreDeps)(e),u=(0,D.toImmutable)({}).withMutations((function(e){o.forEach((function(n){var r=t.getIn(["storeStates",n]);e.set(n,r)}))}));return t.setIn(["cache",r],w.default.Map({value:n,storeStates:u,dispatchId:i}))}function E(t,e){var n=y(e);return t.getIn(["cache",n,"value"])}function I(t){return t.update("dispatchId",(function(t){return t+1}))}function b(t,e){return t.withMutations((function(t){e.forEach((function(e){var n=t.has(e)?t.get(e)+1:1;t.set(e,n)}))}))}Object.defineProperty(e,"__esModule",{value:!0}),e.registerStores=o,e.replaceStores=u,e.dispatch=a,e.loadState=s,e.addObserver=c,e.getOption=f,e.removeObserver=h,e.removeObserverByEntry=l,e.reset=p,e.evaluate=_,e.serialize=d,e.resetDirtyStores=v;var O=n(3),w=r(O),T=n(9),A=r(T),D=n(5),C=n(10),z=n(11),R=n(4),M=w.default.Record({result:null,reactorState:null})},function(t,e,n){var r=n(8);e.dispatchStart=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.groupCollapsed("Dispatch: %s",e),console.group("payload"),console.debug(n),console.groupEnd())},e.dispatchError=function(t,e){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.debug("Dispatch error: "+e),console.groupEnd())},e.dispatchEnd=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&((0,r.getOption)(t,"logDirtyStores")&&console.log("Stores updated:",n.toList().toJS()),(0,r.getOption)(t,"logAppState")&&console.debug("Dispatch done, new state: ",e.toJS()),console.groupEnd())}},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,l.isArray)(t)&&(0,l.isFunction)(t[t.length-1])}function o(t){return t[t.length-1]}function u(t){return t.slice(0,t.length-1)}function a(t,e){e||(e=h.default.Set());var n=h.default.Set().withMutations((function(e){if(!i(t))throw new Error("getFlattenedDeps must be passed a Getter");u(t).forEach((function(t){if((0,p.isKeyPath)(t))e.add((0,f.List)(t));else{if(!i(t))throw new Error("Invalid getter, each dependency must be a KeyPath or Getter");e.union(a(t))}}))}));return e.union(n)}function s(t){if(!(0,p.isKeyPath)(t))throw new Error("Cannot create Getter from KeyPath: "+t);return[t,_]}function c(t){if(t.hasOwnProperty("__storeDeps"))return t.__storeDeps;var e=a(t).map((function(t){return t.first()})).filter((function(t){return!!t}));return Object.defineProperty(t,"__storeDeps",{enumerable:!1,configurable:!1,writable:!1,value:e}),e}Object.defineProperty(e,"__esModule",{value:!0});var f=n(3),h=r(f),l=n(4),p=n(11),_=function(t){return t};e.default={isGetter:i,getComputeFn:o,getFlattenedDeps:a,getStoreDeps:c,getDeps:u,fromKeyPath:s},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,s.isArray)(t)&&!(0,s.isFunction)(t[t.length-1])}function o(t,e){var n=a.default.List(t),r=a.default.List(e);return a.default.is(n,r)}Object.defineProperty(e,"__esModule",{value:!0}),e.isKeyPath=i,e.isEqual=o;var u=n(3),a=r(u),s=n(4)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=(0,r.Map)({logDispatches:!1,logAppState:!1,logDirtyStores:!1,throwOnUndefinedActionType:!1,throwOnUndefinedStoreReturnValue:!1,throwOnNonImmutableStore:!1,throwOnDispatchInDispatch:!1});e.PROD_OPTIONS=i;var o=(0,r.Map)({logDispatches:!0,logAppState:!0,logDirtyStores:!0,throwOnUndefinedActionType:!0,throwOnUndefinedStoreReturnValue:!0,throwOnNonImmutableStore:!0,throwOnDispatchInDispatch:!0});e.DEBUG_OPTIONS=o;var u=(0,r.Record)({dispatchId:0,state:(0,r.Map)(),stores:(0,r.Map)(),cache:(0,r.Map)(),storeStates:(0,r.Map)(),dirtyStores:(0,r.Set)(),debug:!1,options:i});e.ReactorState=u;var a=(0,r.Record)({any:(0,r.Set)(),stores:(0,r.Map)({}),observersMap:(0,r.Map)({}),nextId:1});e.ObserverState=a}])}))})),ze=t(Ce),Re=function(t){var e,n={};if(!(t instanceof Object)||Array.isArray(t))throw new Error("keyMirror(...): Argument must be an object.");for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n},Me=Re,Le=Me({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),je=ze.Store,Ne=ze.toImmutable,ke=new je({getInitialState:function(){return Ne({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Le.VALIDATING_AUTH_TOKEN,n),this.on(Le.VALID_AUTH_TOKEN,r),this.on(Le.INVALID_AUTH_TOKEN,i)}}),Ue=ze.Store,Pe=ze.toImmutable,He=new Ue({getInitialState:function(){return Pe({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),xe=ze.Store,Ve=new xe({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),qe=Me({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),Fe="object"==typeof window&&"EventSource"in window,Ge=ze.Store,Ke=ze.toImmutable,Ye=new Ge({getInitialState:function(){return Ke({isSupported:Fe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(qe.STREAM_START,s),this.on(qe.STREAM_STOP,c),this.on(qe.STREAM_ERROR,f),this.on(qe.LOG_OUT,h)}}),Be=Me({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Je=ze.Store,We=new Je({getInitialState:function(){return!0},initialize:function(){this.on(Be.API_FETCH_ALL_START,(function(){return!0})),this.on(Be.API_FETCH_ALL_SUCCESS,(function(){return!1})),this.on(Be.API_FETCH_ALL_FAIL,(function(){return!1})),this.on(Be.LOG_OUT,(function(){return!1}))}}),Xe=ze.Store,Qe=new Xe({getInitialState:function(){return!1},initialize:function(){this.on(Be.SYNC_SCHEDULED,(function(){return!0})),this.on(Be.SYNC_SCHEDULE_CANCELLED,(function(){return!1})),this.on(Be.LOG_OUT,(function(){return!1}))}}),Ze=Me({API_FETCH_SUCCESS:null,API_FETCH_START:null,API_FETCH_FAIL:null,API_SAVE_SUCCESS:null,API_SAVE_START:null,API_SAVE_FAIL:null,API_DELETE_SUCCESS:null,API_DELETE_START:null,API_DELETE_FAIL:null,LOG_OUT:null}),$e=ze.Store,tn=ze.toImmutable,en=new $e({getInitialState:function(){return tn({})},initialize:function(){var t=this;this.on(Ze.API_FETCH_SUCCESS,l),this.on(Ze.API_SAVE_SUCCESS,l),this.on(Ze.API_DELETE_SUCCESS,p),this.on(Ze.LOG_OUT,(function(){return t.getInitialState()}))}}),nn=Object.prototype.hasOwnProperty,rn=Object.prototype.propertyIsEnumerable,on=d()?Object.assign:function(t,e){for(var n,r,i=arguments,o=_(t),u=1;u \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/frontend.html.gz b/homeassistant/components/frontend/www_static/frontend.html.gz index 3f49436d6c0..ac7a962c713 100644 Binary files a/homeassistant/components/frontend/www_static/frontend.html.gz and b/homeassistant/components/frontend/www_static/frontend.html.gz differ diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 0a4454c68f3..db109f5dda0 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 0a4454c68f3c29c77cd60f4315d410d8b3737543 +Subproject commit db109f5dda043182a7e9647b161851e83be9b91e diff --git a/homeassistant/components/frontend/www_static/mdi.html b/homeassistant/components/frontend/www_static/mdi.html index 0f1aa609e46..e9f69984a47 100644 --- a/homeassistant/components/frontend/www_static/mdi.html +++ b/homeassistant/components/frontend/www_static/mdi.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/mdi.html.gz b/homeassistant/components/frontend/www_static/mdi.html.gz index 2be36b99edb..e219e5bcd45 100644 Binary files a/homeassistant/components/frontend/www_static/mdi.html.gz and b/homeassistant/components/frontend/www_static/mdi.html.gz differ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html index 6babc87e2ef..b0ed61ad6df 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html.gz index 09b6fecfc09..6f30190703e 100644 Binary files a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html.gz and b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html.gz differ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html index e255ca2f83d..83a2738e422 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html @@ -1,2 +1,2 @@ \ No newline at end of file + clear: both;white-space:pre-wrap}
About


Home Assistant
[[hassVersion]]

Path to configuration.yaml: [[hassConfigDir]]

Developed by a bunch of awesome people.

Published under the MIT license
Source: serverfrontend-uifrontend-core

Built using Python 3, Polymer [[polymerVersion]], NuclearJS [[nuclearVersion]]
Icons by Google and MaterialDesignIcons.com.

The following errors have been logged this session:

[[errorLog]]
\ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html.gz index aa8a5cc8517..280bf68a9a1 100644 Binary files a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html.gz and b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-info.html.gz differ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html index bd1998a7949..4725aa4a729 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz index 0683f460f7d..cdfed733269 100644 Binary files a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz and b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz differ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html index 90a36bccc6a..d6f91e28853 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html.gz index e40d047db48..d397aee1a1e 100644 Binary files a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html.gz and b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html.gz differ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html index b9aba112b63..0b665c3b983 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html @@ -1,2 +1,2 @@ -